"REST API 는 hypertext-driven 이어야 한다. 아니면 RESTful 아니다." — Roy Fielding, 2008. 8년 동안 industry 가 그가 REST 로 인정한 적 없는 것들을 'REST' 라고 불러서, 2000년 dissertation 에서 자기가 한 말 의미 명확히 함.
Dissertation 정직하게 읽기
Roy Fielding 의 2000년 박사논문 Architectural Styles and the Design of Network-based Software Architectures 가 REST 를 여섯 제약 가진 architectural style 로 정의. 다섯 — client-server, statelessness, cacheability, layered system, uniform interface — 가 사람들이 REST API 라 부르는 것에 널리 채택. 여섯 번째가 대부분 API 가 건너뛰는 것: HATEOAS — Hypermedia As The Engine Of Application State.
HATEOAS 말함: REST client 는 API 의 진입점 URI 정확히 하나만 알아야. 나머지 — 취할 수 있는 action, navigate 할 수 있는 resource, 결과 다음 페이지, 관련 entity — 가 server 가 response 에 포함한 link 따라가서 발견. Client 가 /users/{id}/orders 하드코딩 안 함; client 가 /users/{id} GET 하고 rel="orders" 가진 link 봐서 order 위해 어디 가야 할지 알아.
HTML 유추
현장에서 HATEOAS 의 가장 깔끔한 예가 HTML 웹. 웹사이트 열 때 브라우저는 사이트 가진 URL 모름. 페이지 봄; 페이지가 link 포함; 하나 클릭; 더 많은 link 가진 새 페이지 받음. Application state 가 hypermedia 통해 진화. 브라우저가 원조 진짜 REST client — generic, link 따라가고 form 채우는 법만 앎.
Fielding 주장: JSON API 도 같은 방식 동작 가능. Response 가 hypermedia (JSON 안 embedded 된 link); client 가 generic (relationship 이름으로 link 걸음); server 가 URI control 유지 — client 가 절대 하드코딩 안 해서.
순수 HATEOAS response 가 어떻게 생겼나
여러 hypermedia JSON format 있고; 가장 흔한 게 HAL (Hypertext Application Language). HAL response 가 이렇게 생김:
{
"id": "u_42",
"name": "Pippa",
"_links": {
"self": { "href": "/users/u_42" },
"orders": { "href": "/users/u_42/orders" },
"edit": { "href": "/users/u_42", "method": "PUT" },
"delete": { "href": "/users/u_42", "method": "DELETE" }
}
}
Client 가 resource 읽고 _links 봐서 다음에 뭘 할 수 있는지 발견. Order 나열엔 "orders" link 따라. 편집은 "edit" 따라. 절대 string template 으로 URI 안 만듦; server 가 건넨 거 따라감.
/users/{id}/orders 를 /customers/{id}/purchases 로 바꾸면 하드코딩 URI client 다 깸. HATEOAS client 는 user resource 에서 orders-rel link 따라가 — 어디 가리키든. Server 가 URI 자유롭게 진화 가능; client 가 계속 동작.왜 강력 (이론적으로)
- URI 진화. Server 가 URI 마음대로 바꿈; client 가 relationship 이름으로 navigate 라서 신경 안 씀.
- 동적 능력 발견. Server 가 user 권한, resource state, 비즈니스 규칙에 기반해서 link 포함하거나 생략 — client 코드 변경 없이 client 동작 변경.
- Generic client. 브라우저가 server-specific 코드 없이 어느 HTML 사이트와도 상호작용 가능. 진짜 HATEOAS client 가 JSON API 에 같은 거 할 수 있어.
- Workflow encoding. Server 가 state machine 통제. Draft 글이 "publish" link 가짐; 일단 publish 되면 안 가짐. Client 가 사용 가능 link 읽고 비즈니스 로직 없이 올바른 UI render.
Workflow 예
Draft, review, publish 될 수 있는 글 상상. 사용 가능 전환이 현재 state 에 의존. 순수 HATEOAS 에선 server 가 이 전환을 link 로 표현:
# Draft state
{
"id": "a_42", "status": "draft", "title": "...",
"_links": {
"self": { "href": "/articles/a_42" },
"submit-review": { "href": "/articles/a_42/review", "method": "POST" },
"delete": { "href": "/articles/a_42", "method": "DELETE" }
}
}
# Review 제출 후 — 다른 link
{
"id": "a_42", "status": "in-review",
"_links": {
"self": { "href": "/articles/a_42" },
"approve":{ "href": "/articles/a_42/publish", "method": "POST" },
"reject": { "href": "/articles/a_42/reject", "method": "POST" }
}
}
Client 가 어떤 link 존재하나 보고 맞는 버튼 render. 글 state machine 의 client 쪽 지식 없음. 새 전환 가진 새 state 추가; 기존 client 가 코드 변경 없이 새 버튼 보여줘.
Format 들과 왜 중요한지
주목할 hypermedia JSON format 셋:
- HAL (
application/hal+json) — 최소, link + embedded sub-resource. 가장 채택됨. - JSON:API (
application/vnd.api+json) — 더 무거움, relationship/pagination/sparse fieldset 에 대해 의견 있음. - Siren (
application/vnd.siren+json) — 입력 필드 가진 action 추가, 진짜 hypermedia 에 더 가까움.
HTML 자체가 ship 된 가장 성공한 hypermedia format. 브라우저가 proof of concept; 아무도 HTML+브라우저가 동작한다는 거 안 의심.
cwkPippa 의 HATEOAS 현실
frontend/src/lib/api.ts) 가 호출하는 모든 URI 하드코딩. 201 Created 의 Location header 가 hypermedia 에 가장 가까운 것; 그게 다임. cwkPippa 엔 괜찮 — 유일 client 가 같은 repo 의 React frontend, 같이 deploy. HATEOAS 비용이 아무것도 사주지 않음. Lesson 3.4 가 그 계산이 뒤집히는 때 설명.