IT 일반,소식

🔗 HATEOAS (Hypermedia As The Engine Of Application State) 상세 설명

_Blue_Sky_ 2025. 12. 10. 17:31
728x90

 

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를 자유롭게 변경할 수 있습니다.

 


 

728x90