
HATEOAS(헤이티오스)는 Hypermedia As The Engine Of Application State의 약자입니다. 이는 REST 아키텍처 스타일의 성숙도 모델에서 가장 높은 단계(레벨 3)를 만족시키는 핵심 요소 중 하나이며, 클라이언트가 서버와의 동적인 상호작용을 가능하게 하는 메커니즘을 의미합니다.
1. HATEOAS의 정의 및 목표
- 정의: 서버가 클라이언트에게 제공하는 응답에 하이퍼미디어(Hypermedia) 링크를 포함시키는 것입니다.
- 목표: 클라이언트가 API의 엔드포인트와 작업을 미리 하드코딩하여 알 필요 없이, 응답으로 받은 링크를 따라가며 다음에 수행할 수 있는 작업(상태 전이)을 동적으로 식별하고 수행할 수 있도록 합니다.
쉽게 말해, 웹 브라우저에서 HTML 페이지를 열면 텍스트와 이미지 외에도 다른 페이지로 이동할 수 있는 링크들이 있는 것과 유사합니다. API 응답 데이터 안에 다음에 할 수 있는 행동에 대한 '링크'를 제공하는 것입니다.
2. 작동 방식 (예시)

전통적인 REST API와 HATEOAS가 적용된 API의 응답 비교를 통해 이해할 수 있습니다.
| 구분 | 전통적인 REST API 응답 (JSON 예시) | HATEOAS 적용 응답 (HAL JSON 예시) |
| 계좌 정보 조회 | json { "accountNumber": "12345", "balance": 100000 } | json { "accountNumber": "12345", "balance": 100000, "_links": { "self": { "href": "/accounts/12345" }, "deposit": { "href": "/accounts/12345/deposits" }, "withdraw": { "href": "/accounts/12345/withdrawals" } } } |
- 전통적 방식: 클라이언트는 계좌 정보를 확인한 후, 입금이나 출금을 하려면 해당 기능을 수행하는 URI(GET /accounts/12345/deposits, POST /accounts/12345/withdrawals 등)를 미리 알고 있어야 합니다.
- HATEOAS 방식: 클라이언트는 응답의 _links 섹션을 보고 현재 상태에서 입금(deposit) 및 출금(withdraw) 작업이 가능하며, 각각 어떤 URI로 요청해야 하는지를 동적으로 알게 됩니다.
3. HATEOAS의 주요 장점

