- HTTP API에 REST 아키텍처를 적용한 목적
- REST 아키텍처 스타일
- Uniform Interface
- Uniform Interface 제약조건
- Self-descriptive message 지키기
- HATEOAS 지키기
- Reference
HTTP API에 REST 아키텍처를 적용한 목적
- 시스템의 독립적인 진화를 보장하기 위해서이다.
REST 아키텍처 스타일
- Client-Server
- Stateless
- Cache
- Uniform Interface
- Layered System
- Code-On-Demand (optional)
- HTTP API를 사용해도 대부분 지킬 수 있다.
- 단, Uniform Interface는 제외.
Uniform Interface
- HTTP 표준에만 따른다면 어떠한 기술이라던지 사용이 가능하며
URI로 지정한 리소스에 대한 조작이 가능한 아키텍처 스타일을 의미한다.
- 위의 개념이 대두된 배경은 크게 2가지가 있다.
- [1] 애플리케이션의 복잡도가 증가하면서 애플리케이션의 분리 및 통합이 중요해졌다.
- [2] 모바일과 같은 다양한 클라이언트 환경이 등장하면서 백엔드 하나로 다양한 Device에 대응하기 위함이다.
Uniform Interface 제약조건
- identification of resources
- manipulation of resources through represenations
- self-descrive messages
- hypermisa as the engine of appliaction state (HATEOAS)
- 이중 REST API라고 불리는 대부분의 API는 2가지를 지키고 있지 않다.
Self-descriptive message
- 메시지 스스로 메시지에 대한 설명이 가능해야 한다.
- 서버의 내용이 변해서 메시지가 변해도 클라이언트는 그 메시지를 보고 해석이 가능하므로 확장 가능하다.
예제 1
HTTP/1.1 200 OK
[ {"op" : "remove", "path" : "a/b/c/"} ]
- self-descriptive 하지 못하다.
- 어떻게 해석해야할지 모르기 때문이다.
예제 2
HTTP/1.1 200 OK
Content-Type : application/json
[ {"op" : "remove", "path" : "a/b/c/"} ]
- self-descriptive 하지 못하다.
- Json Type이라는 것을 이해할 수 있기 때문에 파싱은 가능하다.
- 하지만 ‘op’와 ‘path’ 의미를 알 수 없다.
예제 3
HTTP/1.1 200 OK
Content-Type: application/json-patch+json
[ { "op": "remove", "path": "/a/b/c" } ]
- self-descriptive 하다.
- json patch + json이라는 미디어 타입으로 정의되어 있다.
- json patch 라는 명세를 찾아가면 메시지를 해석할 수 있다.
HATEOAS
- 애플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다.
- 서버가 링크를 바꾼다고 해도 클라이언트는 바꾼 링크를 확인할 수 있다.
예제 1
HTTP/1.1 200 OK
Content-Type : text/html
<html>
<head></head>
<body><a href="/test">test</a></body>
</html>
- HATEOAS를 만족한다.
- a link로 연결되어 있기 때문이다.
예제 2
HTTP/1.1 200 OK
Content-Type : application.json
Link : </articles/1>; rel="previous",
</articles/3>; rel="next";
{
"title" : "The second article",
"contents" : "blah blah ..."
}
- HATEOAS를 만족한다.
- Link 라는 헤더를 통해 이 리소스가 연결되어 있는 다른 리소스를 제공하기 때문이다.
Self-descriptive message 지키기
[방법 1] Media type
- 미디어 타입을 정의하여 IANA에 등록한다.
- 리소스를 리턴할 때 정의한 미디어 타입을 Content-Type으로 사용한다.
GET /todos HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
[
{"id": 1, "title": "회사 가기"},
{"id": 2, "title": "집에 가기"}
]
- 단점은 필요한 Media type을 직접 등록해야하므로 번거롭다.
[방법 2] Profile
- 명세를 작성한다.
- Link 헤더에 해당 명세를 링크한다.
GET /todos HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/json
Link: <https://example.org/docs/todos>; rel="profile"
[
{"id": 1, "title": "회사 가기"},
{"id": 2, "title": "집에 가기"}
]
HATEOAS 지키기
[방법 1] 데이터에 링크 제공
GET /todos HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/json
Link: <https://example.org/docs/todos>; rel="profile"
{
"links": {
"todo": "https://example.org/todos/{id}"
},
"data": [{
"id": 1,
"title": "회사 가기"
}, {
"id": 2,
"title": "집에 가기"
}]
]
[방법 2] 링크 헤더나 Location 제공
POST /todos HTTP/1.1
Content-Type: application/json
{
"title": "점심 약속"
}
HTTP/1.1 204 No Content
Location: /todos/1
Link: </todos/>; rel="collection"