CS

PUT POST PATCH 차이점

수수다 2026. 4. 13. 18:52
반응형

0. 들어가며

작년에 처음 개발을 배우면서 POST, PUT, PATCH의 차이에 대해서
배웠던 것 같은데 

지금은 막상 생성이면 POST, 수정이면 PATCH, 삭제면 DELETE 정도만 쓰고 
PUT을 따로 쓰지 않았다.

그래서 PUT은 뭐가 다른지 알아보니
뭔가 비슷해 보이지만 차이가 있고 
눈에 띄는 것은 멱등성이라는 키워드였다.

멱등성의 성질을 가진 다는 것은 PUT으로 요청하면 그렇게 된다는 건가?

결제와 같은 멱등성을 가지는 비즈니스 로직도 POST로 구현하는 것 같은데
왜 PUT을 쓰지 않은 거지? 라는 의문들을 시작으로

자세하게 공부해보려한다.

https://docs.tosspayments.com/blog/rest-api-post-put-patch

1. HTTP 메서드는 의미를 전달하는 약속이다.

POST, PUT, PATCH, DELETE... 를 처음 배울 때는
생성, 수정, 삭제처럼 CRUD에 대응해서 외우게 된다.

 

하지만 실제로 HTTP 메서드는 

서버를 자동으로 그렇게 동작하게 만드는 장치가 아니다. 

이 요청을 어떤 의미로 해석해야 하는지 전달하는 약속에 가깝다.

 

예를 들어 같은 /user/1 이라는 URI 요청을 보내더라도

  •  POST /user
  •  PUT /user/1
  •  PATCH /user/1

들은 이름만 다른 것이 아니라
서버와 클라이언트가 이 요청을 어떤 뜻으로 받아들여야 하는지가 다르다.

https://www.rfc-editor.org/rfc/rfc9110.html#name-table-of-contents

 

RFC 9110: HTTP Semantics

The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of

www.rfc-editor.org

공식 문서에서는 이런 HTTP 메서드의 의미를 semantics라고 설명한다.

어렵게 보이지만 
HTTP 문맥에서는 "이 요청의 공식적인 의미" 
혹은

"이 메서드를 보면 어떤 기대를 해도 되는가에 대한 약속" 정도로 이해하면 된다.

 

즉,
POST는 서버에게 이 요청을 처리해 달라는 의미에 가깝고

PUT은 이 URI의 리소스를 이 상태로 맞춰 달라는 의미에 가깝고
PATCH는 이 리소스의 일부만 이렇게 바꿔 달라는 의미에 가깝다.
는 차이가 있다.

이 차이는 
사람이 API를 읽을 때도 이 의미를 바탕으로 이해하고
재시도 가능 여부 같은 정책을 다르게 가져갈 수도 있다.

그래서 PUT을 사용했다면
이건 멱등하게 구현되어 있겠지라는 기대가 생기고
반대로 PUT인데도 같은 요청을 보낼 때마다 새로운 데이터가 누적되거나,

매번 다른 상태 변화가 일어난다면

HTTP 메서드가 전달하는 의미와 실제 구현이 어긋난 설계가 된다.

결국 중요한 것은
POST, PUT, PATCH가 단순히 기능 분류표가 아니라
리소스와 요청의 관계를 표현하는 언어라는 점이다.

 


2. 멱등성이란

 

같은 요청을 여러 번 보내도 의도된 최종 효과가 한 번 보낸 것과 같은 성질을 말한다.


여기서 말하는 것이 응답까지 같아야 한다는 것은 아니다.
최초 요청에 성공하여 201 Created 가 반환 될 수 있고
두 번째 요청은 이미 반영된 상태라 200 OK 나 204 No content가 반환될 수도 있다.

여기서 말하는 최종 효과는 "의도"가 중요한 것이다.
kim으로 닉네임 수정, 삭제와 같은 요청을 여러 번 호출하더라도
결론은 닉네임이 kim인 상태고, 삭제된 상태로 같다.
이런 경우를 멱등적이라고 볼 수 있다.

다만 앞에서 말했듯이
PUT이 사용되었다고 해서 자동으로 멱등하게 동작하는 것은 아니다.
PUT이라는 메서드를 보면

같은 요청을 여러 번 보내도 의도된 최종 효과가 한 번 보낸 것과 같겠구나와 같은
기대를 가질 수 있는 것이지

실제로 그렇게 멱등하게 작동하는지는 사실 코드와 설계를 봐야 한다.

또한 POST처럼 멱등 메서드가 아니어도
결제 중복 방지처럼 비즈니스적으로는 멱등하게 설계해야 하는 경우도 있다.

즉 멱등성은
"같은 요청을 반복해도 최종적으로 같은 상태에 수렴하는가"를 보는 개념이지

HTTP 메서드 하나만 보고 서버가 자동으로 그렇게 보장된다고 생각하면 안 된다.


 

3. POST, PUT, PATCH는 무엇이 다를까

POST, PUT, PATCH는 모두 서버의 상태를 바꿀 수 있지만,
각각의 요청이 가지는 의미는 다르다.

POST

POST는 서버에게 이 요청을 처리해 달라는 의미에 가깝다.
주문 생성, 결제 요청처럼 어떤 작업을 수행해 달라는 요청에 자주 사용된다.
이때는 보통 최종 리소스의 URI를 클라이언트가 아직 모른다.
서버가 처리한 뒤 새 리소스의 위치를 정할 수 있다.

예를 들어:

 
POST /order
 

이 요청은
“주문을 생성해 달라”는 뜻에 가깝다.
이 결과로 실제 주문이 /order/101이 될지 /order/102가 될지는 서버가 정한다.

또는

 
POST /payment
 

처럼 결제 요청도
“결제를 처리해 달라”는 의미로 POST를 사용할 수 있다.

PUT

PUT은 이 URI의 리소스를 이 상태로 맞춰 달라는 의미에 가깝다.
즉, 클라이언트가 이미 대상 리소스의 URI를 알고 있는 상태에서 사용한다.
요청 본문은 “처리할 데이터”라기보다 그 리소스가 되어야 할 상태에 가깝다.

예를 들어:

 
PUT /user/1
 

이 요청은
“/user/1 리소스를 이 상태로 맞춰 달라”는 뜻에 가깝다.
즉, 대상이 이미 /user/1로 정해져 있다.

PATCH

PATCH는 이 리소스의 일부만 바꿔 달라는 의미에 가깝다.
PUT이 전체 상태를 맞추는 느낌이라면,
PATCH는 그중 일부 필드만 수정하는 요청에 더 잘 어울린다.

예를 들어:

 
PATCH /user/1
 

이 요청은
/user/1 전체를 다시 정의하는 것이 아니라,
닉네임이나 이메일처럼 일부 값만 변경해 달라는 뜻에 가깝다.

정리하면 다음과 같다.

  • POST: 이 요청을 처리해 달라
    • 예: POST /order, POST /payment
  • PUT: 이 URI의 리소스를 이 상태로 맞춰 달라
    • 예: PUT /user/1
  • PATCH: 이 리소스의 일부만 바꿔 달라
    • 예: PATCH /user/1

 

4. 어디까지 지켜야 할까

 

교과서처럼 완벽하게 나누는 것은 쉽지 않을 것 같다.

기본 의미를 크게 어기지 않는 선에서
왜 이 메서드를 선택했는지 설명할 수 있고, 팀 안에서 일관되게 사용하는 것이 중요하다고 생각한다.

 

5. 라이브러리와 미들웨어는 PUT과 POST를 어떻게 다르게 받아들일까

HTTP 메서드의 차이는 단순히 사람이 문서를 읽을 때만 의미가 있는 것이 아니다.
RFC 9110은 idempotent method는 통신 실패가 발생했을 때 자동으로 다시 시도할 수 있는 근거가 될 수 있다고 설명한다. 반대로 non-idempotent method는 자동 재시도를 조심해야 하며, 프록시는 non-idempotent request를 자동 재시도해서는 안 된다고 말한다.

 

이 차이가 실제로 드러나는 예 중 하나가 NGINX의 proxy_next_upstream 설정이다.
이 설정은 NGINX가 백엔드 서버에 요청을 보냈다가 에러나 타임아웃이 났을 때, 다른 서버로 한 번 더 넘길지를 정하는 옵션이다. NGINX 공식 문서도 proxy_next_upstream을 “어떤 경우에 다음 서버로 요청을 넘길지” 정하는 설정이라고 설명한다. 기본값은 error timeout이다.

 

여기서 중요한 점은, NGINX가 모든 요청을 똑같이 다루지 않는다는 것이다.
공식 문서에 따르면 기본적으로 POST, LOCK, PATCH 같은 non-idempotent method는, 이미 upstream 서버로 요청이 전달된 뒤라면 다음 서버로 넘기지 않는다. 이런 요청까지 재시도 대상으로 포함하려면 non_idempotent 옵션을 명시적으로 켜야 한다.

https://nginx.org/en/docs/http/ngx_http_proxy_module.html

 

 

즉 NGINX는 대략 이렇게 생각하는 셈이다.

  • PUT: 같은 요청이 다시 가더라도 최종 효과가 같을 가능성이 높다
  • POST/PATCH: 같은 요청이 다시 가면 중복 처리될 수 있으니 더 조심해야 한다

물론 이것이 “PUT이면 무조건 안전하다”는 뜻은 아니다.
하지만 적어도 HTTP 메서드의 의미가 단순한 문서상의 설명에서 끝나는 것이 아니라, 중간 시스템의 실제 동작 정책에도 영향을 줄 수 있다는 점은 분명하다.

 

그래서 PUT을 보고
“이 요청은 반복되어도 최종 효과가 같겠지”
라고 기대하는 것은 단순한 감상이 아니다.
실제로 프록시나 미들웨어는 이런 기대를 바탕으로 요청을 다르게 다룰 수 있다.

6. 마무리

처음에는 POST, PUT, PATCH를
그저 생성, 수정, 부분 수정 정도로만 외우기 쉽다.

하지만 조금 더 정확하게 보면
HTTP 메서드는 서버를 자동으로 그렇게 동작하게 만드는 기능 버튼이 아니라,
이 요청을 어떤 의미로 해석해야 하는지 전달하는 약속에 가깝다.

그래서 PUT의 멱등성도
“PUT을 쓰면 자동으로 멱등해진다”는 뜻이 아니라,
PUT이라면 그런 의미로 해석될 수 있어야 한다는 뜻으로 이해해야 한다.

이 관점으로 보면 왜 결제처럼 중복 방지가 중요한 작업도 POST를 쓰는지,
왜 라이브러리와 미들웨어가 PUT과 POST를 다르게 받아들일 수 있는지도 자연스럽게 이해할 수 있다.

결국 핵심은 단순하다.

  • POST는 요청을 처리해 달라는 의미에 가깝고
  • PUT은 특정 URI의 리소스를 원하는 상태로 맞추는 데 가깝고
  • PATCH는 특정 리소스의 일부만 변경하는 데 가깝다

그리고 멱등성은
HTTP 메서드가 자동으로 보장해 주는 기능이 아니라,
그 메서드를 어떤 의미로 해석하고 설계해야 하는지에 대한 기준이다.

반응형