- 클라이언트와 서버 간의 느슨한 결합:
- 서버가 API 엔드포인트(URI)를 변경하더라도, 클라이언트는 응답에서 제공되는 href 값만 사용하기 때문에 클라이언트 코드를 수정할 필요가 없습니다. 클라이언트는 오직 rel 이름(관계 이름, 예: deposit, withdraw)에만 의존합니다.
- 자기 기술 문서화 (Self-descriptive Documentation):
- API 응답 자체에 다음 가능한 작업이 포함되어 있으므로, 클라이언트 개발자는 별도의 API 문서를 찾아보지 않아도 리소스 상태에 따른 애플리케이션의 흐름을 파악하기 쉽습니다.
- 동적인 상호작용:
- 서버는 리소스의 현재 상태(예: 계좌 잔액이 0이면 '출금' 링크를 제공하지 않음)에 따라 클라이언트에게 제공할 링크를 동적으로 변경할 수 있습니다. 이를 통해 클라이언트가 애플리케이션의 상태를 동적으로 전이시킬 수 있습니다.
4. HATEOAS의 고려 사항 및 단점
- 구현의 복잡성:
- 단순한 CRUD API를 넘어 HATEOAS를 도입하면, 응답에 링크를 생성하고 관리하는 로직이 추가되어 서버 측 구현이 복잡해질 수 있습니다. Spring 환경에서는 Spring HATEOAS와 같은 라이브러리를 사용해 이 복잡성을 줄이기도 합니다.
- 오버헤드 (네트워크 부담):
- 매 응답마다 데이터 외에 링크 정보가 추가되어 데이터 전송량이 늘어날 수 있습니다.
- 추가 호출 필요성:
- 때로는 특정 작업을 수행하기 위해 첫 번째 호출에서 링크 정보를 받은 후, 두 번째 호출에서 실제 작업을 수행해야 하므로, 네트워크 호출 횟수가 늘어날 수 있습니다.
5. HAL (Hypertext Application Language)
HATEOAS를 구현하기 위한 방법 중 가장 널리 사용되는 것이 HAL(Hypertext Application Language)입니다. HAL은 JSON 또는 XML 코드 내에 외부 리소스에 대한 링크를 추가하기 위한 간단하고 표준화된 데이터 타입입니다.
- HAL은 주로 _links 필드와 _embedded 필드를 사용하여 하이퍼미디어를 표현합니다.
- _links: 현재 리소스와 관련된 다른 리소스에 대한 링크를 담습니다. (필수적으로 자신을 가리키는 self 링크 포함)
- _embedded: 다른 리소스를 포함하여 반환할 때 사용됩니다.
HATEOAS는 진정한 의미의 RESTful API를 구현하기 위한 핵심 요소로 간주되지만, 프로젝트의 복잡성, 클라이언트의 특성 등을 고려하여 적용 여부를 결정하는 것이 중요합니다.
HATEOAS를 적용한 구체적인 API 예시를 보여드리겠습니다.
이 예시에서는 HAL(Hypertext Application Language) 표준을 사용하여 고객(Customer) 리소스를 조회하고, 그 상태에 따라 다음 가능한 작업을 링크로 제공하는 시나리오를 가정합니다.
💡 HATEOAS API 구체적인 예시 (HAL JSON)
1. 고객 리소스 조회 (GET /customers/101)
클라이언트가 고객 ID 101번의 정보를 요청했을 때 서버가 반환하는 응답입니다.
{
"id": 101,
"firstName": "김",
"lastName": "민수",
"email": "minsu.kim@example.com",
"_links": {
"self": {
"href": "/customers/101",
"title": "현재 고객 정보"
},
"orders": {
"href": "/customers/101/orders",
"title": "이 고객의 주문 목록 보기"
},
"update": {
"href": "/customers/101",
"method": "PUT",
"title": "고객 정보 수정"
},
"delete": {
"href": "/customers/101",
"method": "DELETE",
"title": "고객 정보 삭제"
}
}
}
- 클라이언트의 역할: 클라이언트는 이 응답을 받은 후, 고객 정보 수정(PUT), 고객 정보 삭제(DELETE), 주문 목록 조회(GET) 등의 작업을 위해 URI를 미리 알 필요 없이 _links 섹션에 있는 update, delete, orders 관계 이름(rel)을 보고 동적으로 다음 행동을 결정할 수 있습니다.
2. 주문 목록 조회 (GET /customers/101/orders)
클라이언트가 위에서 받은 orders 링크를 따라가 주문 목록을 요청했을 때의 응답입니다. HATEOAS에서는 컬렉션(목록) 응답에서도 각 항목에 대한 링크와 전체 목록에 대한 탐색 링크를 제공합니다.
{
"_links": {
"self": {
"href": "/customers/101/orders"
},
"customer": {
"href": "/customers/101",
"title": "고객 정보로 돌아가기"
},
"next": {
"href": "/customers/101/orders?page=2",
"title": "다음 페이지"
}
},
"_embedded": {
"orderList": [
{
"orderId": "ORD-001",
"orderDate": "2025-10-20",
"status": "배송 중",
"_links": {
"self": {
"href": "/orders/ORD-001"
},
"cancel": {
"href": "/orders/ORD-001/cancellation",
"method": "POST",
"title": "주문 취소하기"
}
}
},
{
"orderId": "ORD-002",
"orderDate": "2025-10-25",
"status": "배송 완료",
"_links": {
"self": {
"href": "/orders/ORD-002"
},
"review": {
"href": "/orders/ORD-002/reviews",
"method": "POST",
"title": "후기 작성"
}
}
}
]
}
}
- 동적인 상태 전이의 예시:
- ORD-001은 '배송 중' 상태이므로 취소(cancel) 링크가 제공됩니다.
- ORD-002는 '배송 완료' 상태이므로 취소 링크는 없고, 대신 후기 작성(review) 링크가 제공됩니다.
서버는 이처럼 리소스의 현재 상태에 따라 클라이언트가 수행할 수 있는 논리적 작업(상태 전이)을 동적으로 제어하며, 클라이언트는 이 링크들을 통해 다음 단계로 이동합니다.
3. HATEOAS의 핵심 가치 요약
| 개념 | 설명 | 응답 예시에서의 역할 |
| 리소스 (Resource) | 서버가 제공하는 데이터 자체. | id, firstName, email 등의 실제 고객 데이터. |
| 링크 (Link) | 리소스가 취할 수 있는 다음 상태나 관련 리소스로의 연결 정보. | _links 객체 안에 있는 각 항목 (예: orders, update). |
| 관계 이름 (Rel) | 링크의 목적을 설명하는 이름. 클라이언트가 의존해야 하는 핵심 식별자. | self, orders, cancel, review 등. |
| URI (Href) | 실제로 요청을 보낼 웹 주소. 클라이언트가 신경 쓰지 않아야 하는 부분. | /customers/101, /orders/ORD-001/cancellation 등. |
HATEOAS를 통해 클라이언트와 서버가 '계약'하는 것은 URI가 아니라, 관계 이름(rel) 입니다. 서버는 rel만 유지하면 href를 자유롭게 변경할 수 있습니다.
'IT 일반,소식' 카테고리의 다른 글
| 📝 YAML의 꽃, 앵커(&)와 별칭(*)로 설정 파일 중복 제거하기 (0) | 2025.12.10 |
|---|---|
| 📝 AI의 영원한 굴레: 완벽함이라는 허상과 베타 버전의 운명 (0) | 2025.12.10 |
| 🚢 부산항 9부두 지능형 항만 시스템 개발 계획 (MySQL, Nuxt.js, Nest.js 기반) (1) | 2025.12.07 |
| 🏢 빌딩 엘리베이터 시뮬레이션 개발계획(MySQL, Nuxt.js, Nest.js 기반) (0) | 2025.12.07 |
| NestJS + NuxtJS로 실시간 서버 헬스 모니터링 대시보드 만들기 (WebSocket 기반) (0) | 2025.12.05 |