PATCH
1. 개요
1. 개요
PATCH는 HTTP 메서드 중 하나로, 리소스의 부분적인 수정을 요청할 때 사용한다. 이 메서드는 REST API 설계에서 특정 리소스의 전체를 교체하지 않고 일부 필드만을 업데이트해야 할 경우에 주로 활용된다. PATCH는 2010년 3월 발행된 RFC 5789에서 표준으로 최초 등장하였다.
PATCH 메서드의 주요 용도는 리소스의 일부 필드 업데이트이며, 이를 통해 전체 데이터를 다시 전송하는 것보다 네트워크 효율성을 높일 수 있다. 기존의 PUT 메서드가 리소스 전체를 완전히 교체하는 동작을 하는 반면, PATCH는 명시된 부분만을 변경한다는 점에서 근본적인 차이를 가진다. 이로 인해 대규모 데이터를 다루는 웹 서비스나 애플리케이션 프로그래밍 인터페이스에서 유용하게 사용된다.
PATCH 요청은 일반적으로 JSON 형식의 문서를 통해 수행되며, JSON Patch나 JSON Merge Patch와 같은 표준화된 형식을 사용하여 변경 내용을 기술한다. 이러한 부분 업데이트 방식은 클라이언트와 서버 간의 불필요한 데이터 전송을 줄이고, 동시에 여러 클라이언트에 의한 업데이트 충돌 가능성을 낮추는 데 기여한다.
2. 개념과 특징
2. 개념과 특징
2.1. HTTP 메서드로서의 PATCH
2.1. HTTP 메서드로서의 PATCH
HTTP 메서드로서의 PATCH는 리소스의 부분적인 수정을 요청할 때 사용된다. 이 메서드는 RFC 5789[5]에서 처음 표준으로 정의되었으며, REST API 설계에서 특정 필드만을 선택적으로 업데이트해야 할 때 유용하게 활용된다.
PUT 메서드가 리소스를 완전히 새로운 표현으로 교체하는 것과 달리, PATCH 메서드는 리소스의 일부만을 변경하는 데 목적이 있다. 예를 들어, 사용자 프로필에서 이름만 변경하고자 할 때, PUT을 사용하면 주소나 연락처 등 다른 모든 필드의 데이터도 함께 요청에 포함시켜야 한다. 반면 PATCH를 사용하면 변경하고자 하는 이름 필드에 대한 정보만 전송하면 되므로, 네트워크 대역폭을 절약하고 요청을 간소화할 수 있다.
PATCH 요청의 본문에는 수행할 변경 사항을 명시하는 패치 문서 형식이 포함된다. 대표적인 형식으로는 JSON Patch와 JSON Merge Patch가 있다. 이러한 형식은 변경할 필드의 경로와 적용할 연산(예: 추가, 제거, 교체)을 구조화된 방식으로 표현하여, 서버가 리소스를 정확히 부분 수정할 수 있도록 지시한다.
따라서 PATCH 메서드는 API 설계 시 리소스의 전체 상태를 모르거나, 불필요한 데이터 전송을 피하고자 할 때 PUT 대신 선호되는 방법이다. 이를 통해 클라이언트와 서버 간의 효율적인 상호작용이 가능해진다.
2.2. 기존 PUT 메서드와의 차이점
2.2. 기존 PUT 메서드와의 차이점
PUT 메서드는 리소스 전체를 새로운 표현으로 완전히 교체하는 데 사용된다. 클라이언트가 리소스의 모든 필드 값을 알고 있어야 하며, 요청 본문에 리소스의 완전한 새로운 상태를 담아 보낸다. 반면, PATCH 메서드는 리소스의 일부만을 수정하는 데 사용된다. 클라이언트는 변경하고자 하는 특정 필드에 대한 수정 지시사항만을 요청 본문에 담아 보내면 된다.
이러한 차이는 네트워크 효율성에 직접적인 영향을 미친다. 대규모 리소스를 다룰 때, 단 몇 개의 필드만 업데이트하려는 경우 PATCH는 변경사항만을 전송하면 되므로 PUT에 비해 요청 본문의 크기를 크게 줄일 수 있다. 이는 대역폭 사용을 최적화하고 응답 시간을 단축시키는 장점이 있다.
또한, PUT 메서드는 멱등성을 가지지만, PATCH 메서드의 멱등성은 사용되는 패치 포맷에 따라 달라진다. 예를 들어, JSON Patch 표준은 각 연산이 명시적으로 정의되어 있어 동일한 요청을 반복해도 동일한 최종 상태를 보장하는 멱등성을 가질 수 있다. 그러나 "증분"과 같은 비멱등적 연산을 포함하는 사용자 정의 패치 포맷을 사용한다면 PATCH 요청은 멱등성을 보장하지 않는다.
API 설계 관점에서 볼 때, 리소스의 일부 속성만을 선택적으로 업데이트해야 하는 경우가 빈번하다. 사용자의 프로필에서 이메일 주소만 변경하거나, 주문 상태를 '배송 중'으로만 변경하는 경우 등이다. 이러한 시나리오에서 PUT을 사용하면 변경하지 않을 다른 모든 필드의 현재 값을 클라이언트가 알아내어 함께 보내야 하는 불필요한 복잡성이 생긴다. PATCH는 이러한 부분 업데이트를 위한 명시적이고 효율적인 수단을 제공한다.
2.3. JSON Patch 및 JSON Merge Patch
2.3. JSON Patch 및 JSON Merge Patch
JSON Patch와 JSON Merge Patch는 PATCH 메서드로 리소스를 부분 업데이트할 때 사용되는 두 가지 주요 표준 형식이다. 둘 다 JSON 문서의 변경 사항을 기술하지만, 접근 방식과 기능에서 차이가 있다.
JSON Patch는 RFC 6902로 표준화된 형식으로, 수행할 변경 작업의 목록을 배열로 정의한다. 주요 연산으로는 add, remove, replace, move, copy, test가 있다. 이는 변경할 필드의 경로를 명시적으로 지정하기 때문에 복잡한 중첩 구조를 가진 JSON 문서를 정밀하게 수정하는 데 적합하다. 예를 들어, 배열 내 특정 요소를 교체하거나 한 위치에서 다른 위치로 값을 이동시키는 작업이 가능하다.
반면, JSON Merge Patch는 RFC 7396에 정의된 더 간단한 방식이다. 클라이언트는 원하는 최종 상태의 일부분만을 포함한 JSON 문서를 서버에 보낸다. 서버는 이 문서를 원본 리소스와 병합하여, 제공된 필드는 업데이트하고, null 값으로 설정된 필드는 삭제하며, 언급되지 않은 필드는 그대로 유지한다. 이 방식은 직관적이고 구현이 쉬우나, 배열을 명시적으로 다루거나 null 값을 실제 값으로 설정하는 등의 세밀한 제어에는 한계가 있다.
따라서 API 설계 시, 간단한 필드 갱신에는 JSON Merge Patch를, 복잡한 변환 작업이나 조건부 업데이트가 필요할 경우에는 보다 강력한 연산 집합을 제공하는 JSON Patch를 선택하는 것이 일반적이다. 두 형식 모두 HTTP PATCH 요청의 Content-Type 헤더를 통해 명시적으로 지정하여 사용한다.
3. 사용 사례
3. 사용 사례
3.1. 리소스의 부분적 업데이트
3.1. 리소스의 부분적 업데이트
PATCH 메서드의 가장 핵심적인 사용 사례는 리소스의 부분적인 업데이트를 수행하는 것이다. 웹 API를 설계할 때, 클라이언트가 특정 리소스의 모든 정보를 가지고 있지 않거나, 변경하고자 하는 일부 필드만 전송하여 네트워크 대역폭을 절약하고자 할 때 PATCH를 사용한다. 예를 들어, 사용자 프로필에서 오직 이메일 주소만 변경하고자 한다면, 전체 프로필 데이터를 다시 보내는 대신 변경할 이메일 필드만 포함한 PATCH 요청을 보내면 된다.
이러한 부분 업데이트는 특히 대규모 데이터를 다루는 모바일 애플리케이션이나 네트워크 환경이 제한적인 IoT 기기에서 효율적이다. PUT 메서드는 리소스를 완전히 대체하기 때문에 변경되지 않은 필드에 대한 값도 반드시 요청에 포함시켜야 하지만, PATCH를 사용하면 변경점만 명시적으로 전송할 수 있어 트래픽을 크게 줄일 수 있다. 이는 서버와 클라이언트 간의 불필요한 데이터 교환을 최소화한다.
부분 업데이트를 구현하는 구체적인 방법으로는 JSON Patch나 JSON Merge Patch와 같은 표준화된 형식을 사용하는 것이 일반적이다. JSON Patch는 변경할 연산(add, remove, replace 등), 경로, 값을 명시적으로 나열하는 방식으로, 복잡한 배열 내 요소 수정이나 조건부 업데이트에도 적용할 수 있다. 반면 JSON Merge Patch는 변경하고자 하는 JSON 객체의 일부를 그대로 보내는 더 간단한 방식이다.
3.2. API 설계에서의 활용
3.2. API 설계에서의 활용
API 설계에서 PATCH 메서드는 리소스의 일부 필드만을 효율적으로 업데이트할 수 있는 수단으로 널리 활용된다. 특히 대규모 데이터 구조를 가진 리소스를 다루는 REST API에서, 클라이언트가 변경하고자 하는 특정 속성만을 전송하여 전체 리소스를 교체하는 PUT 메서드보다 네트워크 대역폭을 절약하고 서버의 처리 부담을 줄일 수 있다. 이는 모바일 애플리케이션과 같이 네트워크 환경이 제한적인 상황에서 중요한 장점이 된다.
구체적인 활용 예로, 사용자 프로필 정보를 수정하는 API를 들 수 있다. 사용자가 비밀번호만 변경하려 할 때, PUT을 사용하면 이름, 이메일 등 변경되지 않은 모든 필드값을 다시 요청 본문에 포함시켜야 한다. 반면 PATCH를 사용하면 {"password": "newPassword123"}과 같이 수정할 필드만을 전송하여 업데이트를 요청할 수 있다. 이러한 부분 업데이트 패턴은 설정 변경, 주문 상태 수정, 게시물 일부 내용 편집 등 다양한 비즈니스 로직에 적용된다.
효율적인 API 설계를 위해 JSON Patch나 JSON Merge Patch와 같은 표준화된 형식을 PATCH 요청의 본문으로 채택하는 것이 모범 사례이다. JSON Patch는 op, path, value를 정의한 일련의 연산 배열을 사용하여 정확한 변경 지점과 작업을 명시하므로, 복잡한 구조의 문서에 대한 추가, 이동, 교체 등의 세밀한 조작이 가능하다. 반면 JSON Merge Patch는 변경할 필드와 그 값을 가진 JSON 객체를 그대로 전송하는 더 직관적인 방식으로, 단순한 업데이트 시나리오에 적합하다.
API 설계자는 PATCH의 멱등성이 보장되지 않을 수 있다는 점과, 동시에 발생하는 여러 업데이트 요청으로 인한 충돌 처리 전략을 고려해야 한다. 또한, 클라이언트가 항상 최신 리소스 상태를 인지한 상태에서 변경을 요청하도록 ETag나 Last-Modified 헤더를 이용한 낙관적 잠금 메커니즘을 구현하는 것이 안정성을 높이는 방법이다.
4. 구문과 예시
4. 구문과 예시
4.1. HTTP 요청 형식
4.1. HTTP 요청 형식
HTTP PATCH 요청은 HTTP 헤더와 본문을 통해 구성된다. 요청 라인에는 PATCH 메서드와 대상 리소스의 URI가 명시되며, HTTP 버전이 함께 온다. Content-Type 헤더는 본문에 사용된 패치 문서의 형식을 지정하는 데 필수적이며, 주로 application/json-patch+json이나 application/merge-patch+json이 사용된다.
요청 본문에는 수행할 변경 사항을 기술한 패치 문서가 포함된다. 이 문서는 JSON 형식으로, 리소스를 전체 교체하는 PUT 메서드와 달리, 수정할 특정 필드와 적용할 연산을 구체적으로 나열한다. 예를 들어, op, path, value 멤버를 가진 객체의 배열로 변경 지시를 내리는 JSON Patch 형식을 사용할 수 있다.
클라이언트는 종종 If-Match나 If-Unmodified-Since와 같은 조건부 요청 헤더를 함께 보내 낙관적 잠금을 구현한다. 이는 PATCH 요청이 처리되는 동안 리소스가 다른 클라이언트에 의해 변경되지 않았음을 보장하여 업데이트 충돌을 방지하는 데 도움이 된다. 서버는 요청을 성공적으로 처리하면 일반적으로 200 OK 또는 204 No Content 상태 코드로 응답하며, 업데이트된 리소스의 표현을 본문에 포함시킬 수 있다.
4.2. JSON Patch 연산 예시
4.2. JSON Patch 연산 예시
JSON Patch는 RFC 6902로 표준화된 형식으로, JSON 문서에 적용할 변경 사항을 명시적으로 기술하는 문서이다. 이는 단순히 변경된 필드만 보내는 JSON Merge Patch와 달리, 교체, 추가, 삭제, 이동, 복사, 테스트와 같은 구체적인 연산을 정의하여 더욱 정교한 업데이트가 가능하다.
JSON Patch 문서 자체도 JSON 배열이며, 각 배열 요소는 하나의 연산을 나타낸다. 주요 연산으로는 "op"(operation) 필드에 지정되는 "add", "remove", "replace", "move", "copy", "test"가 있다. 예를 들어, 사용자 프로필에서 이름을 변경하고, 전화번호를 추가하며, 기존 주소를 삭제하는 요청은 다음과 같은 JSON Patch 문서로 표현할 수 있다.
```json
[
{ "op": "replace", "path": "/name", "value": "새로운 이름" },
{ "op": "add", "path": "/phoneNumber", "value": "010-1234-5678" },
{ "op": "remove", "path": "/address" }
]
```
이 패치 문서를 HTTP PATCH 요청의 본문에 담아 서버로 보내면, 서버는 문서에 명시된 순서대로 연산을 적용하여 리소스를 업데이트한다. "test" 연산은 특정 경로의 값이 예상한 값과 일치하는지 검증하여 업데이트 전 조건을 확인하는 데 사용될 수 있으며, 이를 통해 낙관적 잠금과 같은 충돌 방지 메커니즘을 구현할 수 있다. JSON Patch는 연산의 명시성과 배열을 통한 순차적 실행 덕분에 복잡한 업데이트를 정확하고 예측 가능하게 처리할 수 있는 장점이 있다.
5. 주의사항과 모범 사례
5. 주의사항과 모범 사례
5.1. 멱등성과 안전성
5.1. 멱등성과 안전성
PATCH 메서드는 멱등성을 보장하지 않을 수 있다. 멱등성이란 동일한 요청을 여러 번 수행해도 결과가 동일하게 유지되는 성질을 말한다. 예를 들어, PUT 메서드는 리소스 전체를 교체하므로 같은 요청을 반복해도 최종 상태는 변하지 않아 멱등성을 가진다. 반면 PATCH 요청의 내용이, 예를 들어 "count 필드의 값을 1 증가시킨다"와 같은 상대적 변경을 지시한다면, 해당 요청을 여러 번 실행할 때마다 리소스 상태가 달라지므로 멱등성이 깨진다. 따라서 PATCH를 사용할 때는 연산의 종류에 따라 멱등성을 고려한 설계가 필요하다.
HTTP 메서드의 안전성은 요청이 리소스의 상태를 변경하지 않음을 의미한다. PATCH 메서드는 명시적으로 리소스를 수정하는 목적을 가지므로 안전하지 않은 메서드로 분류된다. 이는 GET이나 HEAD와 같은 안전한 메서드와 대비되는 특징이다. 안전하지 않은 메서드는 일반적으로 서버의 상태를 변경할 수 있으므로, 클라이언트는 이에 대한 책임을 인지하고 사용해야 한다.
PATCH의 이러한 특성 때문에 API 설계 시 주의가 요구된다. 서버는 클라이언트가 보낸 PATCH 요청이 멱등한지 아닌지를 명세를 통해 명확히 알려주어야 한다. 또한, JSON Patch와 같은 표준화된 형식을 사용하면 특정 연산에 대한 동작을 예측 가능하게 만들어, 멱등성 문제를 완화하는 데 도움이 될 수 있다. 개발자는 PATCH 요청을 설계할 때, 가능하면 절대적인 값으로 설정하는 방식을 사용해 멱등성을 확보하거나, 그렇지 못한 경우 적절한 오류 처리와 문서화를 통해 예기치 않은 상태 변경을 방지해야 한다.
5.2. 충돌 처리
5.2. 충돌 처리
PATCH 요청을 처리할 때는 여러 클라이언트가 동시에 같은 리소스를 수정하려는 경우 발생할 수 있는 충돌을 고려해야 한다. HTTP 표준 자체는 충돌 해결 방법을 명시하지 않으므로, API 설계자가 적절한 전략을 마련하는 것이 중요하다.
일반적인 충돌 처리 방법으로는 낙관적 잠금이 널리 사용된다. 이 방식은 리소스에 버전 번호나 타임스탬프와 같은 수정 식별자를 포함시키는 것이다. 클라이언트는 PATCH 요청을 보낼 때 자신이 읽었던 버전 식별자(예: If-Match 헤더의 ETag 값)를 함께 전송한다. 서버는 현재 리소스의 버전과 클라이언트가 제공한 버전을 비교하여 일치하지 않으면, 리소스가 이미 다른 요청에 의해 변경되었음을 의미하는 409 Conflict 상태 코드로 응답하여 업데이트를 거부한다. 이를 통해 데이터의 일관성을 유지할 수 있다.
또 다른 접근법은 충돌이 발생했을 때 자동으로 병합을 시도하거나, 클라이언트에게 최신 상태의 리소스를 반환하여 재시도하도록 유도하는 것이다. 특히 JSON Patch 형식을 사용할 경우, 특정 경로의 값을 변경하는 연산이 충돌하기 쉬우므로 주의가 필요하다. 모든 충돌 해결 전략의 핵심은 클라이언트가 실패한 요청 후에 어떻게 최신 데이터를 획득하고 업데이트를 재개할지에 대한 명확한 규칙을 API 문서에 제공하는 데 있다.
