REST 는 REpresentational State Transfer의 약자이다.
a way of providing interoperability between computer systems on the Internet.
즉,REST에서 정의한 제약 조건을 모두 지켜야 REST를 따른다고 말할 수 있다는 것이다.
사실 REST는 아키텍처 스타일이면서 하이브리드 아키텍처 스타일 이라고 말한다.
왜냐하면 아키텍처 스타일이면서, 동시에 아키텍처 스타일의 집합이기 때문이다.
전글을 참조하면 좋다.
Code-on-Demand는 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 한다는 것을 의미하며, 즉 자바스크립ㅂ트를 의미한다.
대체로 REST라고 부르는 것들은 위의 조건을 대부분 지키고 있다.
HTTP만 잘 따라도 Uniform Interface를 제외하곤 다 지킬 수 있기 때문이다.
하지만 Uniform Interface는 잘 지켜지지 않는다고 한다.
위 2가지 조건은 대부분 잘 지켜지는 반면, 아래 2가지 조건이 잘 지켜지지 않는다고 한다.
예를들어 아래와 같은 메세지가 있다고 해보자
GET / HTTP/1.1
단순히 루트를 얻어오는 GET 요청이다.
이 HTTP 요청 메세지는 뭔가 빠져 있어 self-descriptive하지 못하다.
우선 목적지가 빠져있다.
GET /HTTP/1.1
Host: www.example.org
이 요청이 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" } ]
그렇다면 이제 Self-descriptive하다고 볼 수 있는가는 아니다.
해석했다고 하더라도, op 값은 무슨 뜻이고, path가 무엇을 의미하는지는 알 수 없다.
HTTP/1.1 200 OK
Content-Type: application/json-patch+json
[ { "op": "remove", "path": "/a/b/c" } ]
이렇게 작성을 하면 완전해진다.
이 응답은 json-patch+json이라는 미디어 타입으로 정의된 메시지 이기 때문에 json-patch라는 명세를 찾아가 이 메세지를 해석하면 올바르게 메세지의 의미를 이해할 수 있게 된다.
이처럼 Self-descriptive message라는 것은 메시지를 봤을 때 메시지의 내용으로 온전히 해석이 다 가능해야된다는 것이다.
애플리케션의 상태는 HyperLink를 이용해 전이되어야 한다.
이렇게 상태를 전이하는 것을 애플리케이션 상태 전이라 하고, 이 상태 전이마다
항상 해당 페이지에 있던 링크를 따라가면서 전이 했기 때문에 HATEOAS라 할 수 있다.
그래서 html 같은 경우는 HATEOAS를 만족하게 되는데,
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head> </head>
<body> <a href="/test"> test </a> </body>
</html>
a 태그를 통해 하이퍼 링크를 통해 다음 상태로 전이가 가능하기 때문에 만족한다고 볼 수 있다.
JSON으로 표현하면
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..."
}
Link라는 헤더가 있는데, 이것이 바로 이 리소스와 하이퍼링크로 연결되어 있는 다른 리소스를 가르킬 수 있는 기능을 제공해준다.
여기서 어떤 1개의 게시물을 표현 했는데, 이전의 게시물 URI가 /articles/1, 다음 게시물은 /articles/3에 있다는 정보를 표현해준 것이다.
또한, 이 정보는 Link 헤더가 이미 표준으로 문서가 나와 있기 때문에 이 메시지를 보낸 사람이 온전히 해석해서 어떻게 링크가 되어 있는가를 이해하고 하이퍼링크를 타고 다른 상태로 전이가 가능하다.
How do i improve HTTP without breaking the Web
어떻게 웹이 깨지지 않고 HTTP를 개선할 수 있는가 이다.독립적으로 진화를 한다면 ??
서버의 기능이 바뀌고, API가 추가되고 변동이 생겨도, 클라이언트는 바뀌지 않아도 된다.
이를 위해서는 Unifrom Interface가 필수적이기기에, 이를 만족하지 못하면 REST라고 부를 수 없는 것이다.
바로 웹이다.
하지만 모바일 앱은 많은 문제가 있다고 한다.
서버의 기능이 변경되었는데, 클라이언트가 그거을 지원해주는데 한계가 있을 때
업데이트를 진행하는 것이다.
이는 모바일 앱 클라이언트 와 서버가 REST아키텍처 스타일을 따르지 않고있다 라고 말할 수 있다.
웹은 어떻게 가능한 것인가?
25년전 Referer 오타를 냈다.
charset이라는 이름을 잘 못 지었다.
하지만 고치지 않는다 왜?
이름을 고치게 되면 상호운용성이 깨지기 때문이다.
HTTP 상태코드 416도 만우절때 만들었던 코드인데 http가 아니라 상관이 없었지만, 이미 몇몇 서버들이 이를 HTTP상태 코드로 구현해 버렸다.
그래서 416코드를 아예 영구 결번으로 만들어 버렸다.
이렇게 상호 운용성에 대한 많은 노력과 시행착오가 모여 덕분에 독립적인 진화를 할 수 있다.
시스템 전체를 통제할 수 있다 ?
진화에 관심이 없다 ?
하지만 우리는 둘다 어려우니... REST를 따라야 한다.
웹과 API를 비교해보면,
커뮤니케이션이 다르다.
HTTP API는 사람이 아닌 기계가 해석한다.
또한 미디어 타입이 다르다.
self-descriptive 측면에서 보면 JSON은 불완전하다.
완전 하다는 것은 적어도 문법은 정의되어 있다.
어떻게 파싱하고 array를 어떻게 해석해라 까지는 되어있다.
하지만 안에 들어갈 수 있는 key-value에 대한 의미는 아무도 정의되지 않는다.
즉, 문법은 해석 가능하지만 의미를 해석하려면 별도로 문서(API 문서 등)가 필요하다.
self-descriptive message
HATEOAS