지난해 블랙프라이데이 밤 11시, 홈오거나이제이션 상품을 파는 분에게서 떨리는 목소리로 전화가 왔습니다. 그는 Shopify, Amazon, TikTok Shop에서 동시에 판매하고 있었습니다. 한 데스크 오거나이저의 재고가 800개였는데, 두 시간 만에 230개가 초과판매됐습니다. 고객 서비스 팀은 밤새 주문 취소를 위해 구매자들에게 전화를 걸었고, 스토어 평점은 하룻밤 사이에 별 반 개가 떨어졌습니다. 다음 날 아침 그가 저에게 물었습니다. 세 채널 모두 자기 잘못이 아니라고 하는데 — 그럼 누구의 잘못인가요?
먼저 결론부터 말하겠습니다. 열 번 중 아홉 번, 멀티채널 초과판매는 어느 한 플랫폼의 잘못이 아닙니다. 그 사이에 있는 층 — 재고 동기화 체인의 문제입니다. 그리고 저는 매번 같은 방식으로 이 체인을 디버깅합니다. 고리 하나씩 따라가며 깨진 부분을 찾는 거죠. 어느 고리가 깨졌든, 책임은 그곳에 떨어집니다.
진짜 초과판매인가, 가짜 초과판매인가?
첫 번째 단계는 로그를 읽는 게 아닙니다. 하나의 질문을 던지는 것입니다. "판매 가능 재고"는 실제로 어떻게 정의되어 있는가?
물리적인 보유 수량을 그대로 판매 가능 수량으로 모든 채널에 밀어넣는 창고를 저는 너무 많이 봐왔습니다. 선반에 800개 있으니 판매 가능도 800개. 하지만 그 800개 중 60개는 검사 대기 중이고, 40개는 내일 도매 출하에 이미 할당되었고, 50개는 막 도착해서 품질 검사를 아직 통과하지 못한 고객 반품일 수 있습니다. 진짜 판매 가능 수량은 650개인데, 채널들은 800개를 기준으로 팔고 있습니다. 여분 주문 150개가 빠져나간 것도 당연합니다.
그래서 첫 번째 체크는 이렇습니다. 네 개의 숫자를 나란히 놓으세요 — 물리적 보유 수량, 운송 중 및 검사 대기 수량, 할당되었지만 아직 출하되지 않은 예약, 그리고 각 플랫폼이 보여주는 판매 가능 수량. 이 네 개가 맞지 않으면 더 깊이 파고들기를 멈추고 먼저 정의를 확정하세요: 판매 가능 = 보유 − 예약 − 검사 대기 − 동결. 정의를 틀리면 아무리 화려한 기술도 오류 위에 쌓은 정밀함에 불과합니다.

업데이트가 몇 분 늦었나?
정의가 맞다면 시간 지연을 추적하세요. 초과판매는 거의 항상 타이밍 문제입니다. 채널 B 페이지가 아직 재고 있음으로 표시하는 동안 채널 A가 마지막 10개를 팔아버린 것이죠.
세 종류의 타임스탬프가 필요합니다. 첫째, WMS에서 재고 변동이 발생한 시각 — 출고 주문이 확정된 순간. 둘째, WMS가 업데이트를 내보낸 시각. 셋째, 각 플랫폼이 실제로 리스팅을 갱신한 시각. 이 셋을 주문별로 타임라인에 나열하면 지연이 드러납니다.
늘 나오는 용의자들: 채널마다 전송 주기가 다르다 — 한 채널에는 실시간, 다른 채널에는 몇 분마다 배치 전송 (여기 나오는 모든 간격 숫자는 예시일 뿐, 플랫폼의 공식 약속이 아닙니다. 각 플랫폼의 최신 문서를 확인하세요 — 예를 들어 5분이나 15분마다). 대형 세일 당일에는 배치 전송 채널이 하필 잘 팔리는 채널이라 수십 개의 여분 주문이 지연 창을 타고 빠져나갑니다. 또는 연동이 콜백 수신이 아닌 폴링이라 플랫폼이 자기 일정에 맞춰 재고를 가져갑니다. 여기에 네트워크 재시도까지 겹치면 한 업데이트가 10분 늦게 도착합니다 — 안전 재고 버퍼를 태우기에 충분한 시간입니다.
제 표준 수법은 이렇습니다. 세일 당일 초과판매된 주문 20건을 가져와 각 주문의 주문 시각, WMS 차감 시각, 플랫폼의 재고 갱신 시각을 뽑아냅니다. 열 번 중 여덟 번, 초과판매된 주문들은 전부 "지연 창" 안에 들어갑니다 — 지연이 얼마나 길든, 바로 그 창에서 초과판매가 발생한 겁니다.
같은 초의 주문: 실제로 재고를 차지한 건 누구?
그다음엔 더 교활한 녀석이 있습니다. 세 채널이 같은 1초 — 아니 같은 1밀리초 안에 주문을 냈고, WMS에 세 건의 차감 요청이 들어왔습니다. 재고가 2개 남았는데, 세 주문이 모두 "내가 먼저"라고 주장했고, 세 건 다 통과됐습니다.
전형적인 경합 상태(race condition)입니다. WMS 재고 차감 로그를 확인하세요. 같은 SKU가 1초 안에 여러 번 차감 성공했고, 각각이 같은 오래된 "현재 재고" 값을 읽지 않았나요? 그렇다면 차감은 원자적이지 않습니다 — 재고 읽기와 쓰기 사이에 락이 없어서, 세 요청이 모두 "2개 남음"을 읽고 모두 승인된 겁니다.
수정은 복잡하지 않지만, 기술 설계에 명시해야 합니다. 재고 차감은 원자적 연산이어야 합니다 — 데이터베이스 행 락이나 직렬화된 메시지 큐입니다. 작은 창고에서는 아무도 눈치채지 못합니다. 볼륨이 급증하는 순간 폭발합니다. 저는 2024년 캘리포니아 온타리오의 50,000평방피트 3PL에서 봤습니다. 하루 3,000건의 주문은 아주 평온했지만, 블랙프라이데이 밤에 20,000건이 밀려오자 동시 차감으로 인기 SKU가 400개 초과판매됐습니다.
반품은 돌아왔다. 재고는 돌아오지 않았다.
마지막 고리는 가장 간과하기 쉽습니다. 반품입니다. 100개가 돌아와서 품질 검사를 통과하고 선반으로 돌아갔는데 — 판매 가능 재고에는 가산되지 않았습니다. 아니면 이틀 늦게 가산됐습니다.
이건 두 가지로 아픕니다. 하나는 가짜 품절: 상품은 있는데 채널은 0으로 표시해서, 공짜로 매출을 날리는 겁니다. 더 지독한 건: 반품이 재입고 흐름을 두 번 통과해서 판매 가능에 두 번 가산되고, 100개의 가짜 재고가 어디선가 나타나 채널이 계속 팔아댄다는 겁니다.
확인 방법: 반품 주문 20건을 표본으로 뽑아 "품질 검사 완료 시각"과 "판매 가능 재고 가산 시각"을 비교하세요. 격차가 자사 기준(예를 들어 4시간)을 넘으면 이 고리에서 새고 있는 겁니다. 많은 창고에서 반품과 출고는 다른 팀, 다른 시스템으로 돌아갑니다 — 반품은 선반에 입고되는데, 재고 동기화 전송은 발동하지 않습니다.
진짜 교훈: 기술을 고치기 전에 숫자를 정의하라
다섯 고리를 모두 따라가면 범인을 찾을 수 있습니다. 하지만 순서가 중요합니다. 먼저 관계자 모두 — 운영, 엔지니어링, 세 채널 팀 — 가 판매 가능 재고의 정의를 서면으로 하나 합의하도록 하세요. 그다음에야 전송 주기, 콜백 대 폴링, 채널별 안전 재고 버퍼 분리 여부를 논하는 겁니다. 정의가 1이고, 기술은 그 뒤의 0입니다.
이건 제가 모든 고객과 함께 돌리는 체크리스트입니다. 그냥 박스를 체크하면 됩니다.
- 판매 가능 재고 정의 문서화 및 일일 정합: 보유 − 예약 − 검사 대기 − 동결
- 각 채널의 전송 방식(실시간 콜백 대 예약 폴링)과 간격을 표로 정리하고, 대형 세일 전마다 검토
- WMS 차감이 원자적임을 확인하고, 동시 실행 부하 테스트를 최소 한 번 수행
- 채널별 안전 재고 분리: 예를 들어 판매 가능 총 1,000개 중 채널별 900개만 노출하고 100개는 버퍼 풀로 유지
- 반품→판매 가능 파이프라인 연결, 시간 격차 스폿 체크
- 대형 세일 전 전체 엔드투엔드 리허설: 초과판매를 시뮬레이션하고 5분 이내에 알림이 발동하는지 확인
명확하게 보면 아무도 책임을 질 필요가 없습니다 — 초과판매란 작은 지연과 작은 정의 격차가 쌓여 하나의 큰 난장판이 된 것뿐입니다. 체인을 바로잡으면, 다음 블랙프라이데이 밤 11시에 떨리는 목소리의 전화를 받는 사람이 당신이 아닐 겁니다.
영어판 번역본입니다. 내용이 다를 경우 영어판을 우선합니다.







