URI를 정할 때 가장 중요한 것은 리소스를 잘 식별하는 것이다. 회원 가입/수정/삭제/조회에 대한 API를 만든다고 가정했을 때 등록, 수정, 조회, 삭제하는 것을 리소스로 구분하지 않는다. 리소스는 “회원”이다. 때문에 URI를 만들 때 create-member
, update-member
이 아닌 member/{id}
로 만드는 것이다.
단, 리소스를 최대한 사용해서 URI를 설계하되, 리소스만으로 URI를 설계하기 어려운 경우 행위가 포함된 URI를 설계할 수도 있다. 이런 URI를 컨트롤 URI
라고 한다.
위처럼 URI를 설계한다고 했을 때, 회원 조회/등록/수정/삭제 모두 member/{id}
라는 URI를 가지고 가면 어떤 게 수정인지 삭제인지 행위를 구분할 수 없게 되는데 이때 사용하는 것이 행위는 메소드를 가지고 구분한다.
예를 들어 member/{id}라는 URI에 GET 방식으로 요청이 오면 해당 리소스를 조회하고 DELETE 방식으로 오면 해당 리소스를 삭제하는 요청으로 구분할 수 있다.
서버에 전달하고 싶은 데이터는 쿼리(쿼리 파라미터, 쿼리 스트링)를 통해서 전달한다. 메시지 바디를 통해서 전달할 수 있긴 하지만 지원하지 않는 곳이 많아서 잘 사용하지 않는다.
메시지 바디를 통해서 서버로 요청 데이터를 전달한다. 서버는 클라이언트로부터 받은 요청 데이터를 처리하는데 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행한다. 보통 신규 데이터를 등록하는(ex 회원가입) 데 많이 사용한다.
POST는 단순히 새 리소스를 등록하는 것 뿐만 아니라 데이터 생성, 변경을 넘어 프로세스를 처리해야하는 경우에도 사용할 수 있다. 예를 들어 주문이 완료된 경우 배송이 시작됐을 때, 배송 기사가 지정되는 등 큰 데이터 프로세스가 변경되는 경우에는 POST로 처리한다. 때문에 POST의 결과로 새로운 리소스가 생성되지 않더라도 큰 변화가 일어나는 경우 POST를 이용한다.
또한, JSON을 이용해서 조회 데이터를 넘겨야 하는데 GET 메소드를 사용하기 어려운 경우에도 POST를 이용할 수 있다.
리소스가 있으면 대체하고 없으면 새로 생성해준다. 덮어쓰기 하는 행위라고 생각할 수 있다. POST와의 차이점은 클라이언트가 서버에서 어디에 리소스를 생성할지 모르지만 PUT은 클라이언트가 리소스 위치를 알고 URI를 지정한다는 것이다.
🚨 리소스를 완전히 대체한다는 점을 주의!
username : young, age : 20 인 데이터가 존재했을 때 age값만 업데이트 하기 위해서 age : 30만 보내면 서버는 username : young은 없는 age : 30만 가지고 있게 된다.
PUT을 이용해서 리소스가 완전히 대체되게 하고 싶은 것이 아니라 리소스의 일부분(ex age 값만 변경)만 변경하고 싶다면 PATCH를 이용할 수 있다. PATCH 사용도 거의 가능하긴 하지만 HTTP가 못 받아들이는 경우, POST를 이용하면 된다.
호출해도 대상 리소스를 변경되지 않는 것을 안전하다고 표현한다. 안전은 해당 리소스만을 고려하기 때문에 계속 호출하면서 발생하는 장애까지는 고려하지 않는다. GET, HEAD 등(무언가 바뀌지 않는 것)이 안전한 메소드에 포함된다.
한 번을 호출하든 여러 번 호출하든 결과가 똑같은 것을 말한다. 몇 번을 조회해도 같은 결과를 조회하는 GET이나, 같은 데이터를 가지고 값을 대체하면 항상 최종 결과가 같은 PUT이나, 같은 요청으로 여러 번 삭제해도 삭제 결과가 같은 DELETE를 멱등하다고 말한다.
POST의 경우 만약 결제 요청이라고 가정했을 때 중복 결제 요청이 발생하기 때문에 멱등이 아니라고 본다.
서버가 타임아웃 등의 이유로 정상적인 응답을 주지 못 했을 때, 똑같은 요청을 다시 보내더라도 결과가 똑같기 때문에 문제가 발생하지 않는다. 이것을 근거로 자동 복구 메커니즘에 이용할 수 있다.
🚨 재요청을 보내는 중간에 리소스가 변경되는 경우?
멱등은 외부 요인으로 인해 중간에 리소스가 변경되는 것까지 고려하지 않는다. 동일한 요청인 경우 동일한 결과를 내는 것을 가지고 판단한다.
응답 결과 리소스를 캐시해서 사용해도 되는 것들을 말한다. GET, HEAD, POST, PATCH가 캐시 가능에 포함되지만 실제로는 GET, HEAD 정도만 캐시로 사용한다. POST나 PATCH는 본문 내용까지 캐시 키로 고려해야 하기 때문에 구현이 까다롭다.
강의 : 모든 개발자를 위한 HTTP 기본 지식 - 김영한님