하이퍼미디어 RESTful API 안내서

하이퍼미디어 RESTful API 안내서

1. REST 아키텍처 스타일의 재정의

오늘날 업계에서 통용되는 ’REST API’라는 용어는 대부분 HTTP 프로토콜 위에 JSON 페이로드를 전송하는 웹 API를 지칭하는 데 사용된다. 그러나 이러한 통념은 Roy Fielding이 그의 박사 학위 논문에서 제시한 REST(Representational State Transfer)의 근본적인 목표와 철학을 상당 부분 간과하고 있다.1 REST는 특정 기술 구현이나 프로토콜에 대한 명세가 아니라, 월드 와이드 웹(World Wide Web)과 같은 인터넷 규모의 분산 하이퍼미디어 시스템(distributed hypermedia system)을 위한 아키텍처 스타일(architectural style)로 탄생했다.1

REST 아키텍처의 핵심 목표는 시스템을 구성하는 컴포넌트들의 독립적인 배포(independent deployment)를 보장하고, 컴포넌트 간 상호작용의 확장성(scalability)을 극대화하며, 궁극적으로는 수십 년에 걸쳐 시스템이 독립적으로 진화(independent evolution)할 수 있는 기반을 마련하는 것이다.1 Fielding은 이러한 장기적인 목표를 달성하기 위한 필수 불가결한 요소로 ’하이퍼미디어(Hypermedia)’를 지목했으며, 이는 HATEOAS(Hypermedia as the Engine of Application State)라는 제약 조건으로 구체화되었다.

현대의 많은 API 개발 관행은 단기적인 개발 생산성과 효율성을 우선시하는 경향이 있다. Swagger나 OpenAPI Specification과 같은 도구를 사용하여 API의 엔드포인트, 요청 및 응답 구조를 사전에 명확하게 정의하고, 클라이언트는 이 ’대역 외 정보(out-of-band information)’에 기반하여 서버와 상호작용하는 로직을 하드코딩한다.4 이러한 접근 방식은 개발 초기 단계에서 명확하고 예측 가능한 인터페이스를 제공하여 개발 속도를 높이는 장점이 있다. 그러나 이는 클라이언트와 서버 간의 강한 결합(tight coupling)을 초래한다. 서버의 URI 구조가 변경되거나, 특정 리소스의 상태에 따라 가능한 작업이 달라지는 비즈니스 로직이 추가될 경우, 클라이언트는 필연적으로 코드 수정을 강제받게 된다.5 이는 REST의 핵심 목표인 ’독립적 진화’를 정면으로 저해하는 결과로 이어진다.2

Fielding이 지적했듯이, REST의 많은 제약 조건은 “단기적인 효율성과 직접적으로 반대된다”.3 이는 장기적인 시스템의 유연성, 유지보수성, 그리고 생존 가능성을 위해 단기적인 편의성을 기꺼이 희생하겠다는 설계 철학의 발현이다. 따라서 HATEOAS 제약 조건을 충족하지 못하는 API는 기술적으로 ‘진정한 RESTful’ 아키텍처 스타일을 따르고 있다고 보기 어렵다.

본 안내서는 이러한 문제의식에서 출발하여, REST 아키텍처의 근본 원칙을 재조명하고 하이퍼미디어가 그 중심에 있는 이유를 심층적으로 탐구하고자 한다. REST의 여섯 가지 제약 조건을 상세히 분석하고, 그중에서도 가장 핵심적인 ’Uniform Interface’와 HATEOAS의 원리를 파헤친다. 나아가 JSON 환경에서 하이퍼미디어를 구현하기 위한 주요 포맷들을 비교 분석하고, 실제 설계에 적용할 수 있는 모범 사례를 제시한다. 최종적으로는 하이퍼미디어 API 도입에 따르는 전략적 장단점을 고찰함으로써, 미래지향적 API 아키텍처를 구축하고자 하는 개발자와 아키텍트에게 깊이 있는 통찰을 제공하는 것을 목표로 한다.

2. REST의 제약 조건: 독립적 진화를 위한 여섯 기둥

REST 아키텍처 스타일은 시스템 전체에 바람직한 비기능적 속성들, 예를 들어 성능, 확장성, 단순성, 수정 가능성, 가시성, 이식성, 신뢰성 등을 부여하기 위해 여섯 가지의 핵심적인 제약 조건(guiding constraints)을 정의한다.1 이 제약 조건들은 개별적으로 작용하는 것이 아니라, 유기적으로 결합하여 REST의 근본 목표인 ’독립적 진화’를 가능하게 하는 아키텍처의 기둥 역할을 수행한다.

2.1 Client-Server (클라이언트-서버 구조)

클라이언트-서버 제약 조건의 핵심 원리는 ’관심사의 분리(separation of concerns)’이다.7 이는 사용자 인터페이스(UI)에 대한 관심사(클라이언트)와 데이터 저장 및 비즈니스 로직에 대한 관심사(서버)를 명확하게 분리하는 것을 의미한다. 클라이언트는 서버의 내부 데이터 저장 방식이나 구현 기술을 알 필요가 없으며, 서버는 클라이언트의 UI 상태나 사용자 경험에 대해 관여하지 않는다. 이 분리를 통해 클라이언트와 서버는 서로 독립적으로 개발, 배포, 확장될 수 있다.7 예를 들어, 서버 컴포넌트의 교체나 업그레이드가 여러 플랫폼(웹, 모바일 등)의 클라이언트에 영향을 주지 않으며, 반대로 새로운 플랫폼을 위한 클라이언트를 개발할 때도 서버의 변경이 필요 없다. 이러한 독립성은 인터넷 규모의 분산 시스템에서 다양한 조직과 기술 스택이 공존하기 위한 필수 요건이다.7

2.2 Stateless (무상태성)

Stateless 제약 조건은 클라이언트-서버 간의 통신에서 서버가 요청과 요청 사이에 어떠한 클라이언트 컨텍스트(세션 상태)도 저장해서는 안 된다는 것을 의미한다.7 각 요청은 서버가 해당 요청을 이해하고 처리하는 데 필요한 모든 정보를 자체적으로 포함해야 한다.8 예를 들어, 인증이 필요한 요청이라면 매 요청마다 API 키나 토큰과 같은 인증 정보를 포함해야 한다. 이전 요청의 내용이 다음 요청의 처리에 영향을 주어서는 안 된다. 세션 상태 관리에 대한 책임은 전적으로 클라이언트에 있다.7

이러한 무상태성은 여러 가지 중요한 이점을 제공한다. 첫째, 서버의 복잡성을 크게 낮춘다. 서버는 클라이언트의 상태를 추적하고 동기화하기 위한 복잡한 로직을 가질 필요가 없으므로, 각 요청을 독립적으로 처리하는 데만 집중할 수 있다.9 둘째, 서버의 확장성(scalability)을 극대화한다. 특정 클라이언트의 세션 정보에 종속되지 않기 때문에, 로드 밸런서 뒤의 어떤 서버 인스턴스라도 동일한 요청을 처리할 수 있다.9 셋째, 신뢰성(reliability)을 향상시킨다. 특정 서버에 장애가 발생하더라도 다른 서버가 요청을 이어받아 처리할 수 있으며, 하나의 요청 실패가 다른 요청에 영향을 미치지 않는다.8 마지막으로, 가시성(visibility)을 높인다. 각 요청이 완전한 정보를 담고 있으므로, 중간 계층의 모니터링 시스템이 요청을 파악하기 용이하다.

