빠른 비교
PATCH /users/42 HTTP/1.1
Content-Type: application/merge-patch+json
{
"name": "Kim",
"profile": {
"nickname": null
}
}{
"name": "Kim",
"profile": {
"nickname": null
}
}위 payload는 name을 교체하고, profile.nickname을 삭제하라는 의미입니다. object에 없는 member는 추가되고, 이미 있는 member는 교체됩니다.
처리 방식
원본 문서와 비슷한 모양으로 바꿀 부분만 보낸다
JSON Merge Patch는 변경 명령 목록이 아니라 "목표 문서에 덮어쓸 예시 object"에 가깝습니다. patch object의 member를 target object에 재귀적으로 적용합니다. 대상에 없는 key는 추가하고, 대상에 있는 key는 patch 값으로 교체합니다.
{
"title": "Hello",
"author": {
"givenName": "Jane"
}
}위 patch를 기존 문서에 적용하면 title은 "Hello"로 바뀌고, author.givenName도 바뀝니다. patch에 없는 다른 member는 그대로 남습니다. 그래서 간단한 object 중심 API의 부분 수정에 읽기 쉽습니다.
null은 값을 비우는 것이 아니라 삭제 명령이다
JSON Merge Patch에서 patch object 안의 null은 특별한 의미를 가집니다. target object에 같은 key가 있으면 그 member를 삭제합니다. 이 규칙 때문에 "값을 실제로 null로 저장해야 하는 필드"와 Merge Patch는 잘 맞지 않습니다.
{
"profile": {
"nickname": null
}
}위 payload는 nickname을 null로 바꾸는 것이 아니라 nickname member를 제거합니다. API에서 null 자체가 중요한 값이라면 JSON Patch나 별도 명령 구조를 쓰는 편이 더 명확합니다.
배열은 부분 수정이 아니라 통째로 교체된다
Merge Patch는 object member 단위의 병합에 맞춰져 있습니다. 배열 내부의 특정 index만 바꾸거나, 배열 끝에 하나를 추가하는 명령을 표현하지 못합니다. patch의 배열 값은 기존 배열을 통째로 대체합니다.
{
"tags": ["json", "patch"]
}기존 tags가 ["api", "json"]이었다면 위 patch 이후에는 ["json", "patch"]가 됩니다. 배열에서 add, remove, replace 같은 index 기반 작업이 필요하면 JSON Patch가 더 적합합니다.
선택 기준
| 상황 | 적합한 선택 |
|---|---|
| object 필드 몇 개를 단순 수정 | JSON Merge Patch |
| 배열 index, move, copy, test가 필요 | JSON Patch |
null을 실제 값으로 저장해야 함 | JSON Patch 또는 별도 명령 payload |
| 사람이 읽기 쉬운 PATCH body가 중요 | JSON Merge Patch |
| 변경 순서를 명시해야 함 | JSON Patch |
주의사항
Merge Patch에서 null은 삭제 의미입니다. null을 "아직 모름", "비어 있음", "값 없음" 같은 도메인 값으로 저장해야 한다면 삭제 명령과 충돌합니다.
{
"nickname": null
}위 payload는 nickname을 null로 저장하라는 뜻이 아니라 nickname member를 제거하라는 뜻으로 처리됩니다.
patch가 object가 아니면 target 전체를 patch 값으로 교체합니다. 문자열, 배열, null 같은 값을 patch body로 보내면 부분 수정이 아니라 전체 교체가 될 수 있습니다.
참고 링크
2 sources