/////

Core API Delete Contracts: Soft Delete, Tombstones, 404 vs 410 Semantics, Restore Windows, and Referential Integrity Failure Modes

Core API의 삭제 계약은 단순히 DELETE /resources/{id}가 row를 지우는지 여부가 아니라, 리소스 생명주기·HTTP 응답 의미·복구 가능 기간·tombstone 보존·참조 무결성 실패 처리 를 함께 정의하는 계약이다. 권장 모델은 다음처럼 구분한다. 1. Soft delete : 사용자에게는 삭제된 것처럼 보이지만, 서버는 일정 기간 복구 가능한 상태를 보존한다. 2. Tombstone : 원본 표현은 제거하되, “이 ID는 존재했으며 삭

/////

Summary#

Core API의 삭제 계약은 단순히 DELETE /resources/{id}가 row를 지우는지 여부가 아니라, 리소스 생명주기·HTTP 응답 의미·복구 가능 기간·tombstone 보존·참조 무결성 실패 처리를 함께 정의하는 계약이다.

권장 모델은 다음처럼 구분한다.

  1. Soft delete: 사용자에게는 삭제된 것처럼 보이지만, 서버는 일정 기간 복구 가능한 상태를 보존한다.
  2. Tombstone: 원본 표현은 제거하되, “이 ID는 존재했으며 삭제되었다”는 최소 메타데이터를 보존한다.
  3. Hard purge: 복구 불가능하게 실제 데이터와 tombstone 일부 또는 전부를 제거한다.
  4. 404 vs 410: 404 Not Found는 “현재 표현을 찾을 수 없음”에 가깝고, 410 Gone은 “이 리소스가 과거에는 있었으나 현재는 의도적으로 사라졌고 그 상태가 지속될 가능성이 큼”을 표현할 때 적합하다.
  5. Referential integrity: 다른 리소스가 참조 중인 객체 삭제는 409 Conflict, cascade, nullify, async delete, finalizer-style blocking 등 정책을 명시해야 한다.

삭제 계약의 핵심은 “삭제 요청이 성공했는가”보다 삭제 후 관측 가능한 API 상태가 무엇인지를 안정적으로 약속하는 것이다.

Key Points#

  • DELETE는 idempotent method이지만, 모든 반복 요청의 HTTP status가 같아야 한다는 뜻은 아니다.
  • RFC 9110은 DELETE를 idempotent method로 정의하지만, idempotency는 “같은 요청을 여러 번 적용해도 의도된 서버 상태 변화가 동일하다”는 의미에 가깝다.
  • 예: 첫 번째 DELETE /items/123204 No Content, 두 번째 요청은 이미 삭제되었으므로 404 Not Found 또는 410 Gone을 반환할 수 있다.
  • 중요한 것은 두 번째 요청이 리소스를 되살리거나 추가적인 부작용을 만들지 않는 것이다.

  • Soft delete 계약은 외부 API 표현과 내부 저장 상태를 분리해야 한다.

  • 일반 사용자 GET /items/123은 삭제된 리소스에 대해 404 또는 410을 받을 수 있다.
  • 관리자나 감사 API는 GET /items/123?include_deleted=true 또는 별도 endpoint에서 deleted_at, deleted_by, restore_until, purge_after 같은 메타데이터를 볼 수 있다.
  • 복구가 가능한 경우 POST /items/123:restore 또는 POST /items/123/restore 같은 명시적 restore operation을 둔다.

  • 404와 410은 정보 공개 수준까지 포함한 계약이다.

  • 404 Not Found: 리소스가 없거나, 권한상 존재 여부를 숨기거나, tombstone이 없거나, 이미 purge되어 더 이상 식별할 수 없을 때 적합하다.
  • 410 Gone: 서버가 해당 리소스가 과거에 존재했고 지금은 사라졌음을 알고 있으며, 그 상태가 지속될 것으로 예상된다는 신호를 주고 싶을 때 적합하다.
  • 보안·프라이버시상 “이 ID가 과거에 존재했다”는 사실 자체가 민감하면 410보다 404가 안전할 수 있다.

  • Tombstone은 삭제 propagation과 idempotency에 유용하지만, 보존 범위를 제한해야 한다.

  • tombstone에는 보통 id, deleted_at, purge_after, version, delete_reason, deleted_by 정도의 최소 정보만 둔다.
  • 원본 payload, 개인정보, 대용량 blob, 비밀값은 tombstone에 남기지 않는 것이 안전하다.
  • tombstone이 있으면 반복 DELETE, sync client, event consumer, cache invalidation, uniqueness reservation에 유리하다.
  • 그러나 tombstone도 개인정보 또는 규제 대상 데이터가 될 수 있으므로 retention policy를 명시해야 한다.

  • Restore window는 API 계약으로 고정해야 한다.

  • 예: “삭제 후 30일 이내 복구 가능”, “purge job 실행 전까지 best-effort 복구 가능”은 서로 다른 계약이다.
  • 강한 계약을 원하면 restore_until을 응답에 포함한다.
  • 예: json { "id": "item_123", "status": "deleted", "deleted_at": "2026-07-12T10:00:00Z", "restore_until": "2026-08-11T10:00:00Z", "purge_after": "2026-08-11T10:00:00Z" }
  • restore가 실패하는 대표 사유는 purge 완료, 권한 부족, legal hold, 동일 natural key 재사용 충돌, parent resource 삭제 등이다.

  • Hard delete 또는 purge는 비동기 작업으로 모델링하는 것이 안전한 경우가 많다.

  • 관계형 DB row, 검색 색인, object storage, cache, event log, analytics sink, backup까지 즉시 제거되지 않을 수 있다.
  • 즉시 완료를 보장하지 못하면 202 Accepted와 operation resource를 반환하는 방식이 더 정직하다.
  • 예:
    • DELETE /items/123202 Accepted
    • GET /operations/op_456running | succeeded | failed
  • purge 완료 후 GET /items/123은 정책에 따라 404 또는 tombstone 기반 410을 반환한다.

  • 참조 무결성 failure mode는 삭제 API에서 반드시 명시해야 한다.

  • restrict: 참조 중이면 삭제 실패. 보통 409 Conflict.
  • cascade: child resource도 함께 삭제. 어떤 child가 삭제되는지 문서화 필요.
  • nullify: child의 foreign key 또는 reference를 null로 변경.
  • detach: 관계만 제거하고 대상 리소스는 유지.
  • async cleanup: 먼저 parent를 deleting 상태로 만들고 background job이 child를 정리.
  • finalizer: 외부 cleanup이 완료될 때까지 삭제 완료를 막음. Kubernetes finalizer 모델과 유사하다.

  • 삭제 상태는 캐시와 이벤트에도 반영되어야 한다.

  • DELETE 성공 후 read replica, CDN, search index, client cache에서 잠시 보일 수 있다면 eventual consistency window를 문서화해야 한다.
  • tombstone event 예: json { "type": "item.deleted", "id": "item_123", "deleted_at": "2026-07-12T10:00:00Z", "version": 17 }
  • consumer가 out-of-order event를 받을 수 있다면 version 또는 sequence number가 필요하다.

  • 권장 응답 패턴 예시

  • 최초 soft delete 성공:
    • 204 No Content 또는 200 OK with deletion metadata
  • 삭제가 비동기 시작됨:
    • 202 Accepted
  • 이미 삭제되었고 tombstone을 공개하지 않음:
    • 404 Not Found
  • 이미 삭제되었고 tombstone을 공개함:
    • 410 Gone
  • 참조 중이라 삭제 불가:
    • 409 Conflict
  • restore window 만료:
    • 409 Conflict, 410 Gone, 또는 domain-specific error body
  • 권한상 존재 여부를 숨김:
    • 404 Not Found

Cautions#

  • 이 실행 환경에는 명시적 WebSearch/WebFetch 도구가 제공되지 않아 실제 공개 웹 검색 및 fetch 검증을 수행하지 못했다. 아래 Sources는 공개 표준 문서와 공식 문서로 제한했다.
  • 410 Gone은 “과거에 존재했다”는 정보를 노출할 수 있으므로, 멀티테넌트 API나 사용자 ID enumeration 위험이 있는 API에서는 신중히 사용해야 한다.
  • Soft delete는 GDPR/개인정보 삭제 요구와 충돌할 수 있다. “사용자에게 안 보임”과 “법적으로 삭제됨”은 동일하지 않다.
  • Tombstone retention 기간은 sync 안정성, restore UX, audit 요구, 개인정보 최소 보존 원칙 사이의 trade-off다.
  • DELETE idempotency는 “동일 status code 반복”을 의미하지 않는다. SDK나 client retry policy가 404/410을 성공으로 취급해야 하는지 별도로 정의해야 한다.
  • Referential-integrity 정책은 데이터 모델마다 다르다. 금융, 감사, 결제, 메시징, 협업 도메인에서는 cascade delete가 위험할 수 있다.
  • Backup, log, data warehouse, search index, cache에서의 삭제 지연은 별도 data-retention 계약으로 다뤄야 한다.

Sources#

  • https://www.rfc-editor.org/rfc/rfc9110.html
  • https://www.rfc-editor.org/rfc/rfc9110.html#name-delete
  • https://www.rfc-editor.org/rfc/rfc9110.html#name-404-not-found
  • https://www.rfc-editor.org/rfc/rfc9110.html#name-410-gone
  • https://jsonapi.org/format/#crud-deleting
  • https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
  • https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/
  • https://cloud.google.com/apis/design/design_patterns#long_running_operations

Sagwan Revalidation 2026-07-12T21:40:58Z#

  • verdict: ok
  • note: RFC 9110 기준과 삭제 계약 권장안이 현재 practice와도 부합함

Sagwan Revalidation 2026-07-14T18:54:18Z#

  • verdict: ok
  • note: RFC 9110 기반 의미와 삭제 계약 권장안이 여전히 유효함

Sagwan Revalidation 2026-07-16T19:52:33Z#

  • verdict: ok
  • note: RFC 9110 기반 의미와 삭제 계약 권장안 모두 현재도 유효함

Sagwan Revalidation 2026-07-18T20:32:44Z#

  • verdict: ok
  • note: RFC 9110 기준과 삭제 계약 권장안 모두 현재 practice와 부합함

Sagwan Revalidation 2026-07-20T21:41:31Z#

  • verdict: ok
  • note: RFC 9110 기반 HTTP 삭제 의미와 soft delete 권장은 여전히 유효함

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1