2.3 Cacheable (캐시 가능성)

웹의 성능과 확장성을 지탱하는 핵심 메커니즘 중 하나는 캐싱이다. Cacheable 제약 조건은 REST API의 응답이 스스로 캐시 가능한지(cacheable) 아닌지(non-cacheable)를 명시적으로 또는 암시적으로 정의해야 함을 요구한다.7 클라이언트나 프록시 서버와 같은 중간 계층은 캐시 가능한 응답을 재사용함으로써, 동일한 요청에 대해 서버까지 불필요한 네트워크 트래픽을 발생시키지 않을 수 있다. 잘 관리된 캐싱은 클라이언트-서버 간의 상호작용을 부분적으로 또는 완전히 제거하여 사용자 인지 성능(user-perceived performance)을 향상시키고, 서버의 부하를 줄여 시스템 전체의 확장성을 개선한다.7 HTTP 프로토콜은Cache-Control, Expires, ETag 등의 헤더를 통해 정교한 캐싱 전략을 지원하며, RESTful API는 이러한 표준 메커니즘을 적극적으로 활용해야 한다.

2.4 Layered System (계층형 시스템)

Layered System 제약 조건은 시스템이 계층적인 구조로 구성될 수 있으며, 각 컴포넌트는 자신이 상호작용하는 바로 인접한 계층 너머를 볼 수 없도록 제한한다.8 즉, 클라이언트는 자신이 최종 서버(end server)에 직접 연결되었는지, 아니면 중간에 프록시, 게이트웨이, 로드 밸런서와 같은 중개 서버(intermediary server)를 거치고 있는지 알 수 없으며, 알 필요도 없다.7

이러한 아키텍처는 여러 가지 이점을 제공한다. 첫째, 시스템 확장성을 향상시킨다. 로드 밸런서를 추가하여 여러 서버에 요청을 분산시키거나, 공유 캐시를 두어 성능을 개선하는 등의 작업이 클라이언트나 최종 서버의 코드 변경 없이 가능하다.7 둘째, 보안을 강화한다. 보안 정책을 별도의 계층(예: API 게이트웨이)에서 강제함으로써 비즈니스 로직과 보안 로직을 명확히 분리할 수 있다.7 셋째, 레거시 시스템을 캡슐화하고 현대적인 인터페이스를 제공하는 데 유용하다. 클라이언트는 최신 API와 통신하지만, 중간 계층이 이를 레거시 시스템이 이해할 수 있는 형태로 변환해 줄 수 있다.

2.5 Code on Demand (코드 온디맨드, 선택 사항)

Code on Demand는 REST의 여섯 가지 제약 조건 중 유일하게 선택 사항(optional)이다.10 이 제약 조건은 서버가 클라이언트의 기능을 일시적으로 확장하거나 커스터마이징하기 위해 실행 가능한 코드(예: JavaScript 애플릿이나 스크립트)를 클라이언트로 전송할 수 있음을 허용한다.7 예를 들어, 웹 브라우저가 서버로부터 HTML 문서와 함께 JavaScript 코드를 다운로드하여 실행함으로써 동적인 사용자 인터페이스를 렌더링하는 것이 대표적인 사례이다. 이를 통해 클라이언트는 사전에 모든 기능을 구현할 필요 없이, 서버가 제공하는 로직에 따라 동작을 동적으로 변경할 수 있다. 하지만 모든 시스템에 이 제약 조건이 필요한 것은 아니므로 선택적으로 적용할 수 있다.

2.6 Uniform Interface (일관된 인터페이스)

Uniform Interface는 REST 아키텍처 스타일을 다른 스타일(예: RPC)과 구별하는 가장 근본적이고 중요한 제약 조건이다.9 이는 시스템의 모든 컴포넌트가 자원에 접근하기 위해 일관된, 단일한 인터페이스를 사용하도록 강제하는 것을 의미한다. 이 제약 조건을 통해 시스템 아키텍처가 단순화되고, 상호작용의 가시성이 향상되며, 무엇보다도 컴포넌트들의 독립적인 진화가 가능해진다.1 클라이언트와 서버는 이 일관된 인터페이스라는 ’계약’을 통해 상호작용하므로, 각자의 내부 구현이 변경되더라도 인터페이스만 준수한다면 시스템 전체는 안정적으로 동작할 수 있다. 이 제약 조건은 네 가지 하위 제약 조건으로 구성되며, 다음 장에서 심층적으로 다룬다.

이상의 여섯 가지 제약 조건은 RESTful 시스템이 장기적인 관점에서 변화에 유연하게 대응하고 지속적으로 성장할 수 있도록 설계된 아키텍처 원칙들의 집합이다.

제약 조건 (Constraint)핵심 원칙 (Core Principle)시스템에 미치는 영향 (Impact on System Properties)
Client-Server관심사의 분리이식성(Portability), 확장성(Scalability), 독립적 진화
Stateless각 요청은 독립적이며, 상태는 클라이언트가 관리확장성, 신뢰성(Reliability), 가시성(Visibility)
Cacheable응답은 캐시 가능 여부를 명시성능(Performance), 효율성(Efficiency), 확장성
Layered System계층 간 상호작용은 인접 계층으로 제한확장성, 보안(Security), 수정 용이성(Modifiability)
Code on Demand (Optional)서버가 클라이언트에 실행 코드를 전송 가능확장성(Extensibility), 기능 동적 추가
Uniform Interface자원 접근을 위한 일관된 인터페이스단순성(Simplicity), 가시성, 독립적 진화

3. 핵심 제약 조건: Uniform Interface 심층 분석

Uniform Interface(일관된 인터페이스) 제약 조건은 REST 아키텍처의 심장과도 같다. 이는 클라이언트와 서버 간의 결합도를 근본적으로 낮추고(loosely coupling) 독립적인 진화를 가능하게 하는 핵심 메커니즘을 제공한다.1 오늘날 대부분의 API가 HTTP 프로토콜을 사용함으로써 이 제약 조건의 일부는 자연스럽게 충족하는 것처럼 보이지만, 네 가지 하위 제약 조건을 모두 만족하는 경우는 극히 드물다.9 바로 이 지점에서 진정한 RESTful API와 일반적인 ’HTTP JSON API’의 근본적인 차이가 발생한다.

Uniform Interface는 네 가지 하위 제약 조건으로 구성된다.

3.1 Identification of Resources (자원의 식별)

첫 번째 하위 제약 조건은 시스템 내의 모든 ’자원(resource)’이 URI(Uniform Resource Identifier)를 통해 고유하게 식별되어야 한다는 것이다.1 여기서 중요한 개념은 ‘자원’ 그 자체와 ’자원의 표현(representation)’이 개념적으로 분리된다는 점이다.1 예를 들어, ’사용자 123’이라는 자원은 서버 데이터베이스에 특정 형태로 저장되어 있을 수 있다. 클라이언트가/users/123이라는 URI로 이 자원을 요청할 때, 서버는 이 자원의 ’상태’를 특정 형식의 ’표현’으로 변환하여 응답한다. 이 표현은 HTML, JSON, XML 등 다양한 미디어 타입이 될 수 있으며, 클라이언트는 Accept 헤더를 통해 원하는 표현 형식을 서버에 요청할 수 있다. 서버의 내부 데이터 모델이 변경되더라도, 클라이언트가 사용하는 URI와 주고받는 표현의 형식만 유지된다면 상호작용에는 문제가 없다. 이는 클라이언트를 서버의 내부 구현으로부터 격리시키는 중요한 원리다.

