결론부터 말하겠습니다. 배송 라벨이 사라질 때 운송사의 잘못인 경우는 거의 없습니다. 주문은 WMS와 운송사의 라벨 API 사이에 있는 자사의 연동 체인 어딘가에서 죽었습니다. 운송사에 전화하는 것부터 시작하지 마세요. 다음 순서로 디버깅하세요. WMS 출고→API/큐 계층→운송사 응답→상태 역기록→인쇄 스테이션. 주문이 멈춘 곳, 그곳이 문제의 위치입니다. 순서를 틀리면 3일을 태우고도 아무것도 못 찾습니다.
주문이 "증발하는" 이유
라벨 요청은 소포에 도착하기 전에 5개의 링크를 거칩니다.
- WMS가 출고 요청을 생성합니다.
- 연동 계층(미들웨어)이 운송사 API로 전송합니다.
- 운송사가 라벨 데이터와 추적 번호를 반환합니다.
- WMS가 추적 번호를 주문에 역기록하고 "인쇄 대기"로 옮깁니다.
- 포장 스테이션이 라벨을 인쇄하고 작업자가 박스에 붙입니다.
각 링크가 주문을 삼킬 수 있습니다. 요청이 나가지 않거나, 소비되지 않는 큐에서 썩거나, 운송사 응답을 읽기 전에 자사 쪽이 타임아웃되거나, 역기록이 실패하거나, 프린터가 오프라인입니다. 에러는 쉬운 경우입니다. 최소한 보이기 때문입니다. 치명적인 건 조용한 실패입니다. 자사 WMS는 요청을 보냈다고 믿고, 운송사는 온 적이 없다고 믿으며, 주문은 그 틈에 앉아 누구도 주장하지 않습니다. 그래서 창고는 "주문 분실"을 외치고 IT는 "로그가 정상으로 보인다"고 우기는 겁니다.
세 번 봤습니다: 두 개의 실전 이야기
첫 번째는 작년 11월, UPS 라벨 API를 쓰던 중국 동부의 3PL 의류 창고 이야기입니다. 하루에 20~30개의 라벨이 사라졌고, 운송사는 백엔드에 요청이 온 적이 없다고 단언했습니다. 오후 내내 파고든 결과 원인을 찾았습니다. 타임아웃은 5초였는데, 성수기에 운송사 API 응답은 8~10초였습니다. 타임아웃이 발생할 때마다 WMS는 주문을 "라벨 실패"로 표시했습니다. 운송사는 이미 라벨과 추적 번호를 생성한 상태였는데도요. 두 개의 이야기, 하나의 주문. WMS는 수동 재인쇄 대기의 실패를 보여주고, 운송사 청구에는 이미 라벨 요금이 찍혀 있었습니다. 더 나쁜 건, 창고는 "실패"를 보고 재시도를 눌렀고, 재시도는 같은 주문에 두 번째 추적 번호를 만들었습니다. 소포당 두 개의 후보 라벨. 잘못된 것을 고르면 분실 소포와 화난 고객입니다.
두 번째는 올해 3월, 국제 운송사 API를 쓰던 중국 남부의 국경 간 이커머스 창고입니다. 자정부터 2 AM 사이에 접수된 주문이 대량으로 사라졌고, 낮에는 완벽했습니다. 더 지독한 근본 원인. 운송사 API에는 야간 정기 점검 시간이 있어 "서비스 불가"를 반환했는데, WMS 연동 계층에는 실패 큐가 전혀 없었습니다. 실패한 요청은 그냥 버려졌습니다. 재시도도 없고, 알림도 없고, 기록도 없습니다. 2시간 치 주문이 시스템에 흔적 하나 남기지 않았고, 주문은 "라벨 대기"에 머물렀으며, 창고는 시스템이 느린 줄 알고 아침까지 기다렸습니다. 로그가 진실을 보여줬습니다. 꼬박 2시간 치 요청은 전송조차 되지 않았습니다. 연동 계층이 삼킨 겁니다.
증상은 달라도 근본 원인은 같습니다. 라벨 체인을 정산하는 사람이 아무도 없었습니다. 돈은 정산합니다. 재고는 정산합니다. 라벨은? 아무도 안 했습니다.
플레이북: 5개 링크 디버깅 체인
이건 제 오픈 전날 체크리스트입니다. 오픈 전에 모든 항목에 체크하게 합니다.
1단계: WMS 출고 로그 확인. 출고 가능한 모든 주문에 주문번호, 소포 무게와 치수, 서비스 상품이 포함된 출고 요청 기록이 있는지 확인합니다. WMS 내부에 출고 요청이 생성되지 않았다면 문제는 내부입니다. 주문 상태 머신이 멈췄거나 출고 스케줄러가 죽은 겁니다. API는 건너뛰세요.
2단계: 연동 계층 큐 확인. 비동기 출고라면 큐 적체, 컨슈머가 살아 있는지, 데드레터 큐에 뭐가 쌓이는지를 봅니다. 동기 호출이라면 타임아웃과 재시도 설정을 봅니다. 타임아웃은 운송사 SLA 응답 상한보다 짧으면 안 됩니다. 성수기에는 여유를 두고 두 배로. 의류 창고의 5초 타임아웃은 바로 여기서 잡혔습니다.

3단계: 운송사 응답 확인. 모든 요청에는 요청-응답 쌍 로그가 필요합니다. 무엇을 보냈는지, 타임스탬프는 언제인지, 무엇이 돌아왔는지, 추적 번호는 무엇인지. 응답 없이 요청만 기록하는 건 아무것도 기록하지 않는 것과 같습니다. 제가 본 최악의 시스템은 "호출 성공"이라는 말만 저장하고 추적 번호조차 없었습니다.
4단계: 상태 역기록 확인. 운송사가 추적 번호를 반환한 뒤 WMS는 이를 주문에 역기록하고 상태를 "인쇄 대기"로 올려야 합니다. 역기록 실패는 재시도 큐로 들어가야지, 조용히 건너뛰면 안 됩니다. 역기록은 가장 큰 희생 지대입니다. 많은 시스템에서 요청과 역기록은 독립된 두 트랜잭션입니다. 요청은 성공하고 역기록은 죽으면 주문은 공중에 뜹니다. 운송사는 갖고 있고, WMS는 없습니다.
5단계: 프린터 확인. 포장 스테이션 프린터가 오프라인이 되거나, 용지가 떨어지거나, 드라이버가 죽거나, 라벨이 안 나오면 작업자가 "재인쇄"를 누릅니다. 재인쇄는 재인쇄 플로우로 해야 합니다. 기존 추적 번호 그대로, 새 용지. 절대 새 라벨 요청을 날리면 안 됩니다. 하나의 주문이 두 개의 추적 번호가 되고, 월말 정산이 당신 개인의 악몽이 됩니다.
6단계: 전체 체인 정산. 일일 마감 후 4방향 정산을 돌립니다. WMS 출고 수 = 연동 계층 요청 수 = 운송사 성공 수 = 인쇄 수. 불일치가 있으면 그게 사라진 라벨입니다, 정량화된. 이 정산 스크립트는 오픈 첫날부터 있어야 합니다. 첫 사고 이후가 아닙니다. 늦게 만들면 "몇 개를 잃었는가"에도 답할 수 없습니다.
7단계: 멱등성 키. 모든 라벨 요청에는 전역적으로 고유한 멱등성 키를 싣습니다. 주문번호 + 소포 순번을 쓰세요. 주문번호 단독은 절대 안 됩니다. 다중 소포 주문에서 충돌합니다. 운송사 쪽과 자사 연동 계층 모두 키로 중복 제거해야 합니다. "재시도가 중복 라벨을 인쇄한다"에 대한 유일한 방어입니다. 두 번째는 없습니다.
| 링크 | 전형적인 증상 | 디버깅 액션 |
|---|---|---|
| WMS 출고 | "라벨 대기"에 멈춘 주문, 요청 기록 없음 | 주문 상태 머신, 출고 스케줄러 확인 |
| API 큐 | 지연 시간 증가, 데드레터 큐 적체 | 컨슈머 상태, 큐 깊이 알림 확인 |
| 운송사 응답 | 빈번한 타임아웃, 산발적 실패 | 타임아웃 설정, 운송사 상태 페이지, 쌍 로그 확인 |
| 상태 역기록 | 추적 번호는 있는데 주문 상태 그대로 | 역기록 트랜잭션, 재시도 큐 확인 |
| 인쇄 스테이션 | 작업자가 "인쇄가 안 돼요" 보고 | 프린터 상태 확인, 재인쇄 플로우 사용, 재요청 금지 |
흔한 실패 지점 (오픈 전 자가 점검)
- 타임아웃이 너무 짧다. 성수기에 반드시 터진다. 세 번 봤는데, 매번 "대형 세일 전까지는 잘 됐다"로 시작한다.
- 실패를 큐에 넣지 않고 버린다. 자정 정기 점검이나 운송사의 랜덤 500이 "주문을 찾을 수 없음"이 된다.
- 멱등성 키 없는 재시도. 재시도는 기분이 좋다. 월말 정산이 숙취다. 운송사는 중복 라벨마다 요금을 청구한다.
- 돈과 재고는 정산하면서 라벨은 안 한다. 재무는 맞고 재고는 맞는데, 고객이 "소포가 안 왔어요"라고 신고할 때까지 수십 개의 사라진 라벨을 아무도 눈치채지 못한다.
- "호출 성공"을 "라벨 생성"으로 착각한다. 운송사 API의 200이 라벨이 생성됐다는 뜻이 아니다. 응답 본문 안의 비즈니스 상태 코드를 읽어라. 운송사는 HTTP 200 안에 비즈니스 실패를 감싸는 게 일상이다.
직관에 반하는 부분
가장 위험한 실패 모드는 에러가 아니다. 가짜 성공이다. 에러는 알림을 울리고 누군가 본다. 하지만 "요청 전송됨, WMS는 성공 표시, 운송사는 받지 못함"은 몇 주간 조용히 앉아 있다가 대형 세일 아침에 터진다. 이를 막는 규칙은 하나다. 운송사가 반환한 추적 번호만이 진실의 원천이다. 추적 번호 없는 주문은 전부 미출고 처리. 오픈 전에 창고와 고객 서비스와 정렬하지 않으면, 사고 후에 세 측이 서로 다툰다. IT가 죄를 뒤집어쓴 채로.
솔직히 말할 만한 트레이드오프가 하나 있다. 동기 호출 대 비동기 큐. 동기는 단순하다. 작업자가 인쇄를 누르고 결과를 안다. 하지만 운송사 응답 하나가 느리면 포장 라인 전체가 막힌다. 비동기는 처리량과 스파이크 흡수를 주지만 체인이 길어지고 디버깅은 두 배 어려워진다. 내 규칙: 하루 5,000건 미만이면 짧은 타임아웃의 동기로, 실패는 수동 검토 큐로. 그 이상이면 비동기. 단, 위의 전체 체인 정산과 알림을 먼저 갖춘 뒤에. 비동기는 은탄환이 아니다. "눈앞의 에러"를 "사후 정산"으로 바꿀 뿐. 정산이 약하면 비동기 손실이 동기보다 찾기 어렵다.
라벨 API는 세일 당일 3 AM까지는 평화로워 보인다. 이 체크리스트를 인쇄해서 포장 스테이션 옆에 붙여라. 어떤 대시보드보다 낫다.
Lin Xiao, WMS 구현 컨설턴트 지음
영어판 번역본입니다. 내용이 다를 경우 영어판을 우선합니다.










