2단계
2단계 — HTTP 재시도와 요청 상관관계 고정하기
2회 조회
목차
네트워크가 끊긴 뒤 클라이언트는 서버가 처리했는지 모릅니다. 재시도 키와 관측용 요청 ID를 같은 값으로 취급하면 중복 실행과 장애 조사가 모두 흐려집니다.
두 식별자의 역할
Idempotency-Key: 같은 업무 명령을 한 번의 결과로 수렴시키는 안정 키입니다. 같은 키에 다른 본문을 보내면409로 거부합니다.X-Request-Id: 한 HTTP 요청과 로그·Kafka·응답을 연결하는 관측 ID입니다. 재시도 요청은 새 요청 ID를 가질 수 있지만 같은 업무 키를 사용할 수 있습니다.
클라이언트 재시도
├─ 같은 Idempotency-Key → 같은 업무 결과
└─ 새 X-Request-Id → 이번 전송의 로그 추적
HTTP 상태도 행동을 결정합니다. 4xx 입력·권한 오류는 자동 재시도하지 않고, 429/5xx/timeout은 명시한 횟수·backoff·상한 안에서만 재시도합니다. 응답을 받지 못한 쓰기는 “실패”로 단정하지 말고 조회·webhook·reconcile 중 하나로 결과를 확인합니다.
문서·방 생성 같은 업무 명령은 idempotency key로 중복을 막고, Kafka producer는 요청 ID를 header로 전달해 consumer 로그와 연결할 수 있어야 합니다. JSON 업무 payload를 바꾸지 않고도 관측 경계를 추가하는 것이 호환성에 유리합니다.
스케줄러가 여러 인스턴스에서 같은 알림을 읽을 수 있다면 “발송 후 sent_at 갱신”만으로는 부족합니다. 외부 호출 전에 조건부 UPDATE ... WHERE last_attempted_at < today RETURNING id로 한 worker만 원자 선점합니다. 비용과 중복 알림이 더 위험한 기능은 실패해도 같은 날 자동 재발송하지 않는 at-most-once 시도 정책을 선택할 수 있으며, attempted_at과 실제 sent_at을 분리해 성공으로 위장하지 않습니다.
UX 기준
재시도 버튼은 중복 클릭을 막고, 이미 접수된 명령에는 “처리 중”을 보여 줍니다. 오류 문구는 내부 예외 대신 사용자가 할 수 있는 다음 행동을 말해야 합니다.