그놈의 Rest, RestAPI, RestFull API …
- 서버를 개발하고 회사의 JD(직무분석)를 분석하다보면, Rest 프로그래밍(설계) 이라는 단어를 자주 접하게 된다.
- 블로그나 유튜브를 보며 REST를 정의 했을때, REST란 자원의 상태를 URL에 담아 표현하는 것이라고 생각했다.
- 다른 개발자분들이 REST에 대해 정의를 해보라고 했을때 설명하기 난해하였고 설명이 진정한 REST가 맞냐는 말에 나는 대답을 하지 못했다.
그래서 REST 이놈이 어떤것인지 정확히 정의하기 위해 REST를 파보기로 했다.
REST(REpresentational State Transfer)정의?
- REST는 HTTP프로토콜을 그대로 활용하여 웹의 장점을 최대한 활용할 수 있는 아키텍처 원칙 세트이다.
- 즉, 리소스를 이름으로 구분하여 해당 리소스의 정보를 주고 받는 모든 것을 의미한다고 한다.
a way of providing interoperability between computer systems on the Internet.
- 인터넷상의 컴퓨터 시스템들간의 상호 운용성을 제공하는 방법
하지만, 이것만으로 설명하기는 난해하여 REST가 탄생한 배경을 살펴보자.
REST의 탄생 배경
WEB(1991년)
- www(월드 와이드 웹)이 팀 버너스리(인물) 에 의해 탄생했을 때 인터넷을 통해 자료(정보)들을 공유할 때 어떻게 하면 잘할 수 있을까 고민하게 되었다.
- 버너스리형은 정보들을 그 해답으로 하이퍼텍스트로 연결하여 제공했다.
HTML방식
으로정보를 표현
하고, 정보들에 대한식별자
로URI
를 만들고- 이러한 정보들을
전송하기 위한 방법
으로HTTP
라는 프로토콜을 만들었다.
HTTP / 1.0 (1994 - 1996년)
- 버너스리형이 만든 HTTP라는 프로토콜을 여러사람들이 설계를 하게 되었다.
- 1.0 명세가 나오기전에 이미
HTTP
는www
에 전송 프로토콜로 이용되고 있었다.
- 당시 대학원생이였던 로이필딩(Roy Fielding)이
HTTP / 1.0
참여하게 되었다. - 웹은 급속도로 성장하는 과도기였고 이시기에 HTTP를 정립하고 기존의 기능을 고쳐야하는 상황이였다.
HTTP
를 고치게 되면 기존 구축되어 있는 웹과 호환성에 문제가 생긴다.- 이 문제를 고민하던중 로이필딩은
HTTP Object Model
을 만든다.
REST(1998년)
HTTP Object Model
가 4년후REST
라는 이름으로 Microsoft Research에서 발표되어 세계 최초로 공개가 된다.
REST(2000년)
- 그 후 2년뒤 로이필딩(Roy Fielding)은
REST
를 박사 논문으로 발표했다. - 이 논문이 오늘 날 우리가 말하는
REST
이다.
프로토콜을 사용하는 API
API(Application Programming Interface)?
API
는 프로그램들이 서로 상호작용하는 것을 도와주는 매개체로 볼 수 있다.
XML - RPC(1998년) -> SOAP
- 원격으로 단일 시스템의 매서드를 호출할 수 있는 프로토콜을 Microsoft에서 만들었다.
- 오늘 날
SOAP(Simple Object Access Protocol)
이라는 이름의 프로콜이다.
Salesforce API(2000년 02월)
- 최초의 공개된 API지만 인기가 너무 없었다.
- 당시 SOAP을 사용해서 만들었는데 너무 복잡한 문제가 있었다.
[ 승부 ] SOAP API vs REST API
flickr API(2004년 8월)
- SOAP, REST방법을 제공했는데 당시 REST가 SOAP에 비해 장점이 많았다.
SOAP | REST |
---|---|
복잡 | 단순 |
규칙 많음 | 규칙 적음 |
어렵다 | 쉽다 |
REST API의 승리
- SOAP은 갈수록 인기가 적어지고 REST는 인기가 많아진다.
- 2006년, AWS가 자사 API의 사용량의 85%가 REST임을 밝힘.
- 2010년, Salesforce.com도 REST API를 추가했다.
로이필딩: 아 그거 REST 아닌데…
CMIS(2008) 등장
- CMS(콘텐츠 관리 시스템)를 위한 표준
- EMS, IBM, Microsoft등이 함께 작업
- REST 바인딩 지원
하지만 우리의 로이필딩형은…
로이필딩: 아 그거 REST 아님 ㅋㅋ…
Microsoft Rest Api Guidelines 발표(2016년)
- URI는 https://{serviceRoot}/{collection}/{id} 형식이어야 한다.
- GET, PUT, DELETE, POST, HEAD, PATCH, OPTIONS를 지원해야 한다.
- API 버저닝은 Major.minor로 하고 URI에 버전 정보를 포함시킨다.
- 등등…
사람들은 이것이 합리적인 좋은 REST API에 부합한다고 생각했다.
하지만 이번에도 로이필딩형은…
로이필딩: 아 그거 REST API
아님 ㅋㅋ HTTP API
임ㅋㅋ
로이필딩: REST API
를 위한 최고의 버저닝 전략은 버저닝 안하는거임ㅋㅋ
진정한 의미의 REST API 란?
REST API?
- REST 아키텍쳐 스타일을 따르는 API
REST?
- 분산 하이퍼미디어 시스템 (예: 웹)을 위한 아키텍쳐 스타일
- 아키텍쳐 스타일이면서 동시에 하이브리드 아키텍쳐 스타일
아키텍쳐 스타일?
- 제약조건의 집합
- 이를 모두 지키는것이 REST
REST를 구성하는 스타일
대체로 대부분 지켜지지만 잘 안지켜지는것이 unifrom interface이다.
- client-server
- stateless
- cache
- uniform interface
- layered system
- code-on-demand(optional)
- 서버에서 코드를 클라로 보내서 실행할 수 있어야한다.
- 자바스크립트를 의미
Uniform Interface가 뭐길래…?
지켜지고 있는 제약조건
- 리소스가 uri로 식별되면 된다.
(identification of resources) - 자원을 CUD할 때, uri에 표현을 담아서 전송하면 된다.
(manipulation of resources through representations
잘 안지켜지는 제약조건(로이형 스위치)
- 메세지는 스스로를 설명해야 한다.
(Self-descriptive message) - 애플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다.
(HATEOAS)
잘 지켜지지 않는 제약조건 예시를 보자
Self-descriptive message 예시
- 메세지는 스스로를 설명해야 한다.
예시) HTTP 요청 메세지
//[틀린예시]: 목적지가 빠져있으면 self-descriptive 하지않다.
GET / HTTP/1.1
//[옳은예시]: 목적지를 추가하면 self-descriptive 하게된다.
GET / HTTP/1.1
HOST: www.example.org
예시) HTTP 응답 메세지
//[틀린예시1]: self-descriptive 하지않다.
HTTP/1.1 200 OK
[{ "op":"remove", "path":"/a/b/c"}] - 어떤 문법인지 모름
//[틀린예시2]: self-descriptive 하지않다.
HTTP/1.1 200 OK
// 문법이 해석가능해 지지만 op, path가 무엇을 의미하는지 모름
Content-Type: application/json
[{ "op":"remove", "path":"/a/b/c"}]
//[옳은예시]: self-descriptive 하게된다.
HTTP/1.1 200
// 문법해석도 가능하고 op, path가 무엇을 의미하는지 미디어 정보가 json-patch+json으로 나타남
Content-Type: application/json-patch+json
[{ "op":"remove", "path":"/a/b/c"}]
HATEOAS를 만족한 예시
- 애플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다.
예시) 태그를 통한 방법
- <a태그>를 통해서 하이퍼링크가 나타나있고 이를 통해 하이퍼링크를 충족하여 전이
HTTP/1.1 200 OK
<html>
<head></head>
<body><a href="/test">test</a></body>
</html>
예시) Json에 나타나있는 Link
- Link를 통해 다른 리소스를 가르킬수 있고 하이퍼링크를 타서 정보를 제공
HTTP/1.1 200 OK
Content-Type: application/json
Link: </test/1>; rel="previous",
</test/3>; rel="next";
{json example...}
그래 쓰는방법은 대충 알겠어 근데 Uniform Interface를 지켜야해?
독립적 진화
- 서버와 클라이언트가 각각 독립적으로 진화한다.
- 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.
REST를 만들게 된 계기
- 어떻게 하면 기존 웹 HTTP를 깨뜨리지 않을수 있을까를 고민한 로이형의 고민의 산물
(How do I improve HTTP without breaking the Web?)
오늘 날 편하게 쓰는 웹
- 웹 페이지를 변경했다고 웹 브라우저를 업데이트 할 필요는 없다.
- 웹 브라우저를 업데이트 했다고 웹 페이지를 변경할 필요도 없다.
- HTTP 명세가 변경되어도 웹은 잘 동작한다.
- HTML 명세가 변경되어도 웹은 잘 동작한다.
반면 앱은?
- 업데이트 마다 동작에 문제가 생긴다.
- REST하지않기 떄문이다.
REST가 웹의 독립적 진화에 도움을 주었나?
- HTTP에 지속적으로 영향을 줌
- Host 헤더 추가
- 길이 제한을 다루는 방법이 명시(414 URI Too Long 등)
- URI에서 리소스의 정의가 추상적으로 변경됨: “식별하고자 하는 무언가”
- 기타 HTTP와 URI에 많은 영향을 줌
- HTTP/1.1 명세 최신판에서 REST에 대한 언급이 들어감
하위 호환성을 지키기 위한 노력(피땀눈물)
- HTML5 첫 초안에서 권고안 나오는데까지 6년
- HTTP/1.1 명세 개정판 작업하는데 7년
상호운용성(interoperability)에 대한 집착
???: 아 그거 어짜피 고쳐봤자 중요한것도아니고 고치면 웹 아예 안되는데 냅둬~
- Referer 오타지만 안고침
- charset 잘못 지은 이름이지만 안 고침
- HTTP 상태 코드 416 포기함(I’m a teapot)
- HTTP/0.9 아직 지원(크롬, 파이어폭스)
이를 고치는 순간 웹은 지옥으로…
REST는 성공?
- REST는 웹의 독립적 진화를 위해 만들어졌다.
- 웹은 독립적으로 진화하고 있다.
다시 돌아와서 오늘날의 REST API는?
- REST API는 REST 아키텍쳐 스타일을 따라야한다.
- 오늘 날 스스로 REST API라고 하는 API들의 대부분이 REST 아키텍쳐 스타일을 따르지 않는다.
로이형 API가 꼭 REST API여야 해요?
로이필딩: 시스템 전체를 통제할 수 있다고 생각하거나, 진화에 관심이 없다면, REST에 대해 따지느라 시간을 낭비하지 마라.
로이필딩: 제발… 제약조건을(저작권) 따르던지 아니면 HTTP API 같은 다른 단어를 써라.
오늘날의 API는 REST가 잘 안되는 이유?
일반적인 웹과 비교해보자.
– | HTML | HTTP API |
---|---|---|
프로토콜 | HTTP | HTTP |
커뮤니케이션 | 사람-기계 | 기계-기계 |
Media Type | HTML | JSON |
HTML vs JSON
– | HTML | JSON |
---|---|---|
Hyperlink | ㅇ(a태그 등…) | x |
Self-descriptive | ㅇ(HTML 명세) | 불완전 |
- 문법 해석은 가능하지만, 의미를 해석하려면 별도로 문서가(API 문서 등) 필요하다.
Self-descriptive와 HATEOAS가 독립적 진화에 어떻게 도움이 될까?
Self-descriptive 확장 가능한 커뮤니케이션
- 서버나 클라이언트가 변경되더라도 오고가는 메시지는 언제나 self-descriptive하므로 언제나 해석이 가능하다.
HATEOAS 애플리케이션 상태 전이의 late binding
- 어디서 어디로 전이가 가능한지 미리 결정되지 않는다. 어떤 상태로 전이가 완료되고 나서야 그 다음 전이될 수 있는 상태가 결정된다.
(링크는 동적으로 변경될 수 있다.)
가짜 REST API를 진짜 Rest API으로 만드는 방법
Self-descriptive: Media type 방법
- 미디어 타입을 하나 정의한다.
- 미티어 타입 문서를 작성한다
(이 문서에 "id"가 뭐고 "title"이 뭔지 의미를 정의한다.) - IANA에 미디어 타입을 등록한다.
(이 때 만든 문서를 미티어 타입의 명세로 등록한다.) - 이제 이 메세지를 보는 사람은 명세를 찾아갈 수 있으므로 이 메세지의 의미를 온전히 해석할 수 있다.
GET ...
HOST:...
HTTP ...
// 미디어 타입을 정해주고 키의 의미를 정의한다.
Content-Type: application/vnd.todos+json
[
{"id":1, "title":"회사 가기"},
{"id":1, "title":"회사 가기"}
]
Media type 등록은 필수인가?
로이필딩: 하지만 하면 좋다 난 쉽던데?
Media type 단점
- 매번 media type을 정의해야 한다.
Self-descriptive: Profile 방법
- "id", "title"의 의미를 정의한 명세를 작성한다.
- Link 헤더에 profile relation으로 해당 명세를 링크한다.
- 메세지를 보는 사람은 명세를 찾아갈 수 있으므로 이 문서의 의미를 온전히 해석할 수 있다.
GET ...
HOST:...
HTTP ...
Content-Type: application/json
// profile relation으로 해당 명세를 링크
Link: <https://example.org/docs/todos>; rel="profile"
[
{"id":1, "title":"회사 가기"},
{"id":1, "title":"회사 가기"}
]
Profile 단점
- 클라이언트가 Link 헤더(RFC 5988)와 profile(RFC 6906)을 이해해야 한다.
- Content negotiation을 할 수 없다.
Content negotiation(콘텐츠 협상)??
- 웹 브라우저(user-agent)가 이용자에게 알맞은 형태의 리소스를 받을 수 있도록, 리소스를 어떤 형태로 받을지 정하는 메커니즘을 일컫는다. 이때 리소스의 형태는 문서의 언어나 이미지 포맷, 인코딩 등을 말한다.
HATEOAS: data로 표현하는 방법
- data에 다양한 방법으로 하이퍼링크를 표현한다.
GET ...
HOST:...
HTTP ...
Content-Type: application/json
// profile relation으로 해당 명세를 링크
Link: <https://example.org/docs/todos>; rel="profile"
[
{
//data에 다양한 방법으로 하이퍼링크를 표현한다.
"link":"http://example.org/todos/1",
"title":"회사 가기"
},
{
"link":"http://example.org/todos/1,
"title":"회사 가기"
}
]
data표현 단점
- 링크를 표현하는 방법을 직접 정의해야한다
- 기존 API를 많이 고쳐야한다.(침투적)
HATEOAS: HTTP 헤더로 표현하는 방법
- Link, Location 등의 헤더로 링크를 표현한다.
POST ...
Content-Type: application/json
{
"title":"제목"
}
HTTP/1.1 204 No Content
// Link, Location 등의 헤더로 링크를 표현한다.
Location: /todos/1
Link: </todos/>; rel="collection"
HTTP 헤더표현 단점
- 정의된 relation만 활용한다면 표현에 한계가 있다.
마무리 정리
- 오늘날 대부분의 "REST API"는 사실 REST를 따르지 않고 있다.
(로이: 그러니 가짜다.) - REST의 제약조건 중에서 특히 Self-Descriptive와 HATEOAS를 잘 만족하지 못한다.
- REST는 긴 시간에 걸쳐(수십년) 독립적으로 진화하는 웹 애플리케이션을 위한 것이다.
- REST를 따르겠다면, Self-descriptive와 HATEOAS를 만족시켜야 한다.
- REST를 따르지 않겠다면, REST를 만족하지 않는 REST API를 뭐라고 부를지 정해야 할 것이다.
- HTTP API라던가 그냥 REST API라고 부를 수도있지만 로이필딩이 싫어할 것이다.
참고자료
HTTP 콘텐츠 협상
유튜브 - 그런 REST API로 괜찮은가
벨로그 - 진정한 RestFull API
REST,REST API, REST FULL API
'CS' 카테고리의 다른 글
로드밸런서(Load Balancer)란? (0) | 2023.10.13 |
---|---|
동기와 비동기 (0) | 2023.10.13 |
프로세스 스레드 (0) | 2023.10.13 |
AXIOS가 뭐하는 녀석인지? - 비동기 통신, Promise, Ajax, HTTP, (0) | 2023.02.16 |