HTTP 409 Conflict

상태 충돌입니다. 요청 자체는 유효하지만 리소스가 변경되어 지금은 적용할 수 없습니다.

HTTP 409의 의미

HTTP 409 Conflict는 서버가 요청을 이해했지만 대상 리소스의 현재 상태와 모순되어 적용할 수 없다는 의미입니다. 대표적인 예는 편집 충돌입니다. 두 클라이언트가 같은 문서를 불러온 뒤 둘 다 저장하면, 두 번째 저장이 첫 번째 저장을 조용히 덮어쓰게 됩니다.

400과 달리 요청 자체는 형식이 올바릅니다 — 나중에 변경 없이 다시 제출하면 성공할 수도 있습니다. 응답 본문에는 클라이언트(또는 사용자)가 문제를 해결하고 다시 시도할 수 있도록 무엇이 충돌하는지 설명해야 합니다.

409 오류의 일반적인 원인

  • 편집 충돌: 클라이언트가 마지막으로 가져온 이후 다른 누군가가 리소스를 수정한 경우입니다(주로 ETag / If-Match를 통해 드러납니다).
  • 이미 존재하는 리소스를 생성하려는 경우 — 중복된 사용자 이름, 이메일, 슬러그 또는 파일 이름입니다.
  • optimistic locking(낙관적 잠금)에서의 버전 불일치: 제출된 버전 번호가 오래된 경우입니다.
  • 서버가 고아 상태로 두기를 거부하는 종속 항목이 있는 리소스를 삭제하거나 이동하려는 경우입니다.
  • 동시에 진행되는 워크플로 단계가 순서에 맞지 않게 적용된 경우입니다(예: 이미 취소된 주문을 승인하는 경우).

개발자로서 해결하는 방법

  • 응답 본문을 확인하세요 — 좋은 API는 충돌하는 필드나 예상되는 현재 버전을 명시합니다.
  • 리소스를 다시 가져온 뒤, 최신 상태 위에 변경 사항을 다시 적용하고 다시 제출하세요.
  • 조건부 요청(ETag를 사용한 If-Match)을 사용하여 데이터를 덮어쓰는 대신 충돌을 안정적으로 감지하세요.
  • 중복 생성 충돌의 경우 멱등성(idempotency)을 미리 정하세요. 기존 리소스를 반환하거나, 해당 리소스를 가리키는 정보와 함께 409를 반환합니다.

응답 예시

HTTP/1.1 409 Conflict
Content-Type: application/json

{"error":"conflict","message":"document was modified by another user","current_version":42}

자주 묻는 질문

409와 400의 차이는 무엇인가요?

400은 요청 자체가 잘못되었거나 유효하지 않다는 의미입니다. 409는 요청은 문제없지만 리소스의 현재 상태와 충돌한다는 의미입니다 — 충돌을 해결한 후 다시 시도하면 성공할 수 있습니다.

API는 언제 422 대신 409를 반환해야 하나요?

페이로드 내부의 유효성 검사 실패에는 422를, 중복이나 오래된 버전처럼 기존 서버 측 상태와의 충돌에는 409를 사용하세요.

ETag는 409 오류를 방지하는 데 어떻게 도움이 되나요?

클라이언트는 마지막으로 확인한 ETag를 If-Match로 전송합니다. 서버는 리소스가 변경되지 않은 경우에만 변경 사항을 적용하며, 그렇지 않으면 덮어쓰는 대신 409(또는 412)를 반환합니다.