Q: 어떻게 인터넷에서 정보를 공유할 것인가?
A: 정보들을 하이퍼텍스트로 연결한다.
표현 형식: HTML
식별자: URI
전송 방법: HTTP
Roy T.Fielding: "How do I improve HTTP without breaking the Web?"
어떻게 하면 웹을 망가뜨리지 않고 HTTP를 진보시킬 수 있을까?
해결책: HTTP Object Model(=REST)
Roy T.Fielding, Microsoft Research에서 발표
Roy T.Fielding, 박사 논문으로 발표
REST 아키텍쳐 스타일을 따르는 API
REST: 분산 하이퍼 미디어 시스템(예: 웹)을 위한 아키텍쳐 스타일(제약조건의 집합)
아래 두 조건은 거의 모든 REST API들이 지키지 못하고 있다.
메시지는 스스로를 설명해야한다.
GET / HTTP/1.1
이 HTTP 요청 메시지는 뭔가 빠져있어서 self-descriptive 하지 못하다.
GET / HTTP/1.1
Host: www.example.org
목적지를 추가하면 이제 self-descriptive 하다.
HTTP.1,1 200 OK
[ { "op": "remove", "path": "/a/b/c" } ]
클라이언트가 이 응답을 받고 해석해야 하는데, 이게 어떤 문법으로 작성 되어 있는지 모르기 때문에 해석하지 못하므로, self-descriptive 하지 못하다.
HTTP.1,1 200 OK
Content-Type: application/json
[ { "op": "remove", "path": "/a/b/c" } ]
Content-Type 헤더가 반드시 들어가야 한다. 아직은 self-descriptive 하지 못하다.
HTTP.1,1 200 OK
Content-Type: application/json patch+json
[ { "op": "remove", "path": "/a/b/c" } ]
json patch 라는 미디어 타입으로 정의되어 있는 명세를 찾아가서 이걸 이해한 다음에 이 메시지를 해석을 하면 그제서야 이 메시지를 올바르게 이해할 수 있다.
self-descriptive message -> 메시지 내용으로 온전히 해석이 가능해야 한다.
대부분 미디어 타입을 보면 그냥 json이라고 되어있지 이걸 어떻게 해석해야 되는가는 메시지를 보고서는 알 수 없다.
애플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다.
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head></head>
<body><a href="/test">test</a></body?
</html>
a 태그를 통해서 하이퍼링크가 나와있고, 이 하이퍼링크를 통해서 그 다음 상태로 전이가 가능하기 때문에 HATEOAS를 만족한다.
HTTP/1.1 200 OK
Content-Type: application/json
Link: </article/1>; rel="previous",
</article/3>; rel="next";
{
"title": "The second article",
"contents": "blah blah..."
}
Link라는 헤더가 이 리소스와 하이퍼링크로 연결되어 있는 다른 리소스를 가리킬 수 있는 헤더이다. HATEOAS를 만족한다.
웹 페이지들은 REST를 매우 잘 만족하고 있다.
모바일 앱은 위를 만족하지 않는다. 업데이트가 필요하다.
모바일 앱 클라이언트와 서버와 REST 아키텍쳐 스타일을 따르고 있지 않다.
상호운용성(interoperability)에 대한 집착
Roy T. Fielding
하이퍼텍스트를 포함한 self-descriptive한 메시지의 uniform interface를 통해 리소스에 접근하는 API
흔한 웹 페이지 | HTTP API | |
---|---|---|
Protocol | HTTP | HTTP |
커뮤니케이션 | 사람-기계 | 기계-기계 |
Media Type | HTML | JSON |
JSON 때문이구나.. 하는 추측을 할 수 있다.
HTML | JSON | |
---|---|---|
Hyperlink | 됨(a 태그 등) | 정의되어 있지 않음 |
Self-descriptive | 됨(HTML 명세) | 불완전* |
HTML 명세를 보면 HTML에 사용할 수 있는 모든 태그들이 정의되어 있다. 어떤 태그는 어떤 의미인가 하는 명세. JSON 오브젝트 안에 들어갈 수 있는 키 벨류가 어떤 의미를 가져야 하는가를 정의하지 않는다. 불완전 하다는건 적어도 문법은 정의되어 있다. 어떻게 파싱을 하라(중괄호, 대괄호), 어레이 어떻게 해석해라 하는 정의는 되어 있지만, 하지만 그 안에 들어가는 값들이 어떤 의미를 가져야 한다는 정의가 안되어 있다.
GET /tools HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<body>
<a href="https://tools/1">회사 가기</a>
<a href="https://tools/2">집에 가기</a>
</body>
</html>
Self-descriptive
1. 응답 메시지의 Content-Type을 보고 media type이 text/html 임을 확인한다.
2. HTTP 명세에 media type은 IANA에 등록되어 있다고 하므로, IANA에서 text/html의 설명을 찾는다.
3. IANA에 따르면 text/html의 명세는 http://www.w3.org.TR/html 이므로 링크를 찾아가 명세를 해석한다.
4. 명세에 모든 태그의 해석방법이 구체적으로 나와있으므로 이를 해석하여 문서 저자가 사용자에 알려 줄 수 있다.
HATEOAS
a 태그를 이용해 표현된 링크를 통해 다음 상태로 전이될 수 있으므로 HATEOAS를 만족한다.
GET /tools HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/json
[
{"id": 1, "title": "회사 가기"},
{"id": 2, "title": "집에 가기"}
]
Self-descriptive 하지 못하다.
1. 응답 메시지의 Content-Type을 보고 media type이 application/json임을 확인한다.
2. HTTP 명세에 media type은 IANA에 등록되어 있다고 하므로, IANA에서 application/json의 설명을 찾는다.
3. IANA에 따르면 application/json 명세는 draft-ieft-jsonbis-rfc7159bis-04 이므로 링크를 찾아가 명세를 해석한다.
4. 명세에 json 문서를 파싱하는 방법이 명시되어 있으므로 성공적으로 파싱한다. 그러나 id 가 무엇을 의미하고 title이 무엇을 의미하는지 알 방법이 없다.
HATEOAS 하지 못하다
다음 상태로 전이할 링크가 없다.
그런데 Self-descriptive와 HATEOAS가 독립적으로 진화에 어떻게 도움이 될까?
확장 가능한 커뮤니케이션
서버나 클라이언트가 변경되더라도 오고가는 메시지는 언제나 self-descriptive 하므로 언제나 해석이 가능하다.
애플리케이션 상태 전이의 late binding
어디서 어디로 전이가 가능한지 미리 결정되지 않는다. 어떤 상태로 전이가 완료되고 나서야 그 다음 전이될 수 있는 상태가 결정된다. 쉽게 말해서 링크는 동적으로 변경될 수 있다. 서버가 링크를 바꾼다 해도 클라이언트는 영향이 없다. 이동을 해야지만 그 하이퍼링크들을 읽고 다음으로 이동할 수 있는 경로를 알 수 있다.
방법1: Media type
1. 미디어 타입을 하나 정의한다.
2. 미디어 타입 문서를 작성한다. 이 문서에 id가 뭐고 title이 뭔지 의미를 정의한다.
3. IANA에 미디어 타입을 등록한다. 이때 만든 문서를 미디어 타입의 명세로 등록한다.
4. 이제 이 메시지를 보는 사람은 명세를 찾아갈 수 있으므로 이 메시지의 의미를 온전히 해석할 수 있다.
Content-Type: application/json patch+json
단점: 매번 media type을 정의해야한다.
방법2: Profile
Link <https://example.org/docs/todos>; rel="profile"
단점:
1. 클라이언트가 Link 헤더와 profile을 이해해야한다.
2. Content negotiation을 할 수 없다.