당신의 PUT은 리소스를 생성하면 안된다

이상민·2021년 10월 19일
4
post-thumbnail

HTTP와 Restful에 대해 공부하면 GET, POST를 넘어서 PUT, DELETE 같은 다양한 HTTP 메소드들을 만나게 된다. PUT은 보통 리소스를 업데이트하기 위해 많이 사용하고, 몇번을 요청해도 동일한 결과를 보여주는 멱등성을 띈다. 인터넷에 보면 수 많은 사람들이 내가 했던 것과 똑같은 오해를 하길래, 오늘은 그 동안 내가 PUT 메소드에 대해 착각하고 있던 점이 있어 정리하려고 한다.


[착각1] PUT 메소드는 리소스가 없으면 반드시 생성해야한다

내가 착각하고 있던 부분이 바로 위와 같은 생각이다. 결론부터 말하자면 상황에 따라 다르다. 일단 PUT 요청이 들어오면 타겟 리소스가 없을 시 해당 리소스를 생성할 수 있는 것은 맞다. HTTP/1.1 스펙을 정리한 rfc7231 문서에는 다음과 같이 기술되어 있다.

The PUT method requests that the state of the target resource be
created or replaced
with the state defined by the representation
enclosed in the request message payload
-- rfc7231

"??? 뭐야 없으면 생성하고 있으면 수정하는거 맞잖아??"싶다면, 밑에서 더 자세히 설명하겠다

[착각2] 멱등성을 가지니 404를 반환하면 안된다

내가 착각1을 하게된 원인이었다. 나는 PUT은 멱등성을 가지기 때문에 당연히 리소스가 없으면 생성하고 있으면 수정해서 404 같은 에러를 발생하면 안된다고 생각하고 있었다. 하지만 생각해보면 아니라는걸 알 수 있다. 리소스가 없어서 계속 404를 반환해도 멱등성은 유지된다. 멱등성이란 서버(및 데이터) 상태가 동일할때 여러번 요청을 보내도 동일한 결과가 나온다는 뜻일 뿐이다.


PUT이 반드시 리소스를 생성할 필요는 없다

기획 의도와 요청 의도에 따라 PUT API는 존재하지 않는 타겟 리소스에 대해 요청이 들어왔을때 리소스를 생성할 수도 있고, 생성하지 않을 수도 있다. 서비스가 상태를 변경 시키는 요청을 받았을때 클라이언트 대신 제대로된 URI를 선택해준다면 PUT 대신에 POST가 사용되어야한다.

Proper interpretation of a PUT request presumes that the user agent
knows which target resource is desired. A service that selects a
proper URI on behalf of the client, after receiving a state-changing
request, SHOULD be implemented using the POST method rather than PUT.

If the origin server will not make the requested PUT state change to
the target resource and instead wishes to have it applied to a
different resource, such as when the resource has been moved to a
different URI, then the origin server MUST send an appropriate 3xx
(Redirection) response; the user agent MAY then make its own decision
regarding whether or not to redirect the request.
-- rfc7231

PUT이 생성하지 말아야하는 경우

일반적인 게시판 서비스를 만든다고 해보자. 다음과 같은 API가 있을 수 있다.

POST /posts --> 게시글을 생성한다. 게시글 id를 DB에 의해 자동 생성된다

PUT /posts/{id}  --> 해당 게시글을 수정한다

이때 PUT /posts/{id} API는 게시글이 존재하지 않을때 생성해야할까? idDB에 의해 생성되며 클라이언트는 게시글을 POST 요청을 통해 생성하기 전에는 이를 알 수 없다. 그렇기 때문에 PUT /posts/{id} API로 존재하지 않는 게시글의 id로 접근한다면, 이는 해당 타겟 리소스를 생성하려는 의도보다는 잘못된 게시글 id를 보낸것이다. 따라서 404 에러를 반환해야한다.

PUT이 생성할 수 있는 경우

반대로 어떤 경우에 PUT을 통해 리소스를 생성할 수 있을까? 클라이언트가 id를 특정해 생성할때 사용할 수 있다. 학생을 학번으로 특정할 수 있는 다음과 같은 API를 생각해보자.

PUT /students/{studentId}  --> 학번의 학생을 생성하거나 수정한다

학번은 자동 생성하지않고, 학번을 특정해서 요청을 보내는 것의 의도가 게시글과는 다르기 때문에 POST 메소드로 생성하기에는 적합하지 않지 않을 수 있다. 따라서 PUT메소드를 사용해 생성 및 수정을 할 수 있다.

profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

1개의 댓글

comment-user-thumbnail
2023년 5월 10일

이게 궁금햇어요

답글 달기