3.2 Manipulation of Resources Through Representations (표현을 통한 자원 조작)

클라이언트는 식별된 자원을 직접 조작하는 것이 아니라, 서버로부터 받은 자원의 표현을 통해 상호작용한다.11 클라이언트가 자원의 상태를 변경하고자 할 때, 원하는 상태를 담은 표현을 서버에 전송하면, 서버는 이를 해석하여 실제 자원의 상태를 변경한다. 이 과정은 표준화된 HTTP 메서드(GET, POST, PUT, PATCH, DELETE 등)를 통해 이루어진다.7 예를 들어, 클라이언트는 GET /users/123을 통해 사용자 정보를 JSON 표현으로 받은 후, 일부 필드를 수정하여 PUT /users/123 요청의 본문에 담아 전송함으로써 자원의 상태를 변경할 수 있다. 클라이언트는 이 과정에서 서버가 해당 데이터를 어떻게 저장하고 처리하는지에 대한 내부 로직을 전혀 알 필요가 없다.11 오직 일관된 인터페이스(URI + HTTP 메서드 + 표현)를 통해서만 상호작용한다.

3.3 Self-Descriptive Messages (자기 서술적 메시지)

자기 서술적 메시지 제약 조건은 각 메시지(요청 또는 응답)가 그 자체만으로 어떻게 처리되어야 하는지에 대한 충분한 정보를 포함해야 한다는 것을 의미한다.9 이는 단순히 데이터 페이로드만 전송하는 것을 넘어, 그 데이터를 해석하는 데 필요한 메타데이터를 함께 제공해야 함을 뜻한다.

가장 기본적인 수준에서, 이는 HTTP의 Content-Type 헤더를 통해 달성된다. Content-Type: application/json 헤더는 메시지 본문이 JSON 형식이며, IANA에 등록된 명세에 따라 파싱해야 함을 명시한다.11 하지만 진정한 자기 서술성은 구문(syntax)의 해석을 넘어 의미(semantics)의 해석까지 포함해야 한다. 예를 들어, 다음의 JSON 응답이 있다고 가정해 보자.

{
"id": "a7c2-4f31",
"title": "Hypermedia API Report"
}

Content-Type: application/json 헤더는 클라이언트에게 이 문자열을 JSON 객체로 파싱하는 방법을 알려주지만, id 필드가 무엇을 의미하는지, title 필드가 어떤 종류의 제목인지에 대한 의미론적 정보는 제공하지 못한다.11 클라이언트는 이 필드들의 의미를 이해하기 위해 API 문서와 같은 ’대역 외 정보’에 의존해야만 한다.

이 문제를 해결하고 메시지의 의미론적 자기 서술성을 높이기 위해 두 가지 접근 방식이 제안된다.11

  1. 커스텀 미디어 타입(Custom Media Type) 정의: application/vnd.company.report+json과 같이 새로운 미디어 타입을 정의하고 IANA에 등록한다. 이 미디어 타입의 명세 문서에 idtitle 필드의 의미를 상세히 기술한다. 클라이언트는 이 미디어 타입을 보고 해당 명세를 찾아 메시지를 완전히 해석할 수 있다.

  2. 프로파일(Profile) 사용: Link 헤더에 profile 관계(relation)를 사용하여 해당 메시지의 의미를 설명하는 명세 문서의 URI를 제공한다.

Link: <http://api.example.com/profiles/report>; rel="profile"

클라이언트는 이 profile 링크를 따라가 명세를 확인하고 메시지의 의미를 동적으로 파악할 수 있다.

이러한 접근 방식은 API 계약이 정적인 문서에 고정되는 것이 아니라, 각 메시지 자체에 계약의 위치가 포함되어 ’대역 내(in-band)’에서 동적으로 전달될 수 있음을 시사한다. 이는 서버가 새로운 필드를 추가하거나 기존 필드의 의미를 변경했을 때, 클라이언트가 하드코딩된 로직이 아닌 메시지에 포함된 profile 링크를 통해 새로운 명세를 참조하여 적응할 수 있는 잠재력을 제공한다. 즉, 자기 서술성은 API ’의미’의 동적 발견을 가능하게 하는 메커니즘이며, 이는 HATEOAS가 URI의 동적 발견을 가능하게 하는 것과 철학적으로 맞닿아 있다.

3.4 Hypermedia as the Engine of Application State (HATEOAS)

네 번째이자 가장 중요한 하위 제약 조건은 HATEOAS이다. 이는 클라이언트가 API와의 상호작용을 미리 정의된, 하드코딩된 URI를 통해 수행하는 것이 아니라, 서버가 동적으로 제공하는 하이퍼미디어 링크를 통해 애플리케이션의 상태를 전이(transition)시켜야 한다는 원칙이다.11 클라이언트는 오직 초기 진입점 URI(entry point URI)만 알고 있으면 되며, 그 이후의 모든 가능한 행동과 리소스 위치는 서버 응답에 포함된 링크를 통해 발견해야 한다. 이 제약 조건은 클라이언트와 서버의 디커플링을 극대화하고 독립적 진화를 보장하는 정점이므로, 다음 장에서 별도로 심층 분석한다.

4. 애플리케케이션 상태의 엔진, HATEOAS

HATEOAS(Hypermedia as the Engine of Application State)는 REST 아키텍처 스타일의 정수(essence)이며, 다른 네트워크 아키텍처 스타일과 REST를 근본적으로 구별하는 가장 중요한 제약 조건이다.3 이 원칙은 클라이언트와 서버의 디커플링을 극대화하여, 서버의 기능이 클라이언트의 수정 없이도 독립적으로 진화할 수 있는 강력한 기반을 제공한다.3 HATEOAS를 완전히 이해하는 것은 진정한 RESTful 시스템을 이해하는 것과 동일하다.

4.1 상태 전이의 원리: API를 상태 기계로 모델링하기

HATEOAS의 이름에서 ’Engine of Application State’라는 표현은 이 원리가 애플리케이션의 상태 변화를 주도하는 동적인 메커니즘임을 암시한다. HATEOAS는 API를 일종의 상태 기계(State Machine)로 모델링한다. 이 모델에서 API 응답은 단순한 데이터의 집합이 아니라, ’현재 상태(current state)’에 대한 정보와 그 상태에서 가능한 모든 ’상태 전이(state transitions)’를 포함하는 완전한 ’상태 표현(state representation)’이다.

이 원리를 이해하기 위해 은행 계좌 조회 API 예시를 살펴보자.3

상태 1: 계좌 잔고가 충분한 경우

클라이언트가 GET /accounts/12345를 요청했을 때, 서버는 다음과 같은 응답을 반환할 수 있다.

HTTP/1.1 200 OK
Content-Type: application/json

{
"account": {
"account_number": 12345,
"balance": {
"currency": "usd",
"value": 100.00
},
"links": {
"deposits": "/accounts/12345/deposits",
"withdrawals": "/accounts/12345/withdrawals",
"transfers": "/accounts/12345/transfers",
"close-requests": "/accounts/12345/close-requests"
}
}
}

이 응답은 계좌 번호와 잔고라는 데이터뿐만 아니라, links 객체를 통해 현재 상태에서 가능한 모든 행동(입금, 출금, 이체, 계좌 해지)을 하이퍼미디어 링크로 제공한다. 클라이언트는 이 링크들을 보고 사용자에게 해당 기능들을 UI 버튼 등으로 제공할 수 있다.

