말 그대로 메시지가 스스로 설명되어야 한다는 것입니다. 메시지의 모든 요소는 메시지만 보고 그 뜻을 알아야 한다는 것을 의미합니다.
서버의 API변경(추가, 수정 삭제), URI변경 등 기능이 수정되어도 클라이언트는 문제없이 돌아가야 합니다. 만약 서버의 기능이 수정되어 클라이언트도 변경할 때 Self-descriptive messages를 사용하면 개발자가 요청의 의미를 쉽게 파악할 수 있어 이해도를 높일수 있습니다.
결론적으로, REST API를 구현하는데 Self-descriptive messages는 API의 이해도, 유지보수성, 재사용성을 높이는 데 중요한 역할을 합니다.
1
GET / HTTP/1.1
목적지가 빠져있어 이해하기 어렵다.
2
GET / HTTP/1.1 Host: www.example.org
목적지 주소가 존재하기 때문에 어떤 메시지인지 파악이 가능하다. self-descriptive 하다고 할 수 있습니다.
1
HTTP/1.1 200 OK [ { "id": "example123", "name": "홍길동" } ]
이 응답에선 어떤 자원인지는 확인할 수 있지만 어떤 형식(포맷)으로 작성된 정보인지 응답해주지 않았기 때문에 해석에 실패합니다. 따라서 self descriptive 조건을 만족하지 않는다. 라고 할 수 있겠죠?
그렇기 때문에 응답할 때 HTTP 헤더에 Content-Type이 반드시 들어가야 합니다.
2
HTTP/1.1 200 OK Content-Type: application/json [ { "id": "example123", "name": "홍길동" } ]
헤더에서 Content-Type이 명시되어 자원의 대괄호, 중괄호, 큰따옴표의 안에 있는 의미가 어떤 형식의 데이터인지 알게 되어, 파싱이 가능하여 문법을 해석할 수 있게 됩니다.
하지만 그걸 해석했다고 하더라도 id 값은 무슨 뜻이고, name이 무엇을 의미하는지는 알 수 없습니다. self descriptive라는건 "id"와 "name"이 의미하는 바를 명시하라는 것인데, 어떻게 알려줄 수 있을까?
3
HTTP/1.1 200 OK Content-Type: application/json-patch+json [ { "id": "example123", "name": "홍길동" } ]
Media type을 정의하는 방법으로 명시하면 완전해집니다. 이 응답은 json-patch+json이라는 미디어 타입으로 정의된 메시지이기 때문에 json-patch라는 명세를 찾아가서 이해한 다음, 이 메시지를 해석을 하면 그제야 올바르게 메시지의 의미를 이해할 수 있게 됩니다.
메시지의 내용으로 온전히 해석이 다 가능해야 된다는 것입니다.
- 서버가 제공하는 내용을 클라이언트는 미디어 타입을 정의한다
- 미디어 타입 문서를 작성한다. 이 문서에 id가 무엇이고 title이 무엇인지 의미를 정의한다
- IANA에 미디어 타입을 등록한다. 이 때 만든 문서를 미디어 타입의 명세로 등록한다.
- 그 미디어 타입을 리소스 리턴할 때 Content-type 으로 사용한다
- 이제 이 메시지를 보는 사람은 명세를 찾아갈 수 있으므로 이 메시지의 의미를 온전히 해석할 수 있다.
💨 단점
매번 media type을 정의해야 해서 효율적이지 않다.
IANA를 지원하지 않는 경우도 있다.
- id가 무엇인지 title이 무엇인지 의미를 정의한 명세를 작성한다.
- Link 헤더에 profile relation으로 해당 명세를 링크한다.
- 이제 메시지를 보는 사람은 명세를 찾아갈 수 있으므로 이 문서의 의미를 온전히 해석할 수 있다.
💨 단점
클라이언트가 Link 헤더와 profile을 이해해야한다.
브라우저가 스펙 지원을 안한다..
따라서 매번 Media type을 정의하는게 번거롭고, profile 링크 헤더를 브라우저에서 지원하지 않기 때문에, HATEOAS를 구현하는데 사용되는 형식인 HAL의 데이터에 명세의 링크를 추가하는 방법을 사용합니다.
HATEOAS 구현은 다음 글에서 이어서하겠습니다!