멱등성
멱등성이란?
멱등성은 같은 요청을 여러 번 실행해도 결과가 한 번 실행한 것과 같도록 만드는 성질입니다. 유통 시스템에서는 네트워크 재시도, 외부몰 중복 전송, PDA 재전송 때문에 같은 요청이 여러 번 들어오는 일이 흔합니다.
유통 시스템에서 멱등성이 중요한 이유
중복 처리는 금전과 재고 사고로 바로 이어집니다. 주문이 두 번 생성되거나, 재고가 두 번 차감되거나, 송장이 두 번 생성되면 운영자가 수동으로 복구하기 어렵습니다.
주문 중복 수신
외부몰 주문 수집 배치는 같은 주문을 다시 가져올 수 있습니다. mall_id + external_order_no에 unique key를 두고 이미 처리된 주문이면 기존 주문 id를 반환합니다.
출고 요청 중복 수신
ERP가 WMS 응답을 받지 못하면 같은 출고 요청을 다시 보낼 수 있습니다. WMS는 source_system + external_request_no로 중복을 판단해야 합니다.
재고 차감 중복 처리
출고확정 API가 timeout 후 재시도되면 재고 차감이 두 번 일어날 수 있습니다. 확정 문서 id 또는 idempotency key로 이미 생성된 수불을 확인합니다.
택배사 송장 중복 생성
송장 생성 API는 특히 위험합니다. 같은 패키지 id로 이미 송장이 있으면 새 송장을 만들지 않고 기존 송장 번호를 반환해야 합니다.
외부몰 주문 연동
외부몰은 주문, 취소, 배송 상태를 여러 번 보내거나 순서가 뒤바뀌어 보낼 수 있습니다. 이벤트 id와 주문 상태 전이를 함께 검증합니다.
idempotency key
idempotency key는 클라이언트 또는 송신 시스템이 같은 요청을 식별하기 위해 보내는 키입니다.
POST /api/outbound-shipments/OB-001/confirm
Idempotency-Key: confirm-OB-001
서버는 이 키와 요청 본문 해시, 처리 결과를 저장합니다. 같은 키가 다시 오면 이전 결과를 반환합니다.
unique key
DB unique key는 멱등성의 마지막 방어선입니다.
| 업무 | unique key 예시 |
|---|---|
| 외부몰 주문 | mall_id, external_order_no |
| 출고 요청 | source_system, external_request_no |
| PDA 스캔 | device_id, scan_event_id |
| 송장 | package_id, courier_code |
| 재고 수불 | source_type, source_id, movement_type |
처리 로그
멱등 요청 로그에는 요청 키, 상태, 응답 코드, 응답 본문, 오류 메시지, 처리 시각을 저장합니다. 장애 시 운영자가 "이미 성공한 요청인지, 실패해서 재처리해야 하는지" 판단할 수 있어야 합니다.
재처리 설계
재처리는 같은 요청을 다시 보내는 방식이 많습니다. 따라서 재처리 대상 API는 반드시 멱등해야 합니다. 성공한 요청은 기존 결과를 반환하고, 실패한 요청은 안전하게 다시 처리해야 합니다.
실패/성공 응답 전략
| 상황 | 응답 전략 |
|---|---|
| 처음 성공 | 200 또는 201과 생성 결과 반환 |
| 같은 키 재요청 | 이전 성공 응답 반환 |
| 같은 키 다른 본문 | 409 충돌 반환 |
| 처리 중 재요청 | 202 처리 중 또는 잠시 후 재시도 안내 |
| 이전 실패 재요청 | 실패 원인에 따라 재처리 또는 실패 응답 |
예외 상황
| 예외 | 처리 방향 |
|---|---|
| DB 저장 전 timeout | unique key로 최종 상태 조회 |
| 외부 API 성공 후 내부 저장 실패 | 외부 조회 API로 보정 |
| 요청 본문 변경 | 같은 key로 다른 요청이면 차단 |
| 오래된 key 재사용 | 보관 기간 정책 필요 |