상태 2: 계좌가 마이너스 잔고(초과 인출) 상태인 경우

동일한 계좌가 초과 인출 상태가 되면, 리소스의 ’상태’가 변경된다. 이때 서버는 다음과 같이 다른 링크 집합을 포함한 응답을 반환한다.

HTTP/1.1 200 OK
Content-Type: application/json

{
"account": {
"account_number": 12345,
"balance": {
"currency": "usd",
"value": -25.00
},
"links": {
"deposits": "/accounts/12345/deposits"
}
}
}

이제 links 객체에는 ‘입금(deposits)’ 링크만 존재한다. 출금, 이체, 해지와 같은 행동은 현재 상태에서 불가능하므로 서버가 해당 링크를 제공하지 않은 것이다. 클라이언트는 이 응답을 받고, 비즈니스 로직을 스스로 판단할 필요 없이 단순히 links 객체에 ‘withdrawals’ 링크가 없다는 사실만으로 출금 버튼을 비활성화할 수 있다.

이처럼 리소스의 상태가 변함에 따라 가능한 다음 행동(링크)이 동적으로 변하는 것, 이것이 바로 하이퍼미디어가 ’애플리케이션 상태의 엔진’으로 작동하는 원리다.3 클라이언트는 API의 복잡한 비즈니스 규칙(예: ‘잔고가 0 이상일 때만 출금 가능’)을 미리 알거나 하드코딩할 필요가 없다. 클라이언트는 오직 서버가 제공하는 상태 표현(데이터와 링크)에만 의존하여 동작하면 된다. 이는 진정한 의미의 서버 주도(server-driven) 상호작용을 구현하는 것이다.

4.2 디커플링의 원리: 독립적 진화의 실현

HATEOAS가 제공하는 가장 큰 가치는 클라이언트와 서버의 강력한 디커플링이다.3 클라이언트는 API와 상호작용하기 위해 초기 진입점 URI(entry point URI) 외에는 어떠한 URI에 대한 사전 지식도 가질 필요가 없다.3

예를 들어, 클라이언트가 사용자 정보를 수정한 후, 수정된 사용자 정보를 다시 조회해야 한다고 가정해 보자.

  • HATEOAS 미적용 시: 클라이언트는 사용자 수정 API(PUT /users/123)를 호출한 후, 사용자 조회 API의 URI(GET /users/123)를 직접 하드코딩하여 호출해야 한다. 만약 서버 개발자가 성능상의 이유로 사용자 조회 URI를 /profiles/123으로 변경한다면, 모든 클라이언트 개발자는 이 변경 사항을 통보받고 자신의 코드를 수정해야만 한다. 이는 서버의 변경이 클라이언트에 직접적인 파급 효과를 미치는 강한 결합 상태다.

  • HATEOAS 적용 시: 클라이언트가 PUT /users/123를 성공적으로 호출하면, 서버는 응답 본문이나 Location 헤더에 수정된 리소스를 조회할 수 있는 링크를 포함하여 반환한다.

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "123",
"name": "Updated Name",
"_links": {
"self": {
"href": "/profiles/123"
}
}
}

클라이언트는 응답에서 self라는 관계(relation, rel)를 가진 링크를 찾아 그 href 값(/profiles/123)을 사용하여 다음 요청을 보낸다. 클라이언트는 URI가 /users/123에서 /profiles/123으로 변경되었다는 사실을 알 필요가 없다. 오직 ’self’라는 관계의 의미만 이해하면 된다.5

이러한 방식은 서버가 내부 구현이나 URI 구조를 자유롭게 변경하고 리팩토링할 수 있는 유연성을 부여한다. 서버의 기능이 진화하더라도, 클라이언트는 서버가 제공하는 하이퍼미디어 링크를 따라가기만 하면 되므로 코드 변경 없이 새로운 변화에 적응할 수 있다. 이것이 바로 REST가 지향하는 ’독립적 진화’의 핵심이다.2

5. JSON 환경에서의 하이퍼미디어 구현: 주요 포맷 비교 분석

웹의 근간을 이루는 HTML은 <a> 태그를 통한 링크, <form> 태그를 통한 액션 정의 등 하이퍼미디어를 자연스럽게 지원하는 내장 메커니즘을 갖추고 있다.3 반면, 오늘날 API에서 가장 널리 사용되는 데이터 포맷인 JSON은 본질적으로 순수한 데이터 구조를 표현하기 위한 것으로, 하이퍼미디어 컨트롤을 위한 표준적인 방법을 내장하고 있지 않다.4 이러한 한계로 인해 순수 JSON만으로는 HATEOAS 원칙을 구현하기가 매우 까다로우며 2, 이 문제를 해결하기 위해 JSON에 하이퍼미디어 시맨틱스를 추가하는 여러 표준화된 포맷들이 등장했다.

본 장에서는 먼저 하이퍼미디어 컨트롤이 없는 일반적인 REST API 응답과 하이퍼미디어가 적용된 응답의 차이를 비교하고, 이어서 주요 하이퍼미디어 포맷인 HAL, Siren, JSON-LD, Collection+JSON을 구조, 특징, 사용 사례를 기준으로 심층 비교 분석한다.

5.1 일반적인 REST API 응답 vs. 하이퍼미디어 응답

사용자 프로필 정보를 조회하는 API를 예로 들어 두 응답 형식의 차이를 살펴보자.

5.1.1 일반적인 REST API JSON 응답 (데이터 중심)

일반적인 API 응답은 요청된 리소스의 상태(데이터)만을 포함한다.15

// GET /users/42

{
"id": 42,
"username": "johndoe",
"email": "johndoe@example.com",
"status": "active",
"department_id": 101
}

이 응답은 사용자 ’johndoe’에 대한 정보를 담고 있지만, 이 정보를 가지고 다음에 무엇을 할 수 있는지에 대한 정보는 전무하다. 클라이언트 개발자는 API 문서를 참조하여 다음과 같은 사실을 미리 알고 코드를 작성해야 한다.

  • 이 사용자의 상세 부서 정보를 보려면 /departments/101로 GET 요청을 보내야 한다.

  • 이 사용자의 비밀번호를 변경하려면 /users/42/password로 PUT 요청을 보내야 한다.

  • 이 사용자를 비활성화하려면 /users/42/deactivate로 POST 요청을 보내야 한다.

이러한 URI와 행위들은 모두 클라이언트 코드에 하드코딩되어야 하며, 서버가 이 구조를 변경하면 클라이언트는 즉시 오작동하게 된다.

5.1.2 하이퍼미디어 JSON 응답 (HAL 포맷 예시)

하이퍼미디어 API 응답은 데이터와 함께, 관련된 리소스와 가능한 액션에 대한 ’링크(하이퍼미디어 컨트롤)’를 포함한다.16 가장 널리 알려진 포맷 중 하나인 HAL(Hypertext Application Language)을 사용한 예시는 다음과 같다.

// GET /users/42

{
"id": 42,
"username": "johndoe",
"email": "johndoe@example.com",
"status": "active",
"_links": {
"self": { "href": "/users/42" },
"edit": { "href": "/users/42" },
"department": { "href": "/departments/101" },
"password-change": { "href": "/users/42/password" },
"deactivate": { "href": "/users/42/deactivate" }
},
"_embedded": {
"department": {
"id": 101,
"name": "Research and Development",
"_links": {
"self": { "href": "/departments/101" }
}
}
}
}

이 응답에는 _links_embedded라는 예약된 속성이 추가되었다.17

  • _links: 현재 리소스와 관련된 다른 리소스나 액션에 대한 URI를 제공한다. 클라이언트는 ’department’라는 관계(rel)를 가진 링크의 href를 따라가 부서 정보를 조회할 수 있고, ‘deactivate’ 링크를 따라가 비활성화 액션을 수행할 수 있다. URI를 하드코딩할 필요가 없다.

  • _embedded: 관련된 리소스(여기서는 부서 정보)를 응답에 직접 포함시켜 클라이언트가 추가적인 네트워크 요청을 하지 않도록 최적화할 수 있다.18

이처럼 하이퍼미디어 응답은 API를 ’자가 문서화(self-documenting)’하고, 클라이언트가 동적으로 API를 탐색(discover)하고 상호작용할 수 있도록 만든다.

5.2 주요 하이퍼미디어 포맷 비교 분석

5.2.1 HAL (Hypertext Application Language)

  • 구조 및 특징: HAL은 단순성과 최소한의 구조를 지향하는 포맷이다.17 핵심은

_links_embedded라는 두 개의 예약된 속성이다. _links 객체는 링크 관계(rel)를 키로, 링크 객체(href 등의 속성을 가짐)를 값으로 가진다. _embedded 객체는 _links와 유사한 구조로, 링크된 리소스의 전체 표현을 내장한다.17 HAL은 기존 JSON 데이터 구조에 이 두 속성만 추가하면 되므로 학습 곡선이 낮고 기존 API에 점진적으로 적용하기 용이하다는 큰 장점이 있다.19 그러나 HAL 명세 자체는 링크가 어떤 HTTP 메서드와 함께 사용되어야 하는지, 요청 본문에는 어떤 필드가 필요한지와 같은 ’액션’을 명시적으로 표현하는 표준 방법을 제공하지 않는다.19 이러한 정보는 링크 관계(

rel)의 의미에 암시적으로 의존하거나, profile 링크를 통해 별도의 문서에서 설명해야 한다. 이 한계를 극복하기 위해 HAL-FORMS와 같은 확장이 제안되었으나 아직 널리 채택되지는 않았다.20

  • 사용 사례: 리소스 간의 단순한 연결과 탐색이 주된 요구사항인 범용적인 API에 적합하다. 복잡한 상태 전이나 쓰기 작업보다는 조회 중심의 API에서 효과적이다.21

5.2.2 Siren

  • 구조 및 특징: Siren은 ’엔티티(Entity)’와 ’액션(Action)’을 명시적으로 표현하는 데 중점을 둔, HAL보다 더 구조적이고 표현력이 풍부한 포맷이다.21 Siren 응답은 다음과 같은 명확히 구분된 필드들로 구성된다:

class(엔티티의 유형), properties(엔티티의 상태 데이터), entities(관련 하위 엔티티, 링크 또는 임베디드), actions(수행 가능한 상태 전이), links(탐색용 링크).22 Siren의 가장 큰 차별점은 actions 필드다.19 이 필드를 통해 클라이언트가 수행할 수 있는 각 행동에 대해 name, method(GET, POST 등), href(URI), type(Content-Type), 그리고 요청 본문에 필요한 fields의 상세 정보까지 명시적으로 제공할 수 있다. 이는 클라이언트가 복잡한 쓰기 작업을 수행하기 위해 필요한 모든 정보를 응답 내에서 얻을 수 있게 해준다.

  • 사용 사례: 사용자의 권한이나 리소스의 상태에 따라 수행할 수 있는 작업이 동적으로 변하는, 상태 전이가 복잡한 워크플로우 기반의 API에 매우 적합하다. 클라이언트에게 명확한 행동 가이드를 제공해야 할 때 강력한 성능을 발휘한다.21

5.2.3 JSON-LD (JSON for Linked Data)

  • 구조 및 특징: JSON-LD는 W3C 표준으로, 단순한 API 네비게이션을 넘어 데이터 자체에 시맨틱한 의미를 부여하고 웹 전반의 다른 데이터와 연결하는 ’링크드 데이터(Linked Data)’를 지향한다.23 핵심 메커니즘은 @context 필드다.23

@context는 JSON 문서 내의 키(예: name)를 http://schema.org/name과 같은 전역적으로 고유한 IRI(Internationalized Resource Identifier)에 매핑하는 역할을 한다. 이를 통해 데이터의 모호성을 제거하고 기계가 의미를 정확히 이해할 수 있도록 돕는다. @id는 리소스를 고유한 IRI로 식별하고, @type은 리소스의 클래스(유형)를 지정한다. JSON-LD는 데이터를 단순한 트리 구조가 아닌, 노드와 엣지로 구성된 그래프(graph)로 모델링한다.24

  • 사용 사례: 데이터의 의미와 상호운용성이 매우 중요한 도메인에 적합하다. 예를 들어, 여러 출처의 데이터를 통합해야 하는 대규모 플랫폼, 시맨틱 검색 엔진, 지식 그래프 구축, 공개 데이터셋(Open Data) 배포 등에 사용된다. 일반적인 애플리케이션 API보다는 데이터 교환 포맷으로서의 성격이 더 강하다.21

5.2.4 Collection+JSON

  • 구조 및 특징: Collection+JSON은 이름에서 알 수 있듯이, 리소스 ’컬렉션(collection)’을 관리하고 조작하는 데 특화된 포맷이다.25 전체 응답은 collection이라는 최상위 객체로 감싸여 있다. 이 객체는 items(컬렉션의 각 항목 데이터와 링크), queries(미리 정의된 검색 기능), template(새로운 항목을 생성하거나 기존 항목을 수정하기 위한 데이터 제출 템플릿)와 같은 하위 필드를 포함한다.26 특히 template 필드는 클라이언트에게 쓰기 작업을 위해 어떤 데이터를 어떤 형식으로 보내야 하는지를 명확하게 안내하는 강력한 기능을 제공한다.26

  • 사용 사례: 블로그 게시물 목록, 연락처 목록, 상품 목록 등과 같이 목록 형태의 데이터를 다루는 CRUD(Create, Read, Update, Delete) 중심의 API에 매우 효과적이다. 클라이언트가 컬렉션에 대해 검색, 페이징, 항목 추가/수정 등의 작업을 수행하는 시나리오에 최적화되어 있다.21

특징 (Feature)HAL (Hypertext Application Language)SirenJSON-LD (JSON for Linked Data)Collection+JSON
핵심 철학단순성, 최소한의 구조엔티티와 행위(Action)의 명시적 표현시맨틱 웹, 데이터 연결성컬렉션 관리 및 조작
기본 구조_links, _embeddedclass, properties, entities, actions, links@context, @id, @typecollection 객체 (items, queries, template)
액션 표현암시적 (링크 rel에 의존)명시적 (actions 필드: method, fields 등)암시적 (Hydra 등 확장 필요)template 필드를 통한 쓰기 작업 정의
임베딩 방식_embedded 필드 사용entities 필드 내 임베디드 표현그래프 내 노드로 자연스럽게 표현지원하지 않음 (각 item은 링크된 리소스)
의미 표현relprofile 링크에 의존class 속성으로 엔티티 유형 기술@context를 통한 강력한 시맨틱 매핑rel에 의존
복잡도낮음중간높음중간
주요 사용 사례범용적인 리소스 네비게이션상태 전이가 복잡한 워크플로우 API데이터 통합, 공개 데이터셋CRUD 중심의 컬렉션 API

6. 하이퍼미디어 REST API 설계 원칙 및 모범 사례

하이퍼미디어의 이론적 개념을 실제 API 설계에 효과적으로 적용하기 위해서는 일관되고 예측 가능하며, 클라이언트가 쉽게 사용할 수 있는 인터페이스를 만들기 위한 구체적인 설계 원칙과 모범 사례를 준수하는 것이 중요하다. 이는 단순히 링크를 포함하는 것을 넘어, API 전체의 상호작용 방식을 체계적으로 모델링하는 과정이다.

전통적인 API 설계가 주로 데이터베이스 스키마를 반영하는 ’리소스’를 정의하는 데 집중하는 경향이 있다면, 하이퍼미디어 API 설계는 이러한 접근 방식을 지양해야 한다.27 대신, 설계의 초점은 ’데이터가 무엇인가?’에서 ’이 데이터를 가지고 무엇을 할 수 있는가?’로 전환되어야 한다. 즉, 정적인 데이터 모델이 아닌, 사용자의 여정과 비즈니스 프로세스를 반영하는 동적인 ’상호작용 모델’을 API 수준에서 설계하는 것이다. 이는 API를 단순한 데이터 창구에서 애플리케이션의 비즈니스 로직을 온전히 표현하는 인터페이스로 격상시키는 패러다임의 전환을 요구한다.

6.1 리소스 네이밍 및 URI 구조

  • URI에는 명사를 사용하라: 리소스의 URI는 행위를 나타내는 동사가 아닌, 대상을 나타내는 명사로 구성해야 한다. 행위는 HTTP 메서드를 통해 표현된다.27 컬렉션을 나타내는 URI는 복수형 명사를 사용하는 것이 일반적이다.

  • Good: GET /users, POST /users

  • Bad: GET /getUsers, POST /createUser

  • URI 구조는 단순하고 계층적으로 유지하라: 리소스 간의 관계는 URI 경로를 통해 계층적으로 표현할 수 있다. 예를 들어, 특정 고객의 모든 주문은 /customers/5/orders로 표현할 수 있다. 하지만 이러한 계층이 지나치게 깊어지는 것(예: /customers/1/orders/99/products)은 피해야 한다.27 복잡한 URI는 유지보수가 어렵고, 리소스 간의 관계가 변경될 때 유연성이 떨어진다.

collection/item/collection 수준을 넘지 않는 단순한 구조를 유지하고, 더 복잡한 관계는 하이퍼미디어 링크를 통해 표현하는 것이 바람직하다.27

  • 경로 세그먼트에는 소문자와 하이픈을 사용하라: URI 경로 세그먼트는 소문자로 작성하고, 단어 사이는 하이픈(-)으로 연결하는 것이 가독성과 일관성 측면에서 권장된다. 쿼리 파라미터에는 스네이크 케이스(snake_case)를 사용할 수 있다.30

6.2 HTTP 메서드의 의미론적 사용

HTTP 메서드는 각각 고유한 의미와 속성(안전성, 멱등성)을 가지며, 이를 정확히 준수하여 사용해야 한다.31

  • GET: 리소스를 조회한다. 안전(Safe)하고 멱등적(Idempotent)인 메서드이다.

  • POST: 새로운 리소스를 생성하거나, 기존 리소스에 하위 리소스를 추가하거나, 다른 메서드로 표현하기 어려운 복잡한 처리를 요청할 때 사용한다. 멱등적이지 않다.

  • PUT: 특정 URI에 위치한 리소스 전체를 요청 본문의 내용으로 대체(replace)한다. 리소스가 없으면 새로 생성할 수도 있다. 멱등적이다.

  • PATCH: 리소스의 일부를 부분적으로 수정(modify)한다. 멱등적일 수도, 아닐 수도 있으나 멱등적으로 설계하는 것이 권장된다.30

  • DELETE: 리소스를 삭제한다. 멱등적이다.

6.3 링크 관계(rel)의 명확한 정의

하이퍼미디어 API에서 클라이언트는 URI가 아닌 링크 관계(rel)를 기준으로 다음에 수행할 작업을 결정한다. 따라서 rel 값은 API의 시맨틱스를 정의하는 매우 중요한 요소다.

  • 표준 관계를 우선 사용하라: self, next, prev, first, last 등 IANA에 등록된 표준 링크 관계를 최대한 활용하여 범용 클라이언트와의 호환성을 높여야 한다.32

  • 도메인 특화 관계는 문서화하라: 애플리케이션의 고유한 비즈니스 로직을 표현하기 위해 커스텀 rel 값(예: deactivate-account, add-to-cart)을 정의할 수 있다. 이 경우, 해당 rel의 의미와 사용 방법을 명확하게 문서화해야 한다. 가장 좋은 방법은 profile 링크를 통해 해당 rel의 정의를 담은 명세 문서의 URI를 제공하는 것이다.32

6.4 페이지네이션, 필터링, 정렬의 하이퍼미디어적 표현

대규모 컬렉션을 다룰 때 페이지네이션, 필터링, 정렬은 필수적이다. 이러한 기능들 또한 하이퍼미디어 원칙에 따라 동적으로 제공되어야 한다.

  • 페이지네이션: 응답에 next, prev, first, last 관계를 가진 링크를 포함하여 클라이언트가 컬렉션을 순회할 수 있도록 안내해야 한다.30 클라이언트는 page=2와 같은 쿼리 파라미터를 직접 구성해서는 안 된다.

  • 필터링 및 정렬: 클라이언트가 수행할 수 있는 필터링이나 정렬 옵션을 동적으로 알려주기 위해 쿼리 템플릿을 사용할 수 있다. Collection+JSON의 queries 필드나 HAL의 URI 템플릿((https://datatracker.ietf.org/doc/html/rfc6570))이)이) 좋은 예다. 이를 통해 서버는 사용 가능한 필터링 조건이나 정렬 기준을 클라이언트에게 제공하고, 클라이언트는 이를 기반으로 UI를 구성하여 사용자 입력을 받아 요청 URI를 생성할 수 있다.

6.5 일관된 오류 처리

오류 응답 또한 일관된 구조를 가져야 하며, 가능하면 문제 해결에 도움이 되는 정보를 포함해야 한다.

  • 표준 오류 포맷을 사용하라:(https://datatracker.ietf.org/doc/html/rfc7807)는는) 오류 응답을 위한 표준 JSON 포맷을 정의한다. 이를 따르면 클라이언트가 오류를 기계적으로 파싱하고 일관되게 처리하는 데 도움이 된다.30

  • 도움말 링크를 제공하라: 오류 응답에 help 또는 about 관계를 가진 링크를 포함하여, 해당 오류에 대한 상세 설명이나 해결 방법을 담은 문서로 연결해 줄 수 있다. 이는 API의 사용성을 크게 향상시킨다.

이러한 설계 원칙들을 종합적으로 적용함으로써, 개발자는 단순한 데이터 제공자를 넘어, 클라이언트와 동적으로 상호작용하며 장기적인 변화에 유연하게 적응할 수 있는 견고하고 진화 가능한 하이퍼미디어 API를 구축할 수 있다.

7. 전략적 고찰: 하이퍼미디어 API의 장단점과 도입 시 고려사항

하이퍼미디어 API를 도입하는 것은 단순한 기술적 선택을 넘어, 프로젝트의 장기적인 목표와 방향성에 영향을 미치는 전략적 결정이다. 단기적인 개발 효율성과 장기적인 시스템의 진화 가능성 사이에는 명백한 상충 관계가 존재하며, 이를 이해하는 것이 성공적인 도입의 첫걸음이다. 본 장에서는 하이퍼미디어 API의 장점과 단점을 구체적인 논거를 들어 비교 분석하고, 도입을 고려할 때 평가해야 할 핵심 요소들을 제시한다.

7.1 장점 (Advantages)

  1. 발견 가능성 및 API 진화 (Discoverability & Evolvability):

하이퍼미디어 API의 가장 큰 장점은 클라이언트가 API 문서를 지속적으로 참조할 필요 없이, 응답에 포함된 링크를 통해 동적으로 API의 기능과 리소스를 탐색할 수 있다는 점이다.34 이는 API 제공자에게 엄청난 유연성을 부여한다. 서버는 내부 로직 변경이나 성능 최적화를 위해 URI 구조를 자유롭게 리팩토링할 수 있으며, 이러한 변경은 하이퍼미디어 링크를 따라가는 클라이언트에게 투명하게 적용된다.6 이는 API가 수년에 걸쳐 점진적으로 진화하고 개선될 수 있는 강력한 기반이 된다.

  1. 클라이언트-서버 디커플링 (Decoupling):

HATEOAS 원칙을 통해 클라이언트는 서버의 URI 구조나 비즈니스 로직의 세부 사항으로부터 철저히 분리된다.34 클라이언트는 오직 링크 관계(rel)의 의미에만 의존하여 동작하므로, 서버의 내부 구현 변경이 클라이언트에 미치는 파급 효과를 최소화할 수 있다. 이러한 낮은 결합도는 시스템의 전체적인 유지보수성을 크게 향상시키고, 서버와 클라이언트 팀이 서로의 작업에 미치는 영향을 최소화하며 독립적으로 개발을 진행할 수 있게 한다.6

  1. 유연한 클라이언트 동작 (Flexible Client Behavior):

서버는 리소스의 현재 상태나 사용자의 권한에 따라 응답에 포함되는 링크를 동적으로 제어할 수 있다. 클라이언트는 특정 링크의 존재 유무를 확인하여 UI(예: 버튼 활성화/비활성화)나 기능을 동적으로 변경할 수 있다.6 예를 들어, ‘결제 완료’ 상태인 주문 리소스에는 ‘주문 취소’ 링크를 포함하지 않음으로써, 클라이언트가 비즈니스 로직을 하드코딩하지 않고도 올바른 사용자 경험을 제공하도록 유도할 수 있다. 이는 비즈니스 규칙 변경이 서버 코드 수정만으로 클라이언트에 즉시 반영될 수 있음을 의미한다.

7.2 단점 (Disadvantages)

  1. 초기 구현 복잡성 및 비용 (Implementation Complexity & Cost):

하이퍼미디어 API는 단순한 데이터 API에 비해 설계와 구현에 훨씬 더 많은 시간과 노력이 요구된다.35 리소스의 상태에 따른 링크와 액션을 모델링하고, 이를 일관된 포맷으로 표현하는 과정은 상당한 사전 계획과 깊은 고민을 필요로 한다. 이는 “일단 빠르게 만들고 보자“는 식의 단기적 효율성을 중시하는 프로젝트 환경에서는 도입의 큰 장벽으로 작용한다.6

  1. 응답 페이로드 증가 (Increased Payload Size):

데이터와 함께 링크, 임베디드 리소스, 액션 정의 등 다양한 메타데이터가 응답에 포함되므로, 순수 데이터 API에 비해 응답 페이로드의 크기가 커질 수밖에 없다.6 이는 네트워크 대역폭이 제한적이거나, 응답 속도에 극도로 민감한 모바일 환경 등에서는 성능 저하의 요인이 될 수 있다.

  1. 클라이언트 구현의 어려움 (Client-side Challenges):

하이퍼미디어 API를 제대로 활용하기 위해서는 클라이언트가 단순히 정적인 데이터를 파싱하는 것을 넘어, 동적으로 링크를 해석하고 관계(rel)의 의미를 이해하며 상태를 전이하는 로직을 구현해야 한다.6 이는 하드코딩된 URI를 사용하는 것보다 구현이 더 복잡하며, 많은 개발자들이 이 개념에 익숙하지 않다.35 또한, 다양한 하이퍼미디어 포맷을 일관되게 지원하는 성숙한 범용 클라이언트 라이브러리나 프레임워크 생태계가 아직 부족한 것도 현실이다.

  1. 단일 표준 포맷의 부재 (Lack of a Single Standard):

HAL, Siren, JSON-LD, Collection+JSON 등 여러 하이퍼미디어 포맷이 경쟁하고 있으며, 각각의 장단점과 사용 사례가 다르다.6 어떤 포맷을 선택해야 할지에 대한 불확실성은 개발자들에게 혼란을 야기하며, 이는 도구 생태계의 파편화로 이어진다. 하나의 표준이 없다는 것은 범용적인 도구나 라이브러리의 발전을 더디게 만드는 요인이 된다.19

7.3 도입 시 고려사항

하이퍼미디어 API의 도입 여부는 다음의 요소들을 종합적으로 고려하여 신중하게 결정해야 한다.

  • API의 예상 수명과 진화 가능성: API가 단기적인 프로젝트를 위한 것이 아니라, 장기간(수년에서 수십 년)에 걸쳐 유지보수되고 점진적으로 진화해야 하는 공용 API나 대규모 시스템의 핵심 인터페이스라면, 하이퍼미디어 도입의 장기적인 이점이 초기 비용을 상쇄하고도 남을 것이다.2

  • 클라이언트의 다양성과 통제 여부: API를 사용하는 클라이언트가 자사가 직접 통제하는 웹/모바일 애플리케이션으로 한정된다면, 서버와 클라이언트 간의 긴밀한 협의를 통해 변경에 대응할 수 있으므로 디커플링의 이점이 상대적으로 줄어들 수 있다. 반면, 다양한 제3자 개발자들이 사용하는 공개 API(Public API)라면, 하이퍼미디어는 예측 불가능한 클라이언트들의 안정성을 보장하는 데 매우 중요한 역할을 한다.

  • 팀의 기술적 성숙도와 학습 곡선: 하이퍼미디어는 단순히 기술을 도입하는 것을 넘어, API를 설계하고 소비하는 방식에 대한 패러다임의 전환을 요구한다. 팀 구성원들이 하이퍼미디어의 개념을 충분히 이해하고, 새로운 개발 방식을 학습할 의지와 역량이 있는지 현실적으로 평가해야 한다.35

  • 도메인의 복잡성: 상태 전이가 복잡하고, 사용자의 역할이나 리소스의 상태에 따라 가능한 행동이 크게 달라지는 비즈니스 도메인일수록 하이퍼미디어의 가치가 극대화된다. 반면, 단순한 데이터 조회 기능만 제공하는 API라면 도입 효과가 미미할 수 있다.

결론적으로, 하이퍼미디어 API는 모든 상황에 적합한 만병통치약이 아니다. 이는 장기적인 시스템의 건강과 진화 가능성을 위한 전략적 투자이며, 그 가치는 프로젝트의 특성과 목표에 따라 달라진다.

8. 결론: 미래지향적 API 아키텍처를 향하여

본 안내서는 오늘날 널리 퍼진 ’HTTP JSON API’라는 통념을 넘어, REST 아키텍처 스타일의 근본 철학을 심층적으로 탐구했다. REST의 핵심 목표는 단기적인 개발 효율성이 아니라, 인터넷 규모의 분산 시스템이 수십 년에 걸쳐 독립적으로 진화할 수 있는 토대를 마련하는 데 있음을 확인했다.2 이 장대한 목표를 달성하기 위한 핵심 메커니즘이 바로 ’하이퍼미디어’이며, 이는 HATEOAS라는 제약 조건으로 구체화된다.

HATEOAS는 클라이언트가 서버가 동적으로 제공하는 링크를 통해 애플리케이션의 상태를 전이하도록 강제함으로써, 클라이언트와 서버 간의 결합도를 극단적으로 낮춘다. 이를 통해 서버는 클라이언트의 코드 수정 없이도 URI 구조를 변경하고, 새로운 기능을 추가하며, 비즈니스 로직을 발전시킬 수 있다. 이는 예측 불가능한 미래의 변화에 대응할 수 있는 진정한 의미의 ’진화 가능한 시스템(evolvable system)’을 구축하기 위한 필수 조건이다.

물론, 하이퍼미디어 API를 구현하는 길은 순탄치 않다. 초기 설계의 복잡성, 페이로드의 증가, 클라이언트 구현의 어려움, 그리고 표준 포맷의 부재와 같은 현실적인 장벽이 존재한다. 이러한 단점들로 인해 많은 조직이 단기적인 효율성을 택하고, Richardson Maturity Model에서 제시하는 Level 2(HTTP 동사 사용)에 머무르는 경향이 있다.4

그러나 본 안내서에서 분석했듯이, Level 3(Hypermedia Controls)에 도달하는 것은 단순히 기술적 완성도를 높이는 것을 넘어, 시스템의 장기적인 생존성과 적응력을 확보하기 위한 전략적 투자다.34 하이퍼미디어는 API를 정적인 데이터 계약의 집합이 아닌, 살아있는 유기체처럼 동적으로 상호작용하고 스스로를 설명하는 인터페이스로 변화시킨다.

따라서 미래지향적 API 아키텍처를 고민하는 설계자라면, 현재의 개발 편의성을 넘어 시스템의 장기적인 가치를 고려해야 한다. 하이퍼미디어 REST API는 그 길을 제시하는 가장 강력하고 원칙적인 나침반이 될 것이다. 이는 기술적 유행을 따르는 것이 아니라, 월드 와이드 웹을 성공으로 이끈 근본적인 아키텍처 원칙으로 회귀하는 것이며, 변화를 두려워하지 않고 변화를 포용하는 시스템을 만들기 위한 현명한 선택이다.

9. 참고 자료

  1. REST - Wikipedia, https://en.wikipedia.org/wiki/REST
  2. [Restful api 란] - 진짜 Rest API 란 무엇이고 어떻게 써야하는 걸까?, https://thalals.tistory.com/335
  3. HATEOAS - Wikipedia, https://en.wikipedia.org/wiki/HATEOAS
  4. htmx ~ HATEOAS, https://htmx.org/essays/hateoas/
  5. [SpringBoot] HATEOAS 개념 및 간단한 예제 - ZeroBin`s 개발일지, https://zerobin-dev.tistory.com/126
  6. REST with Hypermedia - Hot or Not? - Reflectoring, https://reflectoring.io/rest-hypermedia/
  7. What is REST API? - Visual Paradigm, https://www.visual-paradigm.com/guide/development/what-is-rest-api/
  8. Rest API architectural constraints - WebScrapingAPI, https://www.webscrapingapi.com/rest-api-architecture-constraints
  9. REST API 뽀개기, https://velog.io/@dsa2341/REST-API-%EB%BD%80%EA%B0%9C%EA%B8%B0-6vpzm4ix
  10. REST Architectural Constraints - REST API Tutorial, https://restfulapi.net/rest-architectural-constraints/
  11. REST API (제약 조건) - JJin 개발 Vlog - 티스토리, https://jindream6128.tistory.com/13
  12. en.wikipedia.org, https://en.wikipedia.org/wiki/HATEOAS#:~:text=Hypermedia%20as%20the%20engine%20of,provide%20information%20dynamically%20through%20hypermedia.
  13. REST 기본 개념 총정리 3편 - 균일한 인터페이스 - 테오의 학습기록, https://dev-ws.tistory.com/73
  14. Hypermedia in REST apis : r/softwarearchitecture - Reddit, https://www.reddit.com/r/softwarearchitecture/comments/1mfv45b/hypermedia_in_rest_apis/
  15. JSON Data APIs - Hypermedia Systems, https://hypermedia.systems/json-data-apis/
  16. Hypermedia APIs | Apiture Open Banking APIs, https://developer.apiture.com/docs/concepts/hypermedia
  17. draft-kelly-json-hal-06 - IETF Datatracker, https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-06
  18. HAL - Hypertext Application Language - Matthew Weier O’Phinney weierophinney, https://weierophinney.github.io/hal/hal/
  19. What’s different/better/worse than other JSON hypermedia media types? · Issue #15 · kevinswiber/siren - GitHub, https://github.com/kevinswiber/siren/issues/15
  20. HAL and HAL-FORMS - json - Stack Overflow, https://stackoverflow.com/questions/78512721/hal-and-hal-forms
  21. Designing Hypermedia APIs for Discoverability and Flexibility - Apidog, https://apidog.com/blog/designing-hypermedia-apis/
  22. kevinswiber/siren: Structured Interface for Representing … - GitHub, https://github.com/kevinswiber/siren
  23. JSON-LD 1.1 - W3C, https://www.w3.org/TR/json-ld11/
  24. JSON-LD 1.1 - W3C on GitHub, https://w3c.github.io/json-ld-syntax/
  25. Collection-JSON - HTTP Programming, https://www.http-programming.com/specifications/collection-json/
  26. collection-json/spec: Collection+JSON Specification - GitHub, https://github.com/collection-json/spec
  27. Web API Design Best Practices - Azure Architecture Center …, https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
  28. Api 아키텍처 - Rest Api 설계 모범 지침 - CodeSnap, https://codesnapmag.hashnode.dev/rest-api-design-practice
  29. RESTful 웹 API 디자인에 대한 모범 사례 - Azure - Microsoft Learn, https://learn.microsoft.com/ko-kr/azure/architecture/best-practices/api-design
  30. Best Practices | API Principles, https://schweizerischebundesbahnen.github.io/api-principles/restful/best-practices/
  31. REST API 설계 원칙 - steady study - 티스토리, https://kmkunk.tistory.com/139
  32. Hypermedia API: How to document properly? - Stack Overflow, https://stackoverflow.com/questions/41677977/hypermedia-api-how-to-document-properly
  33. HAL - Hypertext Application Language, https://stateless.group/hal_specification.html
  34. Hypermedia in RESTful APIs: Exploring the Concept and Its Benefits in API Design - Xapi, https://blog.xapihub.io/2024/01/17/Hypermedia-in-RESTful-APIs.html
  35. API Best Practices: Hypermedia (Part 4.1) - MuleSoft Blog, https://blogs.mulesoft.com/dev-guides/api-design/api-best-practices-hypermedia-part-1/