REST API란 무엇인가?
공부 배경
백엔드 개발자로서 REST API를 개발하는 것은 기본 소양이라고 생각했다. 또 많은 기업들이 핵심 역량으로 요구하는 능력이기도 하다. 그럼에도 불구하고, 나는 ‘Controller, RestController정도를 사용하며 프로젝트를 만들 수 있으면 그게 REST API를 만들 수 있는거 아닌가?’하며 대수롭지 않게 여겼었다. 그러다가 관련 강의 또는 영상을 찾아보던 중 그런 REST API로 괜찮은가?라는 유튜브 영상을 접하게 되었고, 그동안 완전히 잘못 알고있었던 REST API의 개념에 대해 공부하고 정리해보는 계기가 되었다.
그런 REST API로 괜찮은가?를 보고…
REST
WEB (1991)
어떻게 인터넷에서 정보를 공유할 것인가?
이에 대한 해답으로 Web이 출범하고 아래를 따른다.
정보들을 하이퍼텍스트로 연결한다
- 표현 형식 : HTML
- 식별자 : URI
- 전송 방법 : HTTP
HTTP/1.0(1994-1998)
Roy T. Fielding : “How do I improve HTTP without breaking the Web?”
Roy T. Fielding 이란 사람이 대학원생 시절 HTTP/1.0 프로토콜 작업에 참여하면서, HTTP를 적립하고, 명세에 기능을 더하고, 기존의 기능을 고쳐야 하는 상황에서 기존에 이미 구축되어 있는 웹과의 호환성에 문제가 생기기 어렵다는 것을 느끼게 되었다.
“어떻게 하면 웹을 망가뜨리지 않고 기능을 개선시킬 수 있을까?”를 고민하였고, 이를 해결하고자 HTTP Object Model을 만들었다. 이는 4년 후에 REST라는 이름으로 발표 된다.
REST(1998)
REpresentational State Transfer : An Architectural Style for Distributed Hypermedia interaction (MicroSoft Reasearch에서 발표)
REST(2000)
“Architectural Styles and the Design of Network-based Software Architectures” (박사 논문으로 발표)
API
XML-RPC(1998)
Microsoft가 원격으로 다른 시스템에 메소드를 호출할 수 있는 XML-RPC 프로토콜을 만든다. 이는 곧 SOAP라는 이름으로 바뀌고 Salesforce라는 회사가 인터넷으로 최초 공개한다.
Salesforce API(2000.2)
SOAP 형태
이는 너무 복잡하여 많이 쓰이지 않았고, flickr에서 SOAP과 REST형태로 더욱 간단한 API를 발표했다.
flikr API
SOAP 형태
REST 형태
SOAP | REST |
---|---|
- 복잡 - 규칙 많음 | - 간단 - 규칙 적음 |
이는 REST API 사용률이 증가했으며 결국 2006년에 AWS는 자사 API의 사용량의 85%가 REST임을 밝혔다.
그것은 REST가 아니다
CMIS 출현(2008)
- CMS를 위한 표준
- EMC, IBM, Microsoft등이 함께 작업
- REST 바인딩 지원
Roy T. Fielding : “No REST in CMIS”
Microsoft REST API Guidelines 발표(2016)
- URI는 https://{serviceRoot}/{collection}/{id} 형식이어야 함.
GET, PUT, DELETE, POST, HEAD, PATCH, OPTIONS를 지원해야함.
- API 버저닝은 Major.minor로 하고 URI에 버전 정보를 포함시킨다.
”s/REST API/HTTP API/” (REST API가 아니고 HTTP API이다.)
“REST API must be hypertext-driven”
“REST API를 위한 최고의 버저닝 전략은 API 버저닝을 안하는 것”
REST API란 무엇인가?
REST API
REST 아키텍쳐를 따르는 API
분산 하이퍼미디어 시스템(ex.웹)을 위한 아키텍처 스타일아키텍쳐 스타일 = 제약 조건의 집합
REST를 구성하는 아키텍처 스타일
- Client - Server
- Stateless
- Cache
- Uniform Interface
- Layered System
- Code-on-Demand (optional)
HTTP만 잘 따라도 Client-Server, Stateless, Cache, Layered System 제약 조건은 지킬 수 있다.
Code-on-Demand는 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 한다는 것을 의미하며, 이것은 자바스크립트를 의미한다. 이는 필수는 아니다.
하지만 Roy T. Fielding이 REST가 아니라고 말하는 것들은 대부분 Uniform Interface 제약 조건을 만족하지 못하기 때문이다.
Uniform Interface
- Identification of resources
- Manipulation of resources through representations
- Self-descriptive messages
- Hypermedia as the engine of application state(HATEOAS)
Identification of resources은 URI로 리소스가 식별되면 된다는 것이고, Manipulation of resources through representations는 representation 전송을 통해서 리소스를 조작해야된댜는 것이다. 즉, 리소스를 만들거나 삭제, 수정할 때 http 메시지에 그 표현을 전송해야된다는 것이다.
위 2가지 조건은 대부분 잘 지켜지고 있다. 하지만 문제는 아래 2개이다. 이 2가지는 사실 우리가 REST API라고 부르는 거의 모든 것들은 지키지 못하고 있다.
Self-descriptive messages
메세지는 스스로를 설명해야 한다
1
GET / HTTP/1.1
단순히 루트를 얻어오는 GET 요청이다. 하지만 이는 Self-descriptive 하지 못하다.
1
2
GET / HTTp/1.1
Host: www.example.org
이 처럼 호스트 헤더에 도메인 명을 기재를 통해 목적지를 추가하면 Self-descriptive 하게 된다.
왜 IP주소가 아닌 도메인? → 하나의 IP주소에 복수의 도메인이 존재 가능하기 때문에
또 이런것도 생각 해 볼 수 있다.
200 응답 메세지이며, JSON 본문이 있다
1
2
HTTP/1.1 200 OK
[ { "op": "remove", "path": "/a/b/c" } ]
이렇게 되면 Self-descriptive 하지 않는데, 그 이유는 이걸 클라이언트가 해석하려고 하면, 어떤 문법으로 작성된 것인지 모르기 때문에 해석에 실패한다. 그렇기 때문에 Content-Type 헤더가 반드시 들어가야한다.
1
2
3
4
HTTP/1.1 200 OK
Content-Type: application/json
[ { "op": "remove", "path": "/a/b/c" } ]
Content-Type 헤더에서 대괄호, 중괄호, 큰따옴표의 의미가 뭔지 알게 되어, 파싱이 가능하여 문법을 해석할 수 있게 된다.
그렇다면 이제 Self-descriptive하다고 볼 수 있는가? 아니다.
우리는 op
값은 뭐고, path
값은 무엇을 의미하는지 이를 봐서는 알 수가 없다.
1
2
3
4
HTTP/1.1 200 OK
Content-Type: application/json-patch+json
[ { "op": "remove", "path": "/a/b/c" } ]
이렇게 명시를 하면 완전해진다. 이 응답은 ‘이것은 json-patch+json이라는 미디어 타입으로 정의된 메시지이다’ 라고 명시해 줌으로써, json-patch라는 명세를 찾아가서 이해한 다음, 이 메시지를 해석을 하면 그제서야 올바르게 메시지의 의미를 이해할 수 있게 된다.
HATEOAS
애플리케이션의 상태는 HyperLink를 이용해 전이 되어야 한다.
이렇게 페이지에 있던 링크를 따라가면서 전이했기 때문에 HATEOAS라고 할 수 있다.
1
2
3
4
5
6
7
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head> </head>
<body> <a href="/test"> test </a> </body>
</html>
HTML에서는 이렇게 a태그
를 통해 하이퍼링크를 넣어 다음 상태로 전이가 가능하게하고, 이는 HATEOAS를 만족 시킨다.
1
2
3
4
5
6
7
8
9
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..."
}
JSON의 경우 Link 헤더
를 통해 하이퍼링크 연결을 한다.
왜 Uniform Interface를 지켜야 하는가?
독립 적 진화
- 서버와 클라이언트가 각각 독립적으로 진화한다.
- 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.
- REST를 만든 계기 : “How do I imporve HTTP without breaking the Web”
서버의 기능이 바뀌고, 새로운 API가 추가되고, 기존 API가 변경 및 삭제되며, URI가 바뀌어도, 클라이언트는 바뀌지 않아도 된다.
REST API에 대한 결론
- REST API를 구현하고 REST API라고 부른다.
→ REST 제약 조건을 따른다. - REST API 구현을 포기하고 HTTP API라고 부른다.
- REST API가 아니지만 REST API라고 부른다. (현재 상태)
→ Roy T. Fielding이 만족 못할 뿐.
“I am getting frustrated by the number of people calling any HTTP-base interface a REST API… Please try to adhere to them or choose some other buzzword for your API.” - Roy T. Fielding
제발 제약 조건을 따르던지 아니면 다른 조건을 써라 - Roy T. Fielding