HTTP 완벽가이드 3장
회사에서 진행 중인 ‘HTTP 완벽가이드 릴레이 세미나’ 3장 발표 자료.
https://docs.google.com/presentation/d/1obobW34ipdOqN1oGThDia92hgbKW-q7VVW1T0owHtM8/edit?usp=sharing
내용
- HTTP 스펙의 변화
- HTTP 메시지 문법
- HTTP 메소드
- HTTP 응답 코드
- 주요 헤더
회사에서 진행 중인 ‘HTTP 완벽가이드 릴레이 세미나’ 3장 발표 자료.
https://docs.google.com/presentation/d/1obobW34ipdOqN1oGThDia92hgbKW-q7VVW1T0owHtM8/edit?usp=sharing
내용
REST에 관해 연구했던 내용을 공개하고 가장 많이 받은 피드백은,
‘간단히 말해보라’는 것이었다.
간단한 문제가 아니라서 여전히 간단히는 말할 수는 없지만,
널리 퍼지기 좋게 몇 가지 문장으로 (자극적으로!) 정리할 필요를 느꼈다.
이 글 조차도 다 읽지 않고 비판하는 사람이 많을 것을 알고 있지만,
나는 계속 REST라는 용어를 함부로(!) 쓴다고 해서 비난하지 않는다.
REST라는 용어를 쓰지 말라고도 하지 않고, 잘못 썼다고 그 사람을 폄하하지도 않는다.
어느 누구도 설득하고 싶지 않다.
다만 REST가 우리에게 주는, 변화와 확장에 대응하라는 교훈을 좀 더 알리고 알리고 싶다.
연구했던 내용을 짧게 줄여 한장에 정리해보겠다.(이미 글이 길어진 기분이지만..)
중간 중간 아래 연재 목록에 어떤 내용이 담겨 있는지 설명한다.
Senior Principal Scientist at Adobe, co-founded Apache, authored the REST architectural style and Web standards for URI, HTTP/1.x, and URI Templates.
온라인에서 보게되는 RESTful API라고 부르는 것 대부분은 로이 필딩의 의도에 반한다.
- 그가 만들었으니 그가 옳다!
몇 가지 잘못 사용되는 수준이 아니라 반대 방향을 바라보고 있다.
2008년 로이 필딩은 블로그에서 이에 관해 비판했지만, 육아를 시작한 후로 더 이상 이야기가 없다. (트위터에선 여전하시다)
2008년에 로이가 한 이야기를 해석해 본 것이 - 5. REST - Roy가 입을 열다
사람들은 REST가 구현하기 어렵다고 하는데,
이런 건 REST의 문제가 아니다. 단지,
사람들의 오해를 단적으로 보여주는 글을 읽고, 여기 달린 100여개의 댓글을 번역하고 정리한 것이 - 4. REST - REST 좋아하시네
그렇다고 REST가 쉽다는 건 아니다. 로이 필딩은 논문이 전문가를 위한 것이라고 언급했다.
논쟁에서 가장 흔히 등장하는 이야기가 Form에서 GET, POST만 지원해서 REST를 적용하기 어렵다인데, 이를 위해 특별히 2. REST - HTML Form에서 GET/POST만 지원하는 이유도 조사했다.
REST가 최종적으로 추구하는 건 효율적이고 확장가능한 시스템이다.
이를 위해 6가지 제약조건(하나는 optional)을 제시했다.
조금 비약해서 소개하자면
로이는 네트웍 기반의 효율적이고 확장가능한 시스템을 만들기 위해선 이 제약조건이 필요할 것으로 생각했고, 이 조건을 만족하면 REST한 시스템이라고 할 수 있다.
이 제약조건에 대해 더 자세히 설명한 것은 - 3. REST - 논문(요약) 훑어보기
API 문서를 옆에 끼고 개발을 해야만 한다면,
API를 수정하려는데 클라이언트에 문제가 생기지 않을까 걱정을 하고 있다면,
UI와 백엔드가 독립적으로 진화할 수 없게 단단히 결합되었다고 볼 수 있다.
로이 필딩은 hypertext의 역할이 가장 중요하다고 강조한다.
response에 링크를 쉽게 추가해주는 ‘HATEOAS 지원 라이브러리’같은 것도 꽤 보이는데,
단순히 다른 페이지에 대한 링크를 추가하는 것 만으로는 부족하다.
사실 웹 문서가 아닌 바에야, 시스템 전체를 관통하는 인터페이스로써 hypertext를 설계하기가 쉽지 않다고 생각한다.
내가 이 부분을 명확하게 설명하기 위해선 사례 연구가 더 필요하다.
로이는 요청/응답 트랜잭션 이외의 영역에서 의존해야할 정보가 있다면, 그건 표준이어야 한다는 생각인 것 같다.
세상엔 별별 표준이 다 만들어진다.
API를 내부 시스템으로 한정하면 독자적인 표준도 가능할 것이다.
그 똑똑한 개발자들 간 10여년이 넘는 시간 동안 용어를 잘못 쓰고 있는 이유는 나도 의아한데, ROA에서 그나마 원형을 발견할 수 있었다.
Leonard Richardson의 RESTful Web Services의 한국어 번역서은 절판 상태.
행복한 아빠님의 블로그에 정리된 게 있어서 참고했다.
마틴 파울러가 Richardson의 Maturity Model을 소개한 블로그를 썼는데, 지앤선 블로그에 번역이 되어있다.
REST에서 ROA로, 여기서 개발자들에게 전달되면서 소위 말하는 REST 규칙이 생겨난 것 같다.
가족오락관 게임처럼..
소위 REST라고 할 때 어떤 것을 떠올리는가?
하지만 지금 이 순간부터 REST라는 용어가 나타나면 유심히 살펴보자.
그 많은 REST라는 용어로부터 확신할 수 있는 형식이 무엇이 있는가?
‘CRUD를 위한 네가지 HTTP 메소드를 쓴다’정도?
루비 온 레일즈와 같은 프레임웍에서 이를 더 부추겼다는 의견도 있다.
하지만 난 당신의 API가 REST가 아니라 해도 괜찮다고 말해주고 싶다.
REST가 아니라도 실패한 디자인이 아니라고 말해주고 싶다.
난 RESTful API를 만들 생각은 ‘아직’ 없다.
이런 이야기를 적은 것이 - 6. REST - 당신이 만든 건 REST가 아니지만 괜찮아
여기선 Your API isn’t RESTful — And That’s Good이라는 블로그의 내용을 번역했는데,
이런 혼란을 종식 시키고 RESTful 대신 RESOURCEful이라는 용어를 정의해서 모범 사례를 구축하자는 주장이다.
우리가 원하는 바로 그 API의 모습이 담겨있다.
최초 누가 주장했는지는 잘 모르겠지만 이 블로그는 2016년 초에 발행됐으며, RESOURCEful이라는 용어의 사용은 점점 증가하는 추세다.
Laravel의 문서에서도 5.3버전(2016년 9월)부터 RESTful이라는 용어가 제거됐다.
이 내용으로 8월달 MPUG 정기 모임에서 발표한 자료도 걸어둔다.
예전 발표자료 정리하기 2탄
한번 훑어주면 튜닝하는 데 꽤 도움된다.(그 동안 개판으로 튜닝했다는 말)
Real MySQL이란 책에서 explain 부분만 대략 보고 정리했는데, 일단은 회사에서 innodb만 쓰니까 관련 부분만 훑어봤다.
오늘 누가 MyISAM이랑 차이가 뭐냐고 물어봤을 때, 입력이 느리다고 말을 했던가?
뭐 틀린 말은 아닌 것 같은데;; table-level lock 때문에.
암튼 트랜잭션 지원 안 함. (아 이걸 이야기 할 것을…)
MyISAM은 외래키 지원도 안 되는구만. 본 것도 같고.
새로 이사온 집에 뚫어놓은 하수구에 물 내려가듯 지식이 빠져나가 큰일이다.
브랜든 아이크나 제임스 고슬링 이런 사람들은 나이가 먹어도 뇌가 잘 돌아가겠지? 기억력도 유지되는지 참 궁금하다.
그 사람들은 술을 안 먹기라도 하는 걸까?
라는 질문을 맥주를 마시면서 하고 있는데, 예거 쯔비켈이라는 맥주가 편의점에서 8월에만 6캔 9,900원에 팔고 있다.
1,650원에 마시기에는 꽤꽤꽤 괜찮은 맥주임!
애드센스 승인을 받으려면 글을 꾸준히 쓰거나 404로 떨어지는 링크가 없어야 한다는 말이 있어서 최근 발표자료나 올려봐야겠다.
자료 : Resource Hints and Preload
prefetch를 비롯한 resource hints와 preload에 대해 연구한 결과.
사실 원래 코드에는 회사 소스 구조도 있었지만, 논란이 될 수 있으니 제거하고 공유한다.
발표일 : 2017년 6월
bsidesoft 블로그에 Jobs에 대한 내용이 올라왔다.
여튼, Jobs에 대한 글 중간에
<!--소용없음. 그냥 async 선언과 동일--> |
“안타깝게도 이 옵션은 직접 태그에 쓰면 소용없고 동적으로 스크립트를 만든 경우에만 적용할 수 있습니다.”라고 나와있어서,
스펙에서는 어디에 나와있는가 질문을 드렸더니 다음과 같은 답변이 달렸다.
…www.w3.org/TR/html51/semantics-scripting.html…
여기에 가시면 script엘리먼트객체의 속성인 async IDL attribute에 대한 작동에 대해 자세히 기술하고 있습니다.
The async IDL attribute controls whether the element will execute in parallel or not. If the element’s “non-blocking” flag is set, then, on getting, the async IDL attribute must return true, and on setting, the “non-blocking” flag must first be unset, and then the content attribute must be removed if the IDL attribute’s new value is false, and must be set to the empty string if the IDL attribute’s new value is true. If the element’s “non-blocking” flag is not set, the IDL attribute must reflect the async content attribute.
분명 훑어보았던 부분인데 IDL attribute를 이해 못해서 그냥 넘어갔던 부분이다.
반성의 의미로 스펙을 좀 더 읽고 내 질문에 대한 답을 정리해본다.
우선 <script async="false" src="1.js"></script>
에서 async가 false로 설정 안 되는 이유.
script element 스펙에는 “The async and defer attributes are boolean attributes“라는 말이 나오는데,
boolean-attribute란 attribute로 명시하는 것 만으로 true가 된다.
즉, async=”true”든 async=”false”든 모두 async가 설정된 것으로 본다.
checked, disabled 같은 애들이 다 boolean-attribute다.
따라서 스크립트를 추가된 순서대로 실행하려면 attribute에서 async를 생략해야 하지만,
그렇게 하면 또 병렬(parallel) 로 로드가 안 되는 문제가 생기게 된다.
그럼 동적으로 삽입된 스크립트에서 가능한 이유는 뭘까?
//js에서 동적로딩하는 경우 |
script element 스펙에 나오는 문장을 이해하기 위해 IDL attribute부터 알아보자.
스택오버플로우에서 답을 찾아봤다.
IDL이란 말은 Web IDL spec에서 왔습니다.
이 문서는 Web IDL이라는 인터페이스 정의 언어를 정의하고, 이는 웹 브라우저 내에서 구현하려는 인터페이스를 설명하는데 사용될 수 있습니다.
Web IDL은 IDL의 일종으로 웹 플랫폼에서의 공통적인 스크립트 객체의 동작을 보다 쉽게 정의될 수 있게 해주는 많은 기능을 갖추고 있습니다.
Web IDL로 설명된 인터페이스가 ECMAScript 실행 환경 내의 구조에 어떻게 대응되는지 또한 이 문서에서 자세히 설명합니다.
Contents attibute란 마크업에서 나타나는 attribute입니다.
<div id="mydiv" class="example"></div> |
여기서 id와 class는 attribute죠. 일반적으로 content attribute는 이에 상응하는 IDL attribute를 갖고 있습니다.
…생략
JavaScript 안에서 IDL attribute는 종종 property라고 불리는데, JavaScript에게는 DOM 객체의 property로써 노출되기 때문입니다.
보통 content attribute와 IDL attribute는 짝을 이루지만, 반드시 둘이 호환되는 건 아닙니다.
…생략 (<option> element의 초기값을 예로 든다)
결국 우리가 JavaScript 개발자로서 인식하는 property가 바로 IDL attribute란 개념을 가리키고 있다.
contents attribute라 함은 일반적으로 attribute라고 생각하는 그 마크업 상에 노출되는 바로 그것.
이제 async에 관한 HTML5.1의 script쪽 명세를 다시 보자.
The async IDL attribute controls whether the element will execute in parallel or not.
Async IDL attribute는 element가 병렬로 실행될 지를 결정한다.
If the element’s “non-blocking” flag is set, then, on getting, the async IDL attribute must return true, and on setting, the “non-blocking” flag must first be unset, and then the content attribute must be removed if the IDL attribute’s new value is false, and must be set to the empty string if the IDL attribute’s new value is true.
Element의 “non-blocking” 플래그가 설정되면, 값을 가져올 때는 async IDL attribute가 true를 반환해야만 하고, 설정할 때는 “non-blocking” 플래그는 일단 해제한다. 이후 IDL attribute의 새로운 값이 false이면 content attribute는 제거, true이면 빈 값을 설정한다.
If the element’s “non-blocking” flag is not set, the IDL attribute must reflect the async content attribute.
Element의 “non-blocking” 플래그가 설정되지 않았다면, IDL attribute는 반드시 async content attribute를 반영(연동)해야 한다.
참고로 값을 가져올 때 현재 content attribute 값을 리턴해야 하는 경우 reflect란 용어를 쓰고 있는데 나는 이를 ‘반영(연동)’이라고 번역했다.
간단히 console 창에서 테스트해보자.
var s = document.createElement('script');
를 통해 생성한 후 바로 s.async
를 보면 true가 나온다.
처음 스크립트가 생성될 때는 “non-blocking” 플래그가 설정되기 때문이다.
Element의 “non-blocking” 플래그가 설정되면, 값을 가져올 때는 async IDL attribute가 true를 반환해야만…
이제 한 문장은 이해한 것 같은데, 어려운 용어가 더 생겼다.
“non-blocking” 플래그라는 게 뭘까?
“non-blocking” 상태를 이해하기 위해 우선 HTML 도큐먼트의 파싱과정을 보자.
“non-blocking”에서 block하는 대상은 HTML의 파싱이다.
보통 네트웍 계층에서 input stream으로 데이터를 넘겨주지만, 실행중인 스크립트로부터 받아들이기도 한다.
document.write가 대표적인데, 여기서 쓰는 데이터는 input stream에 섞여 들어간다.
<ul> |
ul 사이에 li가 제대로 자릴 잡기 위해선 input stream으로부터 가 나타나기 전까지만 데이터를 읽어들이고,
document.write가 포함된 스크립트 구문 실행하면 <li>hello</li>
부분이 input stream에 추가되고,
파서가 non-block 상태가 되면 다시 input stream으로부터 문자를 받아오는데,
<li>hello</li>\n</ul>
순으로 가져오게 된다.
이런 이유로 script 태그는 기본적으로 HTML 파싱을 막는다.
외부 스크립트도 마찬가지인데,
<script src="external.js"></script> |
파서는 를 만나면 src에 명시된 파일을 다운로드하고, 실행하기를 기다린 후에야 파싱을 재개할 수 있다.
그럼 “non-blocking” 상태는 스펙에서 어떻게 설명하는지 보자.
Initially, script elements must have this flag set.
Script element는 초기 플래그 값으로 non-block으로 설정된다.
It is unset by the HTML parser and the XML parser on script elements they insert.
HTML/XML 파서가 script element를 삽입하면서 이 플래그가 해제된다.
그러니까 HTML 파서에 의해 생성된 스크립트 태그는 기본적으로 fetch/실행하는 동안 HTML 파서를 block 블럭하게 된다.
In addition, whenever a script element whose “non-blocking” flag is set has an async content attribute added, the element’s “non-blocking” flag must be unset.
추가적으로, “non-blocking” 플래그가 설정된 script element에 async content attribute가 추가되면, element의 “non-blocking” 플래그는 해제된다.
이 부분은 script element 쪽에서도 언급이 되니 같이 살펴보자.
If the element’s “non-blocking” flag is set, then, on getting, the async IDL attribute must return true, and on setting, the “non-blocking” flag must first be unset, and then the content attribute must be removed if the IDL attribute’s new value is false, and must be set to the empty string if the IDL attribute’s new value is true.
Element의 “non-blocking” 플래그가 설정되면, 값을 가져올 때는 async IDL attribute가 true를 반환해야만 하고, 설정할 때는 “non-blocking” 플래그는 일단 해제한다. 이후 IDL attribute의 새로운 값이 false이면 content attribute는 제거, true이면 빈 값을 설정한다.
최초 script element를 생성할 때는 “non-blocking” 플래그가 설정되기 때문에 async가 true를 반환하는 것은 이미 확인했다.
…설정할 때는 “non-blocking” 플래그는 일단 해제한다.
이 글을 한참이나 쓰고 있는 이유가 이 때문인데, async를 추가하는데 왜 “non-blocking”을 해제하는 걸까? 이런 의문으로 너무 혼란스러웠다.
그러니까, async가 “non-blocking” 상태 아님?하는 의문이다.
나만 빼고 다들 잘 이해를 하고 있는지, “non-blocking” 플래그에 대한 질문도 찾기 쉽지 않다.
여러가지 가정을 하고 스펙을 여러번 읽어본 결과,
브라우저는 “non-blocking” 플래그가 없어도 async로 병렬처리 여부를 확인할 수 있다라고 나름의 결론을 냈다.
왜 병렬로 다운로드 받는가에 대해선 스펙상에서 찾을 수는 없었는데, 어쩌면 다운로드를 병렬로 받는 건 중요하지 않겠다는 생각도 든다.
다운로드는 왜 병렬로 처리되는 걸까?
스펙에서 찾은 건 아니지만, 원래 다운로드는 그냥 알아서 병렬로 다운받는 거 아닌가?
브라우저 별로 동시 다운로드 받을 수 있는 개수가 다르긴 한데, 어쨌든 아래와 같은 일반적인 script 태그를 써도 동시에 다운로드 받는 걸 볼 수 있다.
<script src="small.js"></script> |
현대 브라우저에서 외부 리소스를 다운로드할 때는 fetcher라는 놈에게 위임하고,
(아마 이런 놈들)
Fetcher는 캐시를 확인하거나 각종 다운로드 받을 파일을 나름의 우선순위로 다운로드 한다.
그럼 fetch는 어차피 병렬이 기본인 거고(혹은 브라우저 마음일테고),
async도 “non-blocking” 플래그와 마찬가지로 HTML 파서가 스크립트를 해석하는 순서, 즉 실행 순서를 결정 짓는 것 뿐이란 말인가.
아직 자신은 없다.
차근 차근 각 상황을 되짚어 보자.
우선 async가 없는 일반적인 동적 스크립트 생성 시
다음으로 async가 true로 설정되는 경우
다음으로 스크립트로 xxx.async = false
로 처리하면 왜 병렬로 fetch하고 실행은 순서대로 하는지 살펴보자.
스펙에 의하면 async는 병렬로 ‘실행’할지를 제어한다.
bigScript.async = false; |
OK. 실행이 순서대로 되는 건 알겠다.
결국 async는 비동기 다운로드와는 관계가 없고, 애초에 실행 순서만 관련있었던 것 같다.
async - Execute script in parallel
스펙에 써있는 그대로다.
참고
연재 목록
로이 필딩의 논문을 읽지 못해 생긴 부채를 여기 한장에 남겨둔다.
언젠가 돌아보다 생각나면 진짜 논문을 읽을 날이 오겠지.
그럼 그 때까지, REST in peace!
연재 목록
Update: “Your API isn’t RESTful — And That’s Good”에 대한 요약번역본은 숨겨놨다가, 원문을 쓴 Trevor Reed에게 요약본을 번역하여 퍼뜨리는 것에 대해 댓글로 문의한 후, 재배포함.
여러 동영상을 찾아보다, 2016년에 진행중인 API 스펙들에 관해 이야기하는 강연을 봤다
이들 스펙 만으로는 RESTful하다고 볼 수는 없지만, hypertext에 대한 관점에 공감을 하며 이를 표준 스펙을 통해 풀어나가려는 시도가 이어지고 있다.
좋은 시도이고 꾸준히 발전하길 기원한다.
그러나 지금까지 다루었던 개발자들의 몰이해는 이런 실질적인 구현체가 없었기 때문인가?
튜토리얼 몇 번 따라하고 실무에 적용할 만 한가? 그러면 RESTful API가 될 수 있나?
어렵다고 본다.
사람들이 싸우는 것은 항상 이런 식이다.
수많은 논쟁을 지켜보면 든 생각은, REST에 대해 잘못 알고있는 사람들(어쩌면 당신과 나)을 비난하며 선을 긋지 말자는 것이다.
인터넷에 돌아다니는 99%의 글이, 그 좋은 회사(트위터, 페이스북…)에서 통용되는 용어들이, 단지 몇가지 URL 규칙과 HTTP 메소드가 필요했을 뿐인 사람들이 REST란 용어를 납치했다.
비슷한(?) 예로, 선풍기를 쐬고 자면 죽는다는 미신은 증명하기는 너무나 어렵고 오랜기간 광범위하게 퍼졌으며 전문가들도 경고했으며 모두가 믿기 때문에, 많은 이가 오늘도 타이머를 맞추고 잔다.
그러니까 난 지금 선풍기를 쐬고 자도 안 죽는다는 미신을 숭배하고 있다. 여전히 난 어떤 게 미신인지 증명할 수 없다.
REST뿐 아니라, IT뿐 아니라, 우리는 많은 것을 블랙박스 안에 넣어놓거나 혹은 추상화된 개념으로 이해하고 넘어간다.
블랙박스를 열어보니 다른 게 들어있었다면, 그저 예상과 달랐다고 담백하게 말해보자.
REST를 잘못 알고 있다고 해서, 그가 실력도 없고 뭔가를 자세히 알아볼 생각도 없는 겉멋든 사람이라고 할 수는 없다.
‘난 XX를 안다고 착각하는 부류를 알고 있어. 그런 사람들은 보통 XX한 사람들이지’라며 선풍기 타이머를 돌리지 말자는 이야기다. (물론 난 다른 이유로 타이머를 애용한다)
특정 관점이 다른 사람들을 경계 밖으로 몰아내 모든 교류를 끊지 않았으면 한다.
로이 필딩은 REST에 관한 논문은 전문가를 위한 논문이라고 언급한 적이 있다.
REST는 설계를 위한 지침이지 초심자도 따라할 수 있는 best practice를 제공하는 것이 아니다.
쉽게 말해, 어렵다.
사실 간단한 해결책이 있다.
이 모든 혼란은 REST이라는 용어를 쓰지 않으면 해결된다.
RESTful하지 않다는 것이 실패한 디자인이라는 뜻이 아니다.
다만, 그동안 통용됐던 의미의 REST를 통칭할 수 있는 새로운 용어가 필요하다는 말이다.
마지막으로 이 글을 읽어보자.
이 글에서 그동안 REST라고 잘못 명명된 몇가지 구현 원칙을 RESOURCEful API라는 새로운 이름으로 재정의하고 있다.
2016년 3월 31일에 발행된 Trevor Reed이란 사람의 블로그를 읽어보자.
https://medium.com/@trevorhreed/you-re-api-isn-t-restful-and-that-s-good-b2662079cf0e
현 상황을 가장 명확하게 정리한 글로 보인다.
Resource API Endpoints: |
여기부터는 REST를 알지 못하는 사람들을 이해해보려 좀 더 검색한 내용을 적어볼텐데, 대단한 근거는 없다.
나는 그토록 뛰어난 개발자들이, 게다가 영어권에 살면서 얼마든지 로이의 논문을 비오는 일요일 오후에 슬쩍 읽어볼 수 있을 사람들이 왜 이렇게 일관된(?) 오해를 하고 있는지 궁금했다.
그 기원을 좀 더 찾아보려고 뒤져본 바, ROA(Resource-Oriented Architecture)에서 찾을 수 있었다.
앞에서 잠시 언급했던 행복한 아빠님의 블로그를 보자.
REST(Representational State Transfer)는 HTTP의 주요 저자인 Roy Fielding의 2000년 논문에 의해 소개가 된 네트워크 아키텍처를 위한 구조이다. REST가 화두가 되면서 RET의 정체를 알아보기 위해 “RESTfull Web Services”를 읽고 이 책에서 말하는 Resource-Oriented Architecure(이하 ROA)를 나름대로 정리해 보았다.
ROA는 REST 기반(이하 RESTful) 웹서비스를 만들기 위한 문제점을 해결하는 방법을 제공한다.
ROA는 RESTful 아키텍처이다.
(충분히 못 찾은 것일 수도 있지만) 난 2008년도에 쓰인 이 글이 한국어로 된 것 중에 REST에 대해 이해하기 가장 좋은 글이라고 생각한다.
이 분이 공부했다는 것이 Leonard Richardson의 RESTful Web Services인데
한국어 번역서은 절판 상태.
대신 마틴 파울러가 이를 소개한 블로그를 썼는데, 마침 지앤선이 번역을 해놓았다(중간중간 이해하기 어려운 문장이 보인다면 원문을 참조하기 바란다).
여기까지 와도 아직 REST가 잘못 이해되진 않았다. 제대로 이해하고 구현하려는 시도로 보인다.
위에 소개한 “Your API isn’t RESTful — And That’s Good”에서 언급된 대로,
REST를 이루기 위한 여러 복합적인 요소/방법 중 자신의 결과물과 몇 가지 구현상의 공통점을 발견하고 REST란 용어만 납치했다고 봐야할 것 같다.
구현하기 쉬운 부분만 골라서 best practice set이 만들어진 게 아닐까.
하나만 기억하자,
서버와 클라이언트가 서로의 눈치를 보며 변화/발전을 두려워 하고 있다면(즉, 서로에게 강한 의존성을 갖고 있다면),
그건 REST가 아니다.(하지만 괜찮다. REST라고 안 부르면 되니까.)
서버와 클라이언트는 변화에 대응하기 위해 프로토콜/표준을 통한 약한 의존성을 가져야 한다.
아니 이건 수십년 간 소프트웨어 엔지니어링이 강조하고 있는 것이 아닌가!
마지막으로 아래의 관점도 생각해볼 만 하다.
REST API Design - Resource Modeling
혹시라도 이 긴 여정을 충실히 따라오신 독자가 있다면, 진심으로 고마움과 존경을 표한다.
연재 목록
‘RESTful APIs, the big lie’의 댓글 마지막 쯤 누군가 추천해 준 컨텐츠 몇 개를 소개해본다.
(이번에도 여전한 오역과 거친 의역에 대해 양해를 구하며…)
우선 당사자인 Roy 자신이 쓴 글이 꽤 재미있다.
“REST APIs must be hypertext-driven”이란 글이 꽤 유명한 것 같지만
이것 말고도 Roy가 2008년도에 REST에 관해 쓴 글을 보면 각기 나름의 재미가 있다.
예를 들어 이런 글, “POST 써도 괜찮아”
그 유명한 “REST APIs must be hypertext-driven“(REST API는 hypertext가 주도해야만 해)를 읽어보자.
난 사람들이 HTTP기반의 인터페이스를 REST API라고 부르는 것이 실망스럽다. “SocialSite REST API”라고 부르는, 그건 RPC다
API가 hypertext 주도로 동작하지 않는다면, RESTful하지 않고 REST API가 아니다. 어디 잘못된 매뉴얼이라도 돌아다니는 거야?
API 디자이너들은 당신의 창작물을 REST API라고 부르기 전에 아래 규칙들을 확인하기 바란다
Bjorg : 왜 hypermedia 대신 hypertext란 용어를 사용하는가?
SocialSite REST API에 대해 쓴 블로거(snoopdave)가 와서 댓글을 달았고, 로이가 그건 여전히 RPC 결과를 wrapping한 것 뿐이라고 반박한다
BillHiggins : 사람들이 자신이 REST를 만든다고 생각하는 이유는 뭐라고 생각해, 로이?
nkallen : 내가 생각하는 게 맞는 지 좀 알려줘.
TheOtherMarcus: 리소스와 타입, 가능한 동작을 식별하는 유명한 hypertext media type을 하나 소개해줄 수 있을까? 내가 새로운 아이템을 추가하는 POST를 작성한다고 할 때, 어떤 미디어 타입이 적당한 지 어떻게 표현해야 하지?
jdubray : 보통 하이퍼텍스트는 특정 리소스에서 허용되는 모든 작업을 알려주지 않아. 잠재적인 전환을 알려줄 뿐이지. 이런 전환에 대한 정확한 사전 지식이 없다면 코드를 짜는 게 얼마나 어려울 지 상상이 가. 리소스의 생명 주기(상태, 전환 등)가 변경되었을 때도 내 코드가 문제가 없을지 어떻게 알겠어?
tlainhart : 이 아키텍쳐 스타일에 대한 부정적인 반응 중 하나는 어떻게 그걸 효율적으로 구성할 수 있을까이다. 이를 위해 캐싱 서비스를 사용하는 것이 좋을 거라고 가정해도 될까?
TheOtherMarcus :
Robert Cernysays: 주어진 API가 RESTful한 지 알 수 있게, 또 글로만 적어줘서 고맙다. 지능이 발달한 인간이야 인터페이스의 추상적인 설명을 보고 REST인가를 결정할 수 있지만, 기계는 가능한가? 샘플 소스라도 좀 보내줄 수 있을까? 못 한다면, 왜?
30번 nkallen에 대한 답변
역주) 이후 링크가 깨진 트랙백이 다수…
Dima : 공개된 API 중에 실제로 RESTful하다고 생각한 게 있어? 내가 가진 문제는 보안을 수행하며 동시에 RESTful하게 유지하는 것이야. 보안이 필요한 요청을 보낼 때는 보통 이렇게 하지. GET /resource/11231231/token=KJGHY7687JKGH. POST를 쓰지 않는 한, 이보다 더 좋은 방법이 있을까?
역주) 이후엔 Roy의 답변이 없고, 블로그 몇 개를 더 썼다. 아래 colinjack이란 사람이 한 말은 의미있다
colinjack : DDD와 비교를 하면서, DDD도 오해를 겪고 사람들은 때로 중요하지 않은 부분에 집중을 하지만, Evans의 책이 살아있는 예제를 제공하고 그의 아이디어가 왜 중요한지를 보여준다. 그러나 REST에서는 웹에 많은 컨텐츠가 있지만, REST 전문가가 썼다 하더라도 새로 접하는 사람들에게는 거의 쓸모가 없다. 사실 좋은 REST 예제와 토론은 줄어들고 있고, 아마도 이런 REST라는 용어를 납치하게 된 이유가 된 것 같아. 여기에서 (RESTful하진 않지만) 현실적인 예제가 있긴 하다. (이 링크의 댓글을 보면 ‘REST’에서 ‘RE’는 빼고 ‘ST’에 대한 좋은 글이라는 비아냥이 있다)
GOTO 2014 • REST: I don’t Think it Means What You Think it Does • Stefan Tilkov
이것도 ‘RESTful APIs, the big lie’의 댓글에서 추천을 받은 동영상이다.
‘그건 REST가 아니야’류의 발표나 글은 참 많은데, 제대로 REST를 이야기하는 몇 안 되는 강연 중 하나라고 생각한다.
REST는 좋은 URL에 관한 것이다 -> 땡
REST = URI 패턴 + GET, PUT, POST, DELETE -> 비슷하지만, 땡
hypermedia apis = Responses with links -> 그게 다가 아니다
* Rule #1. Don’t have clients build URIs using string concatenation
* 대신, 레시피를 제공하라. 이것도 역시 hypermedia이다.
* 다음에 요청할 URI를 만들 수 있는 템플릿을 제공
* 이것도 표준이 있다 : https://tools.ietf.org/html/rfc6570
* 여기서 더 나아가면 default data를 제공하는 폼을 만들 수 있다. (43:20 지점)
REST = 서비스 인터페이스에 대한 색다른 접근 방식 -> 너무 단순한 표현이다
이번에도 별로 대단한 걸 얻은 것 같진 않다면 바로 결론으로 넘어가자.
연재 목록
이제 개발자들 사이에 널리 퍼진 REST에 대한 오해를 들춰볼 차례이다.
독자 입장에선 이 정성으로 그냥 논문을 읽지 그러냐는 의문도 들 수 있겠지만,
이 바닥의 수많은 오해를 발견하는 재미도 있었다.
자신을 “SPA (UI/UX/server) architect and author”라고 소개하고 있는
Michael S. Mikowski의 RESTful APIs, the big lie라는 자극적인 글과 댓글을 읽고 한번 정리해볼 필요가 있다고 생각했다.
댓글로 달려드는 모두가 REST나 API를 바라보는 관점이 다르고, 댓글을 읽으면서 ‘그래, 그렇지’하면서 나의 관점도 계속 흔들렸다.
내가 흔들렸던 이유는 이 글을 읽을 때는 막 REST에 대해 공부하기 시작했을 때였기도 했고, RESTful한 API를 만들기 위한 현실적인 고민들이 남일 같지 않았기 때문이기도…
그냥 REST라는 용어만 포기하면 편하다는 결론은 내 후속 블로그 글에서 다시 확인하시고, 일단 개싸움부터 들여다보자.
사실 블로그 자체는 REST를 이해하는데는 별로 도움이 안 되는 글이긴 한데, 이런 개싸움이야 말로 진짜 현실 세계(반 REST 진영이 가장 많이 언급하는 단어가 ‘real world’이다)의 문제인 듯!
주요 논점을 정리해보고, 딸린 댓글을 개발 새발 정리한 버전은 페이지 마지막에 붙여놓겠다.
우선 블로그에서 저자가 주장하는 바를 짧게 정리해보자.
HTTP 메소드와 응답코드는 모호해서 그 뜻이 정확히 뭘 의미하는지 사람마다 다르게 인식한다.
어떤 응답코드를 줄 지는 회사/사람마다 다른 기준이 있을 수 있어서, client 입장에선 정확히 예측하기 어렵다.
브라우저는 PUT과 DELETE같은 문법을 지원하지 않는다.
307 Temporary 같은 애들은 브라우저마다 상이하게 처리되기도 한다. 제대로 지원하는 건 200과 500뿐이다.
HTTP의 문법은 풍부하지 못해서 모든 어플리케이션의 요청과 응답을 표현할 수 없다.
그래서 REST로 통신할 때 문제가 생기면 7가지나 되는 조합으로 원인을 파악해야 한다.
이런 한계 때문에 어떤 문제가 발생했을 때, 디버깅을 위해 고려해야할 게 너무나 많다.
HTTP에 너무 종속되어 있다.
HTTP가 아닌 다른 전송 방식으로 전환하려면 또 저 7가지 조합을 고려해서 만들어야 한다.
그래서 제안하는 건, JSON-Pure APIs
블로그 본문과 댓글에서 발화한 여러 논쟁을 크게 묶어 정리해본다.
따지고 보면 그걸 모르는 사람의 문제지만, 현실적으로는 이해가 되는 부분도 있다.
어떤 응답 로직을 구현하기 위해 적합성 여부를 여러번 생각해야하는 것은 어쨌든 일종의 비용이라고 생각한다.
물론 이것은 REST의 문제가 아닌 구현상의 어려움일 뿐이다.
요청 메소드와 응답 코드가 모든 상황을 담아낼 수 없다는 의견도 있는데, 이 글에 동조하는 사람들은 거대한 엔터프라이즈 환경(ERP, 병원 시스템 등)에서 다양하고 복합적인 리소스를 다루는 상황에 대해 언급한다.
논쟁을 지켜보며 생각이 드는 것은 - 추측이지만,
메소드가 충분치 않다는 감정은 특히 RPC를 실행하는 경우,
그러니까 내부적으로 복잡한 로직이 섞여있을 때 발생하는 것 같다.
예를 들어 리퀘스트를 날려서 설거지와 빨래와 아이 목욕을 시킨다면, 여기서 리소스란 무엇일까? 이 때는 어떤 메소드를 써야하는가?
이 지점부터 한차례 혼란이 오는 것 같은데, 그 리퀘스트를 보내는 대상 리소스가 우리가 흔히 인식하는 리소스, 그러니까 CSS나 이미지같은 소위 정적 리소스 개념을 벗어나는 지점부터 어려워지는 것 같다.
HTTP에서 리소스란 뭐든 지 될 수 있다.
또한 REST를 CRUD로 치환하는 순간 이견은 좁혀지지 않는다.
조회/등록/수정/삭제를 GET/POST/PUT/DELETE로 처리하는 게 REST라고 생각하면 더 이상의 이성적인 논쟁은 불가능해진다.
HTTP 메소드가 부족하다고 생각이 드는 건 모든 RPC 요청의 성격을 CRUD에 매핑하려는 시도에 원인이 있다고 본다.
어떤 기분인 지는 알 것 같다.
REST API는 GET/POST/PUT/DELETE를 쓰는 것 -> 곧 조회/등록/수정/삭제를 의미 -> RPC 업무는 조회/등록/수정/삭제 네 가지로 단순하게 떨어지지 않아!
각 HTTP 메소드가 정확히 어떤 의미인지는 각자 (제발 신뢰할 만한 출처에서) 찾아보기로 하고,
REST 논문에는 애초에 CRUD나 어떤 HTTP 메소드를 써야 한다는 언급이 없었다.
‘REST API는 GET/POST/PUT/DELETE를 쓰는 것이다’라는 공식은 웹 프레임웍의 잘못된 가이드에도 원인이 있기도 하다.
Ruby on Rails의 예를 보자.
PHP의 Laravel은
typical "CRUD" routes
를 제공한다는 설명과 함께 Resource Controllers라고 변경했다. 하지만 여전히 PUT은 UPDATE에 대응이 된다.좀 오버하는 감은 있긴 하다.
하지만 REST에서는 Uniform Interface가 중요한데도 경험적으로 (적어도 HTTP 쪽에서는) 인프라가 충분치 않다는 인식이 있는 것 같다.
위에 Ruby on Rails의 예에서 언급한 것처럼 보안을 이유로(?) PUT을 지원하지 않는 방화벽이랄지,
HTTP 응답 코드를 각기 다르게 해석하는 클라이언트 등 현실적인 제약은 다반사인 것 같다.
구현을 하는 입장에선 아무래도 이런 부분에선 부담이 되는 게 사실이다. (IE 대응을 위해 버려진 수많은 나날을 생각해보자)
이것도 사실 각자의 상황에 맞는 Best Practice의 부재 탓이라고 본다.
HTTP가 끝없는 업계의 요구사항에 매번 응답코드를 추가해줄 수는 없다.
답답하겠지만 결국 개발자는 결정을 해야한다. 현실 세계의 문제는 원래 그렇다.
이에 대한 반론 중에는 개발자도구나 HTTP client 툴을 사용하면 된다고들 하지만,
이 블로그 글쓴이의 의도는 요청/응답 시 신경써야 하는 부분이 많다는 것이다.
난 맞는 지적이라고 생각한다.
SOAP이나 GraphQL처럼 응답 메시지 본문에서 모든 상황을 지켜보고 싶은 마음을 나도 십분 이해한다.
하지만 REST는 쉽게 개발하려고 만든 아키텍처 스타일이 아니다.
웹의 인프라를 충분히 활용해서 효율적으로 동작하고, 독립적으로 진화하고, 확장할 수 있게 설계하기하기 위함이다.
디버깅을 편하게 하기 위해 설계 원칙을 바꾸는 순간 본래의 목적에서 멀어진다.
웹에서의 주요 프로토콜이 HTTP이긴 하고, 그 때문에 REST를 구현했다는 사람들이 HTTP를 많이 쓸 뿐이지 REST는 HTTP에 한정되지 않는다.
맞다. 웹개발자 입장에선 대부분의 API 설계를 HTTP 위에서 하게 된다.
하지만 그것이 REST가 HTTP에 종속됐다는 의미는 아니다.
그래도 된다고 생각한다. 다만 그렇게하면 REST라고 부르지 말자는 것이다. REST라고 부를 수 없다고 나쁜 설계는 아니다.
글쓴이가 제시하는 JSON-Pure API는 “json-ld/hydra”와 같은 hypermedia를 사용하는 REST(중의적인 의미) 사람들을 따라하고 있을 뿐이라는 의견도 있다. (지원하는 클라이언트가 얼마 없지만…)
hypermedia를 구현하기 위한 수많은 API 표준이 존재하는데, 후속 블로그에서 더 다뤄보겠다.
계속되는 HTML의 PUT/DELETE 지원 논쟁.
XHR을 쓰면 된다는 부류와 XHR을 못쓰는 환경이 있는데 어떡하냐는 부류가 자주 부딪힌다.
미안하지만 REST는 Architectural Styles일 뿐 당신들이 request 하나하나를 어떻게 구현하는지 관심이 없다.
내 개인적인 생각으로는 어느 시스템이든 각각의 제약 사항은 존재하기 마련이다.
부족하면 부족한대로 해결해내는 것이 개발자가 할 일이라고 본다.
그러다보면 REST의 제약사항을 어길 수밖에 없는 상황도 분명 올 수 있겠지.
다시 말하지만, 그럼 REST라고 안 부르면 된다!
가장 적당한 디자인을 설계하자.
네가 하려는 건 SOAP과 다를 바 없다는 중의적 의미.
댓글에서 SOAP과의 비교를 하는 사람이 참 많다. 여기 REST와 비교한 글도 참고하자.
(이 블로그는 국내에서 보기 드물게 REST에 대해 정확한 표현을 하고 있음에도 이 글에서는 제대로 REST를 설명하고 있지 않는데, 그 이유는 ROA에 관한 그 분의 다른 글에서 볼 수 있다. 여기서 REST는 아키텍처 스타일, RESTful Web Service는 아키텍처로 구분하고 있는데, 이게 얼마나 신방성 있는지는 좀 더 찾아봐야겠다. ROA는 나중에 다시 다뤄보겠다.)
‘소위 REST’가 SOAP을 대체해 나간 것처럼 기술이 오래 살아남기 위해선 사람들이 얼마나 쉽게 받아들일 수 있는가도 무시할 수 없는 것 같다.
(좋은 내용인데 이렇게 밖에 해석할 수 밖에 없어서 미안하다)
많은 사람들은 REST가 좋은 설계 패턴이라고 생각하면서 REST를 제대로 이해 못한 채 API/서비스를 만들고 여기에 RESTful이라는 표현을 쓰고 있다.
그건 REST가 아니라고 말을 해줘도, 그럼 어떻게 구현하냐고 따지고 든다.
마치 REST라는 용어를 반드시 써야만 하는 사람들처럼.
2008년 논문의 저자 Roy도 사람들이 REST에 대해 오해하는 것에 대해 한탄하며 글을 썼는데, 이는 다음 포스트에서 다룰 예정이다.
이 논쟁에서 등장한 근거와 여러 링크가 궁금하다면 제일 하단 추천 링크도 확인해 볼 것!
양이 너무 많아서 정말 대충 막 그냥 해석해서 써갈겼지만, 써 놓고 보니 또 아깝고 해서 쓸데 없지만 붙여 넣어본다.
각 댓글 앞에는 이 글에 대한 찬반 표시를 했다
👎 너 정말 REST를 제대로 이해하는 거 맞어?
👎 그 문법이 좀 혼란스러운 건 맞어. 그런데 그건 HTTP의 문제 아니냐?
👎 REST는 HTTP에 종속된 게 아니야
👎 인터넷 이야기를 해보자고. 그 거대하게 연결된 웹 자체가 이미 REST가 잘 동작하는 훌륭한 예라고. 20만개의 사이트가 20년 후에도 잘 돌아갈 거야.
👎 오해를 한 것 같은데, REST는 전송 프로토콜과 언어에 대해서는 언급하고 있지 않아. 위키디피아를 봐 “RESTful systems typically, but not always, communicate over the Hypertext Transfer Protocol “
👍 당신이 아무리 철학적으로 올바른 말을 해도, HTTP위에서 REST를 구현하려는 시도는 어쩔 수 없는 현실이야. 쉽고 객관적으로 써보려고 노력했는데 잘 안된 것 같군. 곧 JSON-pure API에 관한 추가 포스팅을 올리도록 하지
👎 신경질적으로 반응한 건 미안한데, 글 제목이 좀 자극적이긴 하잖아. 당신의 그 json-pure api는 어떻게 전송하는지 말해줄래?
👍 정말 재밌게 읽었어. api를 설계할 때 나눠야할 깊은 논의에 있어 좋은 출발점이 될 것 같아.
💩 에헴 graphql 에헴 (역주 graphql이란 게 있는데…란 )
👎 디버깅하기 어렵고 DELETE/PUT이 지원하지 않는다고? 지금 몇년도에 살고 있는거야?
👍 2016에 html form에서 DELETE/PUT이 지원하나보지? 지원 안하면 javascript를 disable시킨 환경에서 어떻게 rest를 사용할건데? - 이건 인터뷰 질문으로 쓰기 좋겠구만
👎 내가 오해를 하고 있나? 확인해보니 HTML에서 둘 다 잘 지원하는데?
💩 가서 비누(역주 : 그거 SOAP 아니냐는 중의적 의미)로 입 좀 행구고 오지 그래
👎 마이클! 로이와 그의 논문에 대한 항목은 좀 축소하거나 삭제할 필요가 있어. 당신이 설명하는 것은 HTTP 위에서의 CRUD이지 로이가 설명했던 것과는 달라. 사실 그게 REST라고 불리고는 있지만, 로이의 논문과 관련있는 것은 단지 사람들이 완전히 다른 것을 가져오기 위해 납치한, 그가 사용한 REST란 이름 뿐이라고. REST에 대한 현대적 관행의 결점을 그의 탓으로 돌리는 건 공정하지 않아.
👎 난 네가 JSON을 사용하는 SOAP을 쓰자고 하는 것 같은데. 세세한 제약이 있는 RPC스타일 API가 어려운 건 다 이유가 있어. 많은 이가 지적했지만, 보통 오해하는 것처럼 REST가 CRUD는 아니야. HTTP 동사를 CRUD로 단순화하면 representation의 개념을 놓치게 돼. 이는 그 패턴이 잘 돌아가게끔 도메인 엔티티를 추상화하지. 나아가 각자가 정의한 의미들을 JSON payload에 담아보내는 것이 HTTP동사/응답 패턴보다 쉽다고 하는게 이해가 안돼. 적어도 HTTP동사/응답에 관해선 표준적인 사용법이 있잖아.
👎 이런 끔찍한 글을 쓰기 전에 REST나 공부해. 틀린 점을 말해줄게. #1. 코드의 의미는 API개발자들이 잘 이해하고 있어. #2. 동사들을 지원하기 위해 API 설계자들은 그걸 다 구현해야 하지(모든 웹 서비스가 다 그런 거잖아. 이상한 소릴 하는구만). 이건 API설계에 대한 이야기야. HTML이 몇몇 동사를 지원하지 않겠지만, API에 HTML을 사용해선 안돼. 그래서 JSON이나 XML을 써야하지. #3. 추가적인 동사는 필요없어. 리소스 기반 설계에 대해 공부 좀 해봐. 내가 아래에 몇가지 알려줄게. REST는 특히 캐싱에 대해 고려하거나 이로써 대역폭에 관해 효율적으로 동작해. #4. REST는 디버깅이 존* 쉬워. 브라우저나 Firebug, postman 등… 사실 REST가 가진 장점이라고 할 수 있지. 다른 웹서비스는 훨씬 더 어렵다고. #5. REST가 HTTP에 강력하게 묶일 필요는 없어. 다른 프로토콜을 섞어 쓸 수도 있고, 그게 안티 패턴도 아냐. 더 이상 나쁜 소리하기 싫으니까 조만간 내가 추천하는 걸 좀 찾아보길 바라. API-craft google group, Books: REST in practice, RESTful Web APIs, RESTful Webservices
👍 내가 본 대부분의 json api는 심지어 REST가 아냐. twitter의 ‘REST’ api를 봐. 물론 몇 개는 REST라고 할 수 있지만, 저건 RPC에 가깝지.
👎 결국 넌 REST의 목적을 이해하지 못하기 때문에 REST가 나쁘다고 말하는 거구나.
👍 아니, 난 REST를 시도때도 없이 사용하는 게 안 좋다는 거야. (곧 릴리즈될) Facebook Relay and Netflix Falcor도 - 전통적인 RESTful API를 벗어나는 것에 대한 - 같은 주제를 다루고 있지.
👎 xhr 클라이언트는 request를 위한 모든 환경을 제공하고 있어.
👎 네가 이런 혼동에서 빠져나오기를 바란다
💩 2 Years later … GraphQL is rising. And GraphQL only use 200 and 500.
👍 API 제공자가 아닌 소비자로서의 나의 문제는, 어떻게 파라미터를 전달할 지, 서비스를 어떻게 노출할 지, 리턴 데이터가 어떻게 되어야 할지 일관된 방법이 없다는 것이다
👎 내 생각에 REST의 유일한 문제는 REST 자체가 아니라 그걸 쓰는 사람들의 문제야. 왜냐면 REST는 종종 HTTP와 혼동하거나 HTTP없이는 구현할 수 없다고 생각하거든. 너도 똑같은 실수를 하는 것 같다고 생각하는 이유는, 넌 HTTP의 상태코드나 동사에 대해 불만이 있다고 말을 하지만 그건 REST랑 상관이 없는 얘기거든. 그건 HTTP에 정의된 거라고. 물론 네가 REST를 HTTP를 통해 구현할 수 있기도 하고, REST를 구현한다는 서비스들이 99%는 http를 쓰고 그 속성을 상속받게 되긴 하지.
👎 네가 지적한 건 뭐 하나 제대로 된 게 없어
💩 facebook이 GraphQL 내놓았어 링크
로이 필딩이 이야기하는 HATEOAS에 관한 이야기
API Conf Panel: The Future of Media API
GOTO 2014 • REST: I don’t Think it Means What You Think it Does • Stefan Tilkov
JSON-RPC
Facebook의 GraphQL
Netflix의 Falcor
RESTful Web API 웹 API를 위한 모범 전략 가이드
Hypermedia Web discussion group
API Craft google group
Hypermedia Client Tutorial
From Zero to Hyper in 30 Minutes: Live Coding a Hypermedia Client
CODE COMPLETE 2
Your API isn’t RESTful — And That’s Good