시스템은 보유 재고 500개를 보여준다. 고객 서비스가 판매할 수 있는 건 300개뿐이다. 그러다 프로모션이 시작되고, 스토어프론트는 "재고 있음"이라고 하고, 창고는 "그런 재고 없다"고 하고, 오버셀 페널티가 날아들기 시작한다. 내가 본 OMS 구축 10건 중 9건은 깨진 재고 모델에서 시작됐다. 문제는 시스템이 아니다 — 문제는 "재고"를 하나의 숫자로 취급한다는 것인데, 사실은 네 개의 수위선이다.

보유 재고는 판매 가능 재고가 아니다

첫 번째 수위선은 보유 재고(on-hand)다. WMS상의 SKU 총수량이다. 많은 기업이 이 숫자를 그대로 스토어프론트에 판매 가능 수량으로 밀어 넣는다. 그게 오버셀 원인 1위다. 그 보유 총량 안에는 팔 수 없는 재고가 여러 종류 섞여 있다. QA 홀드 중인 물량, 폐기 대기 중인 파손 물량, 실사 카운트용으로 잠긴 물량, 재판매 등급 판정이 아직 안 끝난 고객 반품이다.

해결책: OMS는 "판매 가능 보유분"만 인식해야 한다 — 동결·QA 홀드·파손 물량을 모두 뺀 수량이다. 이 필터링은 WMS→OMS 인터페이스 안에 재고 상태 기준으로 하드코딩해야지, 매일 하는 수동 정산으로 할 일이 아니다. 내가 일했던 뷰티 이커머스 회사는 반품 재판매율이 60%였는데 평균 4일 동안 "등급 판정 대기"에 묶여 있었다. 그 4일을 판매 가능하다고 치면 오버셀은 확정이다.

예약: 이미 주인이 있는 재고

두 번째 수위선은 할당된 재고다. 주문이 떨어지는 순간 OMS는 해당 재고를 물어뜯는다. 아직 선반에 앉아 있지만 이미 주인이 있다. 예약은 두 가지 맛이 있다. 특정 로트·특정 로케이션에 묶여 누구도 건드릴 수 없는 하드 할당과, 정확한 피킹 위치가 나중에 정해질 때까지 수량만 잡아두는 소프트 할당이다.

함정은 예약 해제에 있다. 주문 취소, 부분 결품, 결제 시간 초과 — 예약은 즉시 해제되는가? 너무 일찍 해제하면 같은 SKU의 다른 주문이 가로채고, 너무 늦게 해제하면 좀비 주문이 스토어프론트에서 못 파는 재고를 차지하고 앉는다. 내 기본값: 결제 시간 초과 예약은 30분 후 자동 해제, 상담원이 취소한 주문은 실시간 해제, 부분 결품 주문은 결품 라인만 해제하고 확정 라인은 유지한다. 서비스팀의 클릭 작업이 아니라 OMS의 정책으로 코드화하라.

운송 중과 QA 홀드: 미래를 파는 것

세 번째 수위선은 운송 중 재고다. 발주는 됐지만 아직 입고 안 됐다. 좋은 OMS는 운송 중을 입고 예정일로 쪼갠다. 3일 안에 도착? 일부를 선판매해도 된다. 15일 뒤? 품절로 표시하고 말 그대로 하라. 선판매 비율은 공급사의 과거 정시 납기율을 따라야 한다 — 95% 위면 80% 선판매는 정당하고, 만성 지각이면 선판매는 0이다.

QA 홀드는 형제 문제다. 상품이 도착해 검수 구역에 앉아 있는데 WMS가 아직 적치를 안 했다. 그 사이 OMS는 판매 가능 재고에 더하는 게 아니라 "운송 중 / 검수 중"으로 보여줘야 한다. 검수 사이클이 긴 카테고리 — 식품, 화장품, 가전 — 는 QA가 2일에서 일주일까지 걸릴 수 있고, 그 재고 상태가 보여야지 안 보이면 고객 서비스와 창고가 매일 싸운다.

핸드 터미널로 파렛트 바코드를 스캔하는 창고 작업자

안전 재고: 모두가 털어가는 완충재

네 번째 수위선은 안전 재고, 불확실성에 대한 쿠션이다. 늦는 공급사, 수요 급증, 카운트 오차. 감이 아니다 — 계산은 단순하다. SKU의 최근 90일 평균 일 판매량과 변동성을 가져와 보충 리드타임 변동성과 합친다. 둘 다 들쭉날쭉할수록 쿠션은 두꺼워진다. ABC 분류가 여기서 제 몫을 한다. A 품목은 일단위로 안전 재고를 계산하고, C 품목은 어차피 싸니까 대충 해도 된다.

안전 재고의 최대 적은 "빌려 쓰기"다. 프로모션이 시작되면 운영팀이 쿠션에 쌓인 물량을 보고 팔아버린다. 그러면 일상 주문이 품절된다. 철칙을 만들어라. 안전 재고를 건드리려면 승인이 필요하고, 건드리면 보충이 발동된다. SOP에 넣어라 — 어떤 소프트웨어보다 낫다.

다중 창고: 건물별로 수위선을 나눠라

지금까지는 전부 단일 창고 사고다. 다중 창고 기업은 수위선을 시설별로 계산한 뒤 합산해야 한다. 왜? 창고 A의 "재고 있음"은 3일 운송 거리의 창고 B 고객에게는 아무 의미가 없기 때문이다.

표준 패턴은 최단거리 풀필먼트 + 창고별 ATP다. 각 건물이 네 개의 수위선을 직접 계산하고, 주문 라우팅은 판매 가능 재고가 있는 가장 가까운 건물을 우선한다. 모든 건물의 판매 가능 수량이 0일 때만 창고 간 이송 풀필먼트를 허용해야 하고 — 이송 운송 시간은 약속 배송일에 넣는다. 어떤 회사들은 네트워크 재고를 합산해 예쁜 "재고 있음" 배지를 만들고, 빈 건물로 주문을 라우팅한 뒤, 내부 이송 폭풍 속에서 SLA가 무너지는 걸 구경한다. 기억하라. 합산 숫자는 경영 대시보드용이고, 풀필먼트는 건물별 숫자로 돈다.

이송 자체도 모델에 넣는다. 이송 주문이 확정되는 순간, 출고 건물의 판매 가능 수량은 즉시 줄고, 입고 건물의 운송 중에 입고 예정일이 더해진다. 이송을 그룹 채팅으로 돌리고 시스템 문서 없이 처리하는 회사가 너무 많다 — 장부는 영원히 안 맞는다. 이송은 시스템 트랜잭션이어야 한다. 협상 불가다.

하나로 묶는 공식 하나

판매 가능 수량 = 판매 가능 보유분 − 예약 − 안전 재고 + 확정 운송 중(시점별·할인 적용).

공식은 쉽고, 어려운 건 데이터 품질이다. 오버셀이 나면 시스템을 윽박지르지 말고 이 디버깅 체인을 밟아라. 하나: 보유 수량이 정확한가? 먼저 세어라. 장부와 현장이 안 맞으면 나머지는 전부 무의미하다. 오차가 숨기 좋아하는 QA 구역과 반품 구역은 특히 신경 써라. 둘: 예약이 제때 해제되는가? 죽은 주문이 물고 있는 좀비 예약 리포트를 뽑아라 — 판매 가능 재고의 5%를 넘으면 룰을 바꿔라. 셋: 운송 중 날짜가 정직한가? 공급사를 6개월 정시 입고로 채점하라. 만성 낙관주의자는 선판매 비율 0이다. 넷: 안전 재고를 털었는가? 프로모션 기간 이동 내역을 확인하라 — 승인 없이 움직였으면 보충하기 전에 프로세스를 고쳐라.

이 체인으로 10번 중 9번은 근본 원인을 찾는다. 나머지 한 번은 대개 인터페이스 지연이다. WMS→OMS 동기화가 15분 배치로 돌면, 성수기에는 그 블라인드 시간 안에 팔고 받고가 왕창 일어난다. 프로모션 기간에는 동기화를 실시간이나 1분 간격으로 올려라. 서버 비용 추가분은 오버셀 페널티보다 싸다.

최종 결론: OMS 재고 모델링에 은탄환은 없다. 철칙은 하나뿐 — 재고 상태를 잘게 쪼갤수록 오버셀은 줄어든다. 상태 쪼개기를 귀찮아한 회사는 페널티라는 수업료를 낼 것이다. 네 개의 수위선을 똑바로 그으면, 서비스팀이 팔아도 된다고 여기는 숫자가 마침내 창고가 실제로 가진 숫자와 일치한다.

영어판 번역본입니다. 내용이 다를 경우 영어판을 우선합니다.