웹서버에 API 뚫을 일이 있어서 이것저것 보던 중에
몇가지 내가 잘못 알고 있던 부분들과 추가로 찾은 부분들을 정리함.
일단 난 RESTful에서 정의한 method와 HTTP 1.1에서 정의한 method가 다르다고 알고 있었는데 이 부분은 내가 잘못 이해한 것임.
RESTful은 HTTP 1.1의 스펙을 그대로 따르고, HTTP 1.1 스펙상으로 POST와 PUT을 구분하고 있으며, 우리는 습관적으로 POST로 모든 것을 때우고 있다.
일단 spec 상에서 idempotent 항목을 보자(링크)
9.1.2 Idempotent Methods
Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.
However, it is possible that a sequence of several requests is non- idempotent, even if all of the methods executed in that sequence are idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that is not changed by a reexecution of all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence.
A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).
Idempotence는 한글로 멱등성이라고 번역되며 수학용어다.(위키링크)
대충 해석하자면, 멱등성이란 같은 내용을 1번 이상 요청했을 때 결과가 똑같은 경우를 말하며 GET, HEAD, PUT method가 멱등성이 있다. 당연히 POST는 멱등성이 없다.
즉, "PUT /member/rollin" 호출은 여러번 호출되도 결과가 같아야 하고, "POST /member/rollin"은 여러번 호출되면 그때마다 결과가 다를 수 있다.
물론 일련의 요청이 들어왔다고 했을때는 각각의 요청이 멱등성을 가지고 있더라도 전체 요청 결과는 멱등성이 없을 수 있다. 즉, "GET /members"->"PUT /member/rollin"는 멱등성을 가진 GET PUT으로만 구성됐지만 이 일련의 요청 전체는 멱등성을 가지지 않는다. (최초 요청때와 두번째 요청때 GET의 결과가 달라짐)
다시 RESTful 얘기로 넘어가자면...RESTful에서는 이 POST와 PUT에 좀 다른 역할을 지정했다.
위키페디아에서 따온 아래 그림과 같이 PUT은 URI가 존제하면 update 없으면 insert를 하고, POST는 URI가 collection일 경우 collection에 추가를 하고 element일 경우에도 어떤식으로든 해당 URI를 collection으로 간주하고 그 밑에 들어가도록 한다.
간단히 말해 PUT으로 생성을 하려면 요청하는 쪽에서 ID를 알고 있어야 하며, POST로 생성을 하려면 ID를 모르는 상태에서 URI에 collection을 지정해야 한다.
"PUT /articles/1" 하면 1번 글이 생성되고, "POST /articles" 하면 서버에서 할당한 번호의 글이 생성된다.
바꿔말하면...
"POST http://example.com/1"을 호출해서 Update를 하면 안되고,
PUT을 쓸꺼면 멱등성을 고려해야 한다.
는 의미이다.
짬이 더 먹어서 HTTP 1.1 spec을 보니 새삼스럽게 다가오는 부분도 있고,
개발할때 더 신경써야 하겠다는 부분도 있고... 그렇다...
덤으로...
RESTful 스펙으로 깔끔하게 만들라 치면 ServerResource를 하나의 data model로 처리하는 방법도 가능할 것 같다. 결국 ServerResource에 대한 GET 요청 결과는 해당 resource instance이다.
지금처럼 랜더링이다 뭐다 고려해서 만들어야할 필요가 있을까 싶다.
그런데 아직 Service-Dao layer에만 data model을 적용할 생각을 했지, 이를 presentation layer에 적용할 생각은 안하는거던가... 이미 있는데 모르고있던가... 내 아이디어가 현실성이 없던가... 그런데 요즘 node.js 같은거에 프레임워크 붙여서 하는거보면... 나쁠것도 없어 보이는데...
덤으로....2
RESTful 찾다가 RESTful 창시자인 Roy Fielding 씨가 쓴 글(링크)와 이에 대한 동조의 글(링크)를 찾았다.
일단은 RESTful이 되려면 hypertext를 기반으로 해야 한다는 내용이다. 내가 이해한게 맞다면, 어떤 resource의 정보를 받을 때 id만 받을것이 아니라 해당 resource를 찾아갈 수 있는 URI 형태로 제공하라는 것이다.
Roy 글 댓글에 hypertext, hypermedia에 대한 설명이 나오는데 읽어둘만 하다.