티스토리 뷰
DEVIEW 2017 세션 중 하나인 그런 REST API로 괜찮은가를 듣고 정리한 내용입니다.
REST API는 무엇인지, REST를 구성하는 6가지의 제약조건 중 오늘날 대부분의 REST API가 만족시키지 못한다는 self-descriptive messages와 HATEOAS란 무엇인지 중심으로 정리했습니다.
REST API?
- REST 아키텍처 스타일을 따르는 API
- REST : 분산 하이퍼미디어 시스템(웹)을 위한 아키텍처 스타일
- 아키텍처 스타일 : 제약조건들의 집합
- 즉, 제약조건을 모두 만족해야 REST하다고 말할 수 있다.
REST의 구현 원칙을 제대로 지키는 시스템 => RESTful
REST를 구성하는 스타일 (= 제약 조건)
- client-server
- stateless
- cache
- uniform interface
- layerd system
- code on demand (opional)
HTTP만 잘 지켜도 client-server
, stateless
, cache
, layerd system
이 네가지는 만족할 수 있다. code on demand
는 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 하는 javascript를 말한다. 이 조건은 optional이므로 반드시 만족시키지 않아도 된다.
참고 : 이 글에서는 self-descriptive messages와 HATEOAS 설명이 중심이기 때문에 나머지 제약조건에 대한 내용은 생략했다.
uniform interface의 제약조건
- identification of resources : 리소스가 URI로 식별되면 된다.
- manipulation of resources through representations : 메시지를 통한 리소스 조작
- self-descriptive messages : 자기 서술적 메세지
- hypermedia as the engine of application state(HATEOAS) : 애플리케이션 상태에 대한 엔진으로서의 하이퍼미디어
오늘날 REST API라 불리는 것들 중 대부분이 self-descriptive messages
와 HATEOAS
를 만족시키지 못하고 있다.
self-descriptive messages
메시지 스스로 메시지에 대한 설명이 가능해야 한다.
GET / HTTP/1.1
- 이 HTTP 요청 메시지는 목적지가 어딘지 모르기 때문에 self-descriptive하지 못하다.
GET / HTTP/1.1
HOST : www.example.org
www.example.org
라는 목적지를 추가하면 self-descriptive하다.
GET / HTTP/1.1 200 OK
[{"op": "remove", "path" : "/a/b/c"}]
- 클라이언트가 이 응답을 해석할 때 어떤 문법으로 작성된건지 모른다. =>
Content-Type
필요
GET / HTTP/1.1 200 OK
Content-Type : application/json
[{"op": "remove", "path" : "/a/b/c"}]
- 클라이언트가 이 응답이 json 타입인 것을 알게 되었다.
- 하지만 self-descriptive하다고는 할 수 없다.
op
와path
가 어떤 의미인지 모르기 때문이다.
Content-Type : 엔티티 바디에 포함되는 오브젝트의 미디어 타입을 전달한다.
GET / HTTP/1.1 200 OK
Content-Type : application/json-patch+json
[{"op": "remove", "path" : "/a/b/c"}]
application/json-patch+json
은 미디어 타입으로 정해져 있는 메시지다.- 명세를 찾아가서 메시지를 해석할 수 있기 때문에 self-descriptive하다.
참고 : JSON Patch
HATEOAS
클라이언트에 응답할 때 결과 데이터만 제공해주기보다 URI를 함께 제공해야 한다는 원칙이다.
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 : </articles/1>; rel="previous",
</articles/3>; rel="next";
{
"title" : "The second article"
"contens" : "blah blah..."
}
<html>
<head></head>
<body><a href="/test">test</a></body>
</html>
- 링크 헤더(
Link
)는 표준으로 문서가 나와있다.- 이 메시지를 보는 사람이 온전히 해석해서 이 하이퍼링크를 타고 다른 상태로 전이가 가능하다. 때문에 HATEOAS를 만족한다.
왜 uniform interface?
- 독립적인 진화를 하기 위해서
독립적 진화
- 서버와 클라이언트가 각각 독립적으로 진화한다.
- 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.
- REST를 만들게 된 계기 :
"How do I improve HTTP without breaking the web"
uniform interface를 만족시키지 못하면 REST하지 못하다.
self-descriptive messages와 HATEOAS가 독립적 진화에 어떻게 도움이 될까?
self-descriptive messages
- 확장 가능한 커뮤니케이션
- 서버나 클라이언트가 변경되더라도 오고 가는 메시지는 언제나 self-descriptive하므로 언제나 해석이 가능하다.
HATEOAS
- 애플리케이션 상태 전이의 late binding
- 어디서 어디로 전이가 가능한지 미리 결정되지 않는다. 어떤 상태로 전이가 완료되고 나서야 그 다음 전이될 수 있는 상태가 결정된다.
- 쉽게 말해서, 링크는 동적으로 변경될 수 있다. 서버 링크가 바뀌면 클라이언트는 바뀐 링크만 보고 따라가기만 하면 된다.
REST API로 만들어보자
self-descriptive
1. Media Type
GET /todos HTTP/1.1
Host : example.org
HTTP/1.1 200 OK
Content-Type : application/vnd.todos+json
Link : <https://example.org/docs/todos>; rel=""profile"
[
{"id": 1, "title": "회사 가기"}
{"id": 2, "title": "집에 가기"}
]
- 미디어 타입 하나 정의한다.
- ex)
application/vnd.todos+json
- ex)
- 미디어 타입 문서를 작성한다. 이 문서에
id
,title
의 의미를 정의한다. - IANA에 미디어 타입을 등록한다. 이 때 만든 문서를 미디어 타입의 명세로 등록한다.
단점은 매번 Media Type을 정의해야 한다는 것이다.
2. Profile
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": "집에 가기"}
]
id
,title
의 의미를 정의한 명세를 작성한다.- Link 헤더에 profile relation으로 해당 명세를 링크한다.
- 메시지를 보는 사람은 명세를 찾을 수 있으므로 이 문서의 의미를 온전히 해석할 수 있다.
이 방법의 단점은 클라이언트가 Link 헤더(RFC 5988)와 profile(RFC6906)을 이해해야 한다. 그리고 Content negotiation을 할 수 없다.
HATEOAS
1. data
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"
{
{
"link": "https://example.org/todos/1"
"title": "회사 가기"
},
{
"link": "https://example.org/todos/2"
"title": "집에 가기"
}
}
- data에 다양한 방법으로 하이퍼링크를 표현한다.
단점은 링크를 표현하는 방법을 직접 정의해야 한다는 것이다.
2. JSON으로 하이퍼링크를 표현하는 방법을 정의한 명세를 활용
JSON API
HAL
UBER
Siren
Collection+json
참고자료
'Seminar' 카테고리의 다른 글
[Kotlin+Spring] #살아있다 #자프링외길12년차 #코프링2개월생존기 정리 (0) | 2022.06.21 |
---|---|
[Kotlin+Spring] 어디 가서 코프링 매우 알은 체하기 정리 (0) | 2022.06.20 |
- Total
- Today
- Yesterday
- CGLIB프록시
- HtmlUtils
- 정규표현식 패턴
- AOP
- FileNameFilter
- Best Time to Buy and Sell Stock
- 그런RESTAPI로괜찮은가
- 정규표현식 플래그
- java8 stream
- getCanonicalPath
- github actions 구성요소
- getPath
- file
- 정규경로
- github actions 기초
- 코프링
- Longest Consecutive Sequence
- 문자열인코딩과 문자집합의 차이
- opencsv
- csv to bean
- MPEG-2 TS
- 다이나믹프록시
- websocket handshake
- hls.js
- 특수문자 치환
- csv 라이브러리
- github actions components
- getAbsolutePath와
- self-descriptive
- sockjs
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |