HTTP 메서드와 상태 코드: 멱등성, POST와 PUT의 차이
HTTP 메서드의 역할과 멱등성, POST·PUT·PATCH를 구분하는 기준, 헷갈리기 쉬운 상태 코드의 차이를 정리한다.
시리즈 · 네트워크9 / 12
- OSI 7 Layer와 계층별 역할, ARP
- IP 주소: IPv4와 IPv6, NAT, 체크섬
- 라우터: 경로 지정, 브로드캐스트 컨트롤, 라우팅과 스위칭
- DHCP 동작 방식과 UDP를 사용하는 이유
- IP의 한계와 TCP·UDP, 3-Way Handshake
- TCP 4-Way Handshake와 TIME_WAIT
- DNS 정리: 구조, 질의 방식, 레코드, 이중화와 위임
- 로드 밸런서: 구성 방식, 헬스 체크, L4와 L7
- HTTP 메서드와 상태 코드: 멱등성, POST와 PUT의 차이
- HTTP의 Stateless·Connectionless와 쿠키, 세션
- HTTP/1.1, HTTP/2, HTTP/3 비교
- 소켓과 포트, 그리고 웹소켓
HTTP
HTTP는 HTML 문서와 같은 리소스를 가져올 수 있게 해 주는 클라이언트-서버 프로토콜이다.
HTTP 메서드
요청 메서드는 주어진 리소스에 수행하길 원하는 행동을 나타낸다.
| 메서드 | 역할 |
|---|---|
| GET | 특정 리소스의 표시를 요청한다. 오직 데이터를 받기만 한다. |
| HEAD | GET과 동일한 응답을 요구하지만, 응답 본문은 포함하지 않는다. |
| POST | 특정 리소스에 엔티티를 제출한다. 서버의 상태 변화나 부수 효과를 일으킨다. |
| PUT | 대상 리소스 전체를 요청 내용으로 덮어쓴다. |
| PATCH | 리소스의 일부만 수정한다. |
| DELETE | 특정 리소스를 삭제한다. |
| CONNECT | 목적 리소스로 식별되는 서버로의 터널을 맺는다. |
| OPTIONS | 목적 리소스의 통신 옵션을 설명한다. |
멱등성
동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 내고 서버의 상태도 동일하게 남을 때, 해당 메서드가 멱등성을 가졌다고 한다.
- GET, PUT, DELETE는 멱등하다.
- POST는 호출할 때마다 요청된 데이터가 추가되므로 멱등하지 않다.
- PATCH는 일부만 수정하는 “변화”를 명령할 수 있어서 구현에 따라 다르다.
GET과 POST의 차이
- 목적: GET은 데이터를 받는 목적으로만 쓰인다.
- Body: GET은 일반적으로 Body를 사용하지 않는다.
- 멱등성: POST는 멱등성을 보장하지 않는다.
GET에도 Body를 실을 수 있는데 왜 지양하는가
스펙상 GET 요청에 Body를 싣는 것이 금지되어 있지는 않다. 그럼에도 이 방식을 지양하는 이유는 다음과 같다.
- 캐시 가능성: GET 요청은 웹 브라우저 등에 의해 자주 캐시된다. GET 요청을 단순하고 예측 가능하게 유지해야 캐시를 쉽게 관리하고 조회할 수 있다.
- 안전성: GET은 서버 상태를 바꾸지 않는 멱등한 조회 메서드라는 의미를 유지해야 한다.
POST와 PUT, PATCH
기존에 알고 있던 구분
POST와 PUT의 차이를 이렇게만 알고 있었다.
- POST: Create
- PUT: Update
틀린 말은 아니지만, 더 정확한 기준은 리소스의 URI를 누가 결정하는가이다.
- POST: 클라이언트는 등록될 리소스의 URI를 모른다. 서버가 결정한다.
- PUT: 클라이언트가 리소스의 URI를 직접 지정한다.
예시
유저 스키마가 다음과 같다고 하자.
id: Int (순차적으로 1씩 증가하며 저장됨)name: String
POST /members
- 유저를 생성한다.
- 클라이언트는 생성될 유저가 어떤 id를 갖게 될지 모른다. 즉 등록될 리소스의 URI를 모르고, 서버가 결정한다.
PUT /members/{id}
- 유저 정보를 수정한다.
- 클라이언트가 대상 유저가 누구인지 이미 알고 있다. 리소스의 URI를 클라이언트가 알고 지정한다.
PUT과 PATCH
DB 수정이 일어나면 무조건 PUT을 사용해 왔는데 좋은 방법이 아니었다.
- PUT: 기존 데이터를 통째로 덮어쓴다.
- PATCH: 데이터의 일부만 수정한다.
부분 수정에는 PATCH를 쓰는 것이 맞다.
컨트롤 URI
모든 동작이 HTTP 메서드만으로 표현되면 좋겠지만, 실제로는 딱 맞아떨어지지 않는 경우가 많다. 그럴 때 나는 /members/delete/{id}처럼 써 왔는데, /members/{id}/delete처럼 리소스 식별을 해치지 않는 형태로 컨트롤 URI를 붙이는 편이 낫다.
상태 코드
2XX와 3XX 응답 중 무엇을 골라야 하는지는 아래 흐름도로 정리할 수 있다.

200 OK와 201 Created
- 200 OK: 요청을 정상적으로 수행했음을 의미한다.
- 201 Created: POST나 PUT으로 게시물 작성처럼 새로운 데이터를 서버에 쓰는 작업이 성공했을 때 반환한다. 200과 달리 응답의
Location헤더에 생성된 리소스의 위치(예:/members/100)가 포함된다.
3XX 리다이렉션
301과 302는 리다이렉트할 때 요청 메서드가 GET으로 바뀌고 본문이 제거될 수 있다. 메서드와 본문을 유지해야 하면 307과 308을 사용한다.
| 코드 | 이름 | 지속성 | 메서드 | 의미 |
|---|---|---|---|---|
| 301 | Moved Permanently | 영구 | GET으로 바뀔 수 있음 | URL이 영구적으로 바뀌었다 |
| 302 | Found | 일시 | GET으로 바뀔 수 있음 | 일시적으로 다른 URL로 이동한다 |
| 307 | Temporary Redirect | 일시 | 유지 | 클라이언트는 이후에도 원래 URL을 계속 시도해야 한다 |
| 308 | Permanent Redirect | 영구 | 유지 | 클라이언트와 검색 엔진은 URL이 바뀐 것으로 캐싱해 두어야 한다 |
401 Unauthorized와 403 Forbidden
- 401 Unauthorized: 클라이언트가 인증되지 않았거나 유효한 인증 정보가 부족해 요청이 거부되었다. 누구인지 확인되지 않아 요청을 처리할 수 없는 상태다.
- 403 Forbidden: 서버가 요청을 이해했지만 권한이 없어 거부했다. 즉 로그인은 되었지만 권한이 없는 무언가를 요구한 경우다.
Reference
- 모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한
- Http Method 란? (GET, POST, PUT, DELETE)