DEVIEW2015 이응준님의 강연을 정리한 글입니다. (https://tv.naver.com/v/2292653#comment_focus)
학습 목표
· REST란?
· REST의 탄생
· API의 역사 - SOAP과 REST
· REST API
- REST를 구성하는 제약조건
- 문제의 발단 - uniform interface
· Uniform Interface의 제약조건
- self-descriptive messages
- HATEOAS
- Uniform Interface 제약조건이 필요한 이유
· 웹 페이지는 REST 설계가 잘되지만, API는 잘 안되는 이유
- JSON을 Self-descriptive하게 만드는 방법
- JSON을 HATEOAS하게 만드는 방법
REST란?
· REpresentational State Transfer(대표적인 상태 전달)의 약자
· 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일
- 아키텍처 스타일: 제약조건의 집합이다. 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반을 일컫는다.
· 컴퓨터 시스템간의 상호 운용성을 제공하는 방식 중 하나
REST의 탄생
· 1991년 WWW(World Wide Web)이 팀버너스리에 의해 탄생하였다.
이때 인터넷에서 효과적으로 정보를 공유하기 위해 모든 정보를 하이퍼텍스트로 연결했고,
표현형식을 HTML, 식별자를 URI, 전송 방법을 HTTP로 정했다.
· HTTP 설계 작업에 참여자였던 로이필딩은 웹과 HTTP가 이미 사용되고 있는 시점에
어떻게 웹 호환성을 지키면서 HTTP 기능을 개선(HTTP 명세에 기능 더하고, 기존의 기능 수정 등) 할지에 대한 고민으로 했다.
· 이에 대한 해결책으로 HTTP Object Model을 만들었고, 몇 년 후 REST라는 이름의 논문으로 발표하였다.
API의 역사 - SOAP과 REST
· 1998년 마이크로소프트는 XML-RPC라는 원격으로 다른 시스템의 메서드를 호출할 수 있는 시스템을 만든다.
이후 이것은 SOAP이라는 이름으로 바뀐다.
· 2000년 Salesforce는 SOAP 기반의 최초의 API를 만든다.
하지만 이것은 너무 복잡했다.
· 2004년 flickr는 SOAP과 REST 기반의 API를 각각 만들었다.
아래 각 API의 이미지를 보면, REST API가 SOAP API에 비하여 단순하고, 규칙이 적음을 알 수 있다.
SOAP
REST
· 이러한 이유로 REST는 SOAP 보다 월등한 인기를 얻게 되었다.
REST API
· REST 아키텍쳐 스타일을 따르는 API
· REST API의 인기가 뜨거워지면서 많은 사람들이 REST API라는 용어를 사용하게 되었지만,
사람들이 생각하는 REST API와 창시자 로이필딩이 생각하는 REST API는 달랐다.
REST를 구성하는 제약조건
1. client-server
- 클라이언트-서버의 각 파트가 독립적으로 개선될 수 있도록 하자.
2. statelessness
- 각 요청 간 클라이언트의 콘텍스트가 서버에 저장되어서는 안 된다.
3. cache
- 클라이언트는 응답을 캐싱할 수 있어야 한다.
4. uniform interface, 인터페이스 일관성
- 일관적인 인터페이스로 분리되어야 한다.
5. layered system
- 요청된 정보를 검색하는 데 관련된 서버(보안, 로드 밸런싱 등을 담당)의 각 유형을 클라이언트가 볼 수 없는 계층 구조로 체계화하는 계층화된 시스템.
6. Code on demand (선택사항)
- 서버에서 클라이언트로 코드를 보내서 수행시킬 수 있어야 한다. ex) 자바스크립트, 자바 애플릿
문제의 발단 - uniform interface
· 6가지 조건 중 uniform interface를 제외한 것들은 HTTP만 잘 따라도 자연스럽게 다 지켜지는 사항이었다.
Uniform Interface의 제약조건
1. identification of resources, 자원의 식별
- 리소스는 uri로 식별된다. 요청 내에 기술된 개별 자원을 식별할 수 있어야 한다.
ex) 웹 기반의 REST 시스템에서의 URI의 사용을 예로 들 수 있다. htts://{serviceRoot}/{collection}/{id}
2. manipulation of resources through representations, 메시지를 통한 리소스의 조작
- HTTP에 표현을 담아 전송하여 리소스를 조작해야한다.
3. self-descriptive messages, 자기서술적 메시지
- 메세지는 스스로를 설명해야한다.
4. hypermedia as the engine of application state (HATEOAS), 애플리케이션의 상태에 대한 엔진으로서 하이퍼미디어
- REST API라고 알려진 거의 모든 API들이 3, 4번 제약 조건은 거의 지키지 못하고 있다.
self-descriptive messages
· 메시지는 스스로를 설명해야한다.
▶ 예시: self-descriptive하지 못한 메시지
GET / HTTP/1.1
· 위 메시지는 목적지가 빠져있다. 이것을 다음과 같이 수정할 수 있다.
GET / HTTP/1.1
Host: www.example.org
▶ 예시: self-descriptive하지 못한 메시지
HTTP/1.1 200 OK
[{ "op": "remove", "path": "/a/b/c" } ]
· 위 메시지는 어떤 문법으로 쓰였는지 알 수 없기 때문에 클라이언트가 파싱할 수 없기 때문에 self-desciptive하지 못하다.
이것을 다음과 같이 수정하면, 클라이언트는 대괄호, 중괄호, 큰따움표가 무엇을 의미하는 지 이해할 수 있다.
HTTP/1.1 200 OK
Content-Type: application/json
[{ "op": "remove", "path": "/a/b/c" } ]
· 하지만 이렇게 개선된 위 메시지 또한 self-desciptive하지 못하다. "op", "path"가 무엇을 의미하는 지 알 수 없기 때문이다.
이 메시지는 JSON Patch(https://en.wikipedia.org/wiki/JSON_Patch) 미디어 타입의 메시지다.
이것을 명시해야 클라이언트는 JSON Patch 명세를 찾고, 이것을 토대로 메시지를 온전히 이해할 수 있게 된다.
HTTP/1.1 200 OK
Content-Type: application/json-patch+json
[{ "op": "remove", "path": "/a/b/c" } ]
hypermedia as the engine of application state (HATEOAS)
· 애플리케이션의 상태는 Hyperlink를 이용해 전이되어야한다.
▶ 예시: HTML을 통한 HATEOAS를 만족하는 메시지
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head></head>
<body><a href="/test">test</a></body>
</html>
· <a> 태그의 하이퍼링크를 통하여 다음 상태로 전이할 수 있다.
▶ 예시: JSON을 통한 HATEOAS를 만족하는 메시지
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 헤더는 해당 리소스와 관련된 다른 리소스를 가리킬 수 있는 기능을 제공한다.
Uniform Interface 제약조건이 필요한 이유
· 독립적 진화를 하기 위해서
- 로이 필딩이 REST를 만들게 된 계기: "How do I improve HTTP without breaking the Web"
- 서버와 클라이언트가 각각 독립적으로 진화한다.
- 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.
· 실제로 REST를 만족하는 사례: 웹
- 웹 페이지를 변경했다고 웹 브라우저를 업데이트할 필요 없다.
- 웹 브라우저를 업데이트했다고 웹 페이지를 변경할 필요 없다.
- HTTP 명세가 변경되어도 웹은 잘 동작한다.
- HTML 명세가 변경되어도 웹은 잘 동작한다.
웹 페이지는 REST 설계가 잘되지만, API는 잘 안되는 이유
· 웹 페이지 vs HTTP API
웹 페이지 | HTTP API | |
Protocol | HTTP | HTTP |
커뮤니케이션 | 사람-기계 | 기계-기계 |
Media Type | HTML | JSON |
· HTML vs JSON
웹 페이지 | HTTP API | |
Hyperlink | a 태그 등을 이용 | 정의 x |
self-descriptive | HTML 명세가 존재 | 불완전 |
· HTML이 명세가 존재하는 것에 비하여 JSON의 키, 값에 무엇이 있어야하는가는 정의되어 있지 않다.
때문에 JSON의 의미를 해석하려면 별도로 API 문서가 필요하다.
JSON을 Self-descriptive하게 만드는 방법
· 방법 1
1. 미디어 타입을 정의한다.
2. 미디어 타입 문서를 작성하고, "title"의 의미와 "contents"의 의미를 정의한다.
3. IANA에 미디어 타입을 등록하고, 이때 만든 문서를 미디어 타입 명세로 등록한다.
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
Link: </articles/1>; rel="previous",
</articles/3>; rel="next";
{
"title": "The second article",
"contents": "blah blah..."
}
- 단점: 매번 media type을 정의해야한다.
· 방법 2
1. "title"의 의미와 "contents"의 의미를 정의 명세를 작성한다.
2. Link 헤더에 profile relation으로 해당 명세를 링크한다.
3. 메시지를 보는 사람은 명세를 찾아갈 수 있으므로 이 문서의 의미를 온전히 해석할 수 있다.
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
Link: </articles/1>; rel="previous",
</articles/3>; rel="next";
<http://example.org/docs/todos>; rel="profile"
{
"title": "The second article",
"contents": "blah blah..."
}
- 단점: 1. 클라이언트가 Link 헤더(RFC 5988)와 profile(RFC 6906)을 이해해야한다.
2. Content negotiation을 할 수 없다.
JSON을 HATEOAS하게 만드는 방법
· 방법 1: data에 다양한 방법으로 하이퍼링크를 표현한다.
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
Link: </articles/1>; rel="previous",
</articles/3>; rel="next";
<http://example.org/docs/todos>; rel="profile"
{
"account": {
"account_number": 12345,
"balance": {
"currency": "usd",
"value": 100.00
},
"links": {
"deposits": "/accounts/12345/deposits",
"withdrawals": "/accounts/12345/withdrawals",
"transfers": "/accounts/12345/transfers",
"close-requests": "/accounts/12345/close-requests"
}
}
}
- 단점: 링크를 표현하는 방법을 직접 정의해야한다.
· 방법 1-2: JSON으로 하이퍼링크를 표현하는 방법을 정의한 명세들을 활용한다. ex) JSON API, HAL, Collection+json
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!"
}
}, {
"type": "articles",
"id": "2",
"attributes": {
"title": "Rails is Omakase"
}
}]
}
- 단점: 기존 API를 많이 고쳐야한다. (침투적)
· 방법 2: Link, Location(Hyperlink를 표현할 수 있는 헤더) 등의 HTTP 헤더로 링크를 표현한다.
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
Location: /todos/1
Link: </todos/>; rel="collection"
{
"title": "The second article",
"contents": "blah blah..."
}
- 단점: 정의된 relation만 활용한다면 표현에 한계가 있다.
출처
'네트워크' 카테고리의 다른 글
TCP vs UDP (0) | 2022.01.23 |
---|---|
[Network] 다양한 종류의 로드밸런서(Load Balancing)와 다양한 로드밸런싱 알고리즘 (0) | 2021.11.29 |
분산 서버 환경에서 세션 공유 문제 해결하기 (0) | 2021.11.29 |
[Chrome] Chrome 브라우저 NET :: ERR_CERT_INVALID (인증서)문제 해결 (0) | 2020.11.12 |
WebRTC란? (0) | 2019.02.27 |
댓글