PATCH
사용법
PATCH 요청은 기존 리소스를 어떻게 수정할지 기술한 지시 집합을 보냅니다. 리소스 전체를 교체하는 PUT과 달리, PATCH는 지정된 필드나 속성만 변경합니다.
요청 본문에는 서버가 이해하는 형식의 패치 문서가 담깁니다. Content-Type 헤더가 패치 형식을 식별합니다. 서버 응답의 Accept-Patch 헤더는 지원되는 패치 형식을 알립니다.
참고
PATCH는 더 이상 사용되지 않는 메서드가 아닙니다. 이 메서드는 2010년에 표준화되었으며 HTTP 의미론의 현역 일부입니다. 혼동이 생기는 이유는 PATCH가 다른 메서드보다 늦게 추가되었고 일부 오래된 프레임워크에 기본 지원이 없기 때문입니다.
참고
PATCH에는 멱등성 보장이 없습니다. 같은 패치를 두 번 적용하면 결과가 달라질 수 있습니다(예: 리스트에 두 번 추가). 조건부 요청(If-Unmodified-Since나 If-Match) 없이 같은 리소스에 동시에 패치를 적용하면 충돌 위험이 있습니다.
흔한 패치 형식
JSON Patch는 수정 사항을 add, remove, replace, move, copy, test 연산의 순서가 있는 배열로 표현합니다.
Content-Type: application/json-patch+json
[
{"op":"replace","path":"/email",
"value":"alice@example.re"},
{"op":"add","path":"/verified","value":true}
]
JSON Merge Patch는 더 단순한 방식을 씁니다. 패치 문서가 대상 리소스의 구조를 그대로 본뜹니다. 패치에 존재하는 필드는 기존 값을 덮어씁니다. 어떤 필드를 null로 설정하면 그 필드가 제거됩니다.
Content-Type: application/merge-patch+json
{"email":"alice@example.re","nickname":null}
원자성
서버는 패치 문서의 모든 변경을 하나의 원자적 작업으로 적용합니다. 지시 중 하나라도 실패하면 패치 전체가 거부되고 리소스는 변경되지 않은 채 남습니다.
참고
PATCH 요청에는 부수 효과가 있으며 멱등성이 보장되지 않습니다. “리스트에 추가” 연산에 동일한 패치를 연달아 두 번 적용하면 한 번 적용했을 때와 다른 결과가 나옵니다.
JSON Merge Patch
클라이언트가 JSON Merge Patch 형식으로 사용자 42의 이메일 주소를 갱신합니다. 서버는 변경을 적용하고 갱신된 리소스와 함께 200 OK를 반환합니다.
요청
PATCH /users/42 HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
Content-Length: 28
{"email":"alice@example.re"}
응답
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 51
{"id":42,"name":"Alice","email":"alice@example.re"}
JSON Patch
클라이언트가 설정 리소스에 두 가지 연산을 적용합니다. debug 플래그를 교체하고 새 로깅 레벨 필드를 추가합니다. 서버는 204 No Content로 확인해 줍니다.
요청
PATCH /config/app HTTP/1.1
Host: api.example.re
Content-Type: application/json-patch+json
Content-Length: 102
[
{"op":"replace","path":"/debug","value":false},
{"op":"add","path":"/logLevel","value":"warn"}
]
응답
HTTP/1.1 204 No Content
조건부 패치
If-Unmodified-Since를 사용하는 조건부 요청은 다른 클라이언트가 이미 변경한 리소스를 수정하는 일을 막아 줍니다. 주어진 타임스탬프 이후에 리소스가 수정되었다면 서버는 412 Precondition Failed를 반환합니다.
요청
PATCH /docs/report.json HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
If-Unmodified-Since: Mon, 01 Jan 2024 12:00:00 GMT
Content-Length: 21
{"status":"reviewed"}
응답
HTTP/1.1 412 Precondition Failed
Content-Length: 0
CORS
교차 출처 PATCH 요청은 언제나 CORS 프리플라이트를 유발합니다. 브라우저는 서버가 대상 리소스에 PATCH를 허용하는지 확인하기 위해 먼저 OPTIONS 요청을 보냅니다.
PATCH와 PUT 비교
PATCH는 변경 사항만 보내므로 요청이 작아지고, 큰 리소스에서는 대역폭 효율이 좋습니다. PUT은 몇 개의 필드가 바뀌었든 매번 표현 전체를 보냅니다.
PUT은 멱등합니다. 같은 PUT 요청을 두 번 보내도 서버 상태는 같습니다. PATCH는 리스트에 추가하는 것 같은 연산이 적용할 때마다 다른 결과를 내므로 멱등성이 보장되지 않습니다.
기존 리소스의 특정 필드를 갱신할 때는 PATCH를 사용하세요. 리소스 전체를 새 표현으로 교체할 때는 PUT을 사용하세요.
PATCH와 POST 비교
PATCH는 이미 알려진 URI의 기존 리소스를 수정합니다. POST는 새 리소스를 만들거나 서버 측 처리를 유발합니다.
PATCH는 JSON Patch나 JSON Merge Patch 같은 정의된 패치 의미론을 사용합니다. POST는 요청 본문에 정해진 형식 없이 의미론을 전적으로 서버에 위임합니다.