카테고리 없음

AI Sales Forecasting 6: 서비스레벨·안전재고·ROP 설계

Royzero 2026. 2. 10. 10:08
반응형

TL;DR

  • AI Sales Forecasting의 “정답”은 MAPE가 아니라, 목표 서비스레벨/비용을 만족하는 발주 의사결정이다.
  • 발주점(ROP)·안전재고는 “리드타임 동안의 수요 분포”를 만들고, 원하는 서비스레벨에 해당하는 분위수(quantile)를 쓰면 된다.
  • 단, 일자별 P95를 더해서 리드타임 P95를 만들면 안 된다(분위수는 합산 불가). 샘플 경로(시뮬레이션)로 합산해 분포를 만든다.
  • 단발성(프로모션/시즌) 발주는 Newsvendor(크리티컬 프랙타일)로 “부족비용 vs 과잉비용”을 분위수로 바꿀 수 있다.
  • 예측 구간(PI)이 과신되면 서비스레벨이 무너진다. 컨포멀(conformal)로 구간 커버리지를 보정하는 게 안전하다.

본문

TOC

    1. 이번 차시 목표와 사전 준비
    1. 서비스레벨: CSL vs Fill Rate를 먼저 고르기
    1. 재고 정책 선택: (s,Q)·(s,S)·(R,S)·Newsvendor
    1. 핵심 절차: “리드타임 수요 분포” → 분위수 → ROP/Order-up-to
    1. 실전 예시(숫자) + 구현 스니펫
    1. 검증(모니터링) 포인트
    1. 트러블슈팅 3종
    1. 실무 체크리스트(배포 전 / 운영 중)
  • FAQ

1) 이번 차시 목표와 사전 준비

목표

AI Sales Forecasting(확률 예측)을 “발주 추천(언제/얼마나)”로 바꾸는 설계를 끝낸다.

사전 준비(최소)

  • SKU×로케이션별 판매 이력 + 캘린더(휴일/프로모션)
  • 리드타임(평균+변동): 실제 PO/입고 기준으로 측정
  • 발주 제약: MOQ, 박스입수, 로트, 유통기한(있다면)
  • 재고 상태: on-hand, on-order, backorder/committed(가능하면)

Why it matters: 예측이 좋아도 리드타임·제약·재고정의가 틀리면, 발주 추천은 바로 망가진다.


2) 서비스레벨: CSL vs Fill Rate를 먼저 고르기

재고 목표를 “서비스레벨 95%”라고 말할 때, 그게 CSL인지 Fill Rate인지부터 확정해야 한다.

지표 의미 언제 쓰나 함정
CSL (Cycle Service Level) 한 replenishment cycle에서 품절이 안 날 확률(빈도) 품절 “사건(event)”을 줄이고 싶을 때 품절 “양(규모)”은 무시한다
Fill Rate(=Item Fill Rate) 수요 중 즉시 충족된 물량 비율(규모) 고객 경험/결품량이 핵심일 때 변동이 크면 CSL 높아도 Fill Rate는 낮을 수 있다

Why it matters: 같은 “95%”라도 CSL 기준이면 재고가 적게 필요해 보일 수 있지만, 결품량(미충족 수요)이 커질 수 있다.


3) 재고 정책 선택: (s,Q)·(s,S)·(R,S)·Newsvendor

예측을 발주로 바꾸는 방법은, 결국 어떤 재고 정책을 쓰느냐로 결정된다.

정책 주문 트리거 주문량 대표 사용
(s,Q) 연속검토 IP ≤ s 이면 고정 Q 단순 자동발주(두-bin), 중간 SKU
(s,S) 연속검토(min-max) IP ≤ s 이면 S−IP A급 SKU(중요/고가), 예외관리
(R,S) 정기검토 매 R마다 S−IP 발주일 고정(주 1회/월 2회), 묶음발주
Newsvendor(단일기간) 단일 시즌/행사 q* 프로모션/신제품 런칭/부패성 재고

여기서 IP(Inventory Position) 정의가 핵심이다:
IP = (재고 on-hand) + (발주했지만 아직 안 온 물량 on-order) − (백오더/커밋 등)

Why it matters: 같은 예측이라도 (R,S)는 보호기간이 리드타임+리뷰주기라서 보통 안전재고가 더 필요하다.


4) 핵심 절차: “리드타임 수요 분포” → 분위수 → ROP/Order-up-to

4-1. 리드타임 수요 분포를 만든다

발주점(ROP)은 “리드타임 동안의 예상 수요 + 버퍼”로 설명된다.

문제는 “예상 수요”가 분포라는 점이다. 방법은 2가지:

  1. 샘플 기반(권장)
  • 모델이 미래 경로 샘플(시나리오)을 K개 뽑아주면
  • 각 샘플에 대해 리드타임 구간의 일수요를 합산해서 DLT(lead time demand) 샘플 K개를 만든다
  • 그 샘플들의 분위수로 P90/P95 등을 바로 얻는다
  1. 분위수(quantile)만 있는 경우(주의)
  • 일자별 P95를 더해서 “7일 P95”를 만들면 안 된다(일반적으로 틀림)
  • 가능하면 모델 출력 형태를 “샘플 경로”로 바꾸거나, 별도 시뮬레이션/컨볼루션이 필요

Why it matters: 안전재고/ROP는 “한 날의 수요”가 아니라 “리드타임 누적 수요”의 tail(꼬리)을 보는 문제다.

4-2. 목표 서비스레벨을 “분위수”로 바꾼다

  • CSL 목표 α(예: 0.95)라면, 단순화해서
    • ROP(= s) ≈ Quantile_α(리드타임 수요 DLT)
    • Safety Stock = ROP − E[DLT]
      이 관점은 “리드타임 커버 + 안전재고” 프레임과 맞는다.
  • 정규성 가정하에서는 Z-score×표준편차 형태로도 계산한다(고전식).

4-3. (s,S) / (R,S)로 주문량을 만든다

  • (s,S) 연속검토: IP ≤ s 이면 주문량 = S − IP
  • (R,S) 정기검토: 매 R마다 주문량 = S − IP

여기서 S는 보통 “보호기간(리드타임+리뷰주기) 수요 분포”의 분위수로 잡는다.

4-4. 단일기간(프로모션) 발주는 Newsvendor로 정리한다

Newsvendor는 “부족비용(Cu) vs 과잉비용(Co)”을 크리티컬 프랙타일로 바꾼다.
P(Demand ≤ q*) = Cu / (Cu + Co)

즉, 원하는 분위수를 한 번에 정의한다. (AI Sales Forecasting이 확률분포를 주면 바로 q* 계산 가능)

Why it matters: “MAPE 10%” 같은 지표보다, “부족이 더 비싼 상품”이면 애초에 높은 분위수로 주문하는 게 최적일 수 있다.


5) 실전 예시(숫자) + 구현 스니펫

예시 가정

  • 일 단위 발주 판단, 리드타임 7일
  • 모델이 7일 미래 수요 샘플 경로를 10,000개 생성
  • 합산해 만든 DLT 분포에서
    • E[DLT]=700, P95(DLT)=820
  • 목표 CSL=95%라면
    • ROP(s)=820, Safety Stock=120

ROP의 “형식” 자체는 많이 쓰는 공식(리드타임 수요 + 안전재고)과 동일하다.

주문 의사결정(예: (s,S))

  • 현재 IP=600
  • s=820, S=900(운영상 상단 캡/목표 base-stock)이라면
  • IP ≤ s 이므로 주문량 = 900 − 600 = 300
# 핵심 로직(의사코드)
inventory_position = on_hand + on_order - backorders - committed  # 정의는 ERP에 맞춰 확정
if inventory_position <= s:   # s = ROP
    order_qty = max(0, S - inventory_position)  # (s,S)
else:
    order_qty = 0
# 이후 MOQ/박스입수/로트/유통기한 제약 적용

Why it matters: 발주 추천의 품질은 “예측값”이 아니라, IP 정의 + 정책 파라미터(s,S) + 제약 처리에서 결정된다.


6) 검증(모니터링) 포인트

예측 모델 검증(백테스트) 다음 단계는 “의사결정 검증”이다.

  1. 실현 CSL / Fill Rate
  • 목표(예: CSL 95%)를 실제로 달성하는지 주간/월간으로 측정
  1. 예측 구간(PI) 커버리지
  • 95% PI라면 실제가 구간 안에 약 95% 들어오는지 확인
  • 커버리지가 무너지면 안전재고/ROP가 체계적으로 틀어진다
  • 컨포멀 예측은 모델 불가지론적으로 커버리지 보정을 제공하는 접근으로 많이 연구/문서화돼 있다.
  1. 재고 비용 지표
  • 재고일수(DOS), 회전율, 폐기/할인(유통기한), 긴급발주 비율

Why it matters: “정확한 예측”이 아니라 “목표 서비스 + 최소 비용”이 목적이면, 모니터링 지표도 그 목적에 맞춰야 한다.


7) 트러블슈팅 3종

(1) 서비스레벨이 계속 깨진다

  • 원인: 리드타임 변동(σLT)을 무시 / PI 과신(언더커버) / 프로모션 라벨 누락
  • 해결:
    • 리드타임 분포를 측정해 DLT를 다시 시뮬레이션
    • 컨포멀로 PI 커버리지 보정 후 ROP 재산정

(2) 재고가 과도하게 쌓인다

  • 원인: CSL과 Fill Rate를 혼동 / 목표 α를 너무 높게 설정 / 상단 캡(S) 부재
  • 해결:
    • A/B/C 등급별로 목표 α 차등(중요 SKU만 높게)
    • (s,S)에서 S(최대 IP)로 과잉을 제어

(3) 발주 추천이 출렁여서 운영이 힘들다

  • 원인: 일 단위 노이즈를 그대로 주문에 반영 / MOQ·박스입수로 톱니형 주문 발생
  • 해결:
    • (R,S)로 발주일 고정 + 보호기간 분포로 S 산정 ([MIT OpenCourseWare][1])
    • 주문량 스무딩(상·하한, 변경폭 제한) + 예외 승인 흐름

Why it matters: 예측 문제처럼 보이지만, 대부분은 “정책/제약/정의” 문제다.


8) 실무 체크리스트

배포 전

  • SKU별 목표: CSL vs Fill Rate 확정
  • IP 정의(ERP/WMS 기준) 문서화
  • 리드타임(평균/분산) “실제 데이터”로 측정
  • 샘플 기반으로 DLT 분포 생성(분위수 합산 금지)
  • MOQ/박스입수/유통기한 제약을 주문 로직에 반영

운영 중

  • 실현 CSL/Fill Rate 주간 리포트
  • PI 커버리지(캘리브레이션) 추적, 필요 시 컨포멀 보정
  • 예외(override) 비율/사유 로깅 → 피처/정책 개선

Why it matters: 자동발주는 “모델”이 아니라 “운영 시스템”이다. 로그와 지표가 없으면 고장 난 걸 모른다.


FAQ

  1. CSL 95%면 “품절이 5%만 난다”는 뜻인가?
  • “사이클 기준으로 품절 사건이 날 확률”이다. 결품량(규모)은 Fill Rate로 봐야 한다.
  1. 일자별 P95를 더하면 리드타임 P95 아닌가?
  • 아니다(일반적으로 틀림). 샘플 경로 합산으로 DLT 분포를 만들어 분위수를 뽑아라.
  1. (R,S)가 (s,S)보다 재고가 더 필요한 이유는?
  • 다음 주문까지 “리뷰주기+리드타임”을 커버해야 해서 보호기간이 길다.
  1. Newsvendor의 Cu/Co는 어떻게 잡나?
  • Cu(부족비용)=마진 손실+대체구매/이탈 비용, Co(과잉비용)=보관+폐기/할인. 이 비율이 분위수를 결정한다.
  1. PI가 과신되는지(언더커버) 어떻게 아나?
  • 95% PI면 최근 구간에서 실제가 PI 안에 들어온 비율이 95% 근처인지 체크. 깨지면 컨포멀로 보정.
  1. 신제품(콜드스타트)은?
  • 유사 SKU 매핑(카테고리/가격대/채널) + 보수적 초기 α + 짧은 주기 재학습(또는 상위계층 모델)로 시작.

결론 (요약 정리)

  • AI Sales Forecasting → 발주의 핵심은 “리드타임(또는 보호기간) 수요 분포”를 만들고 분위수로 s/S를 정하는 것이다.
  • CSL/Fill Rate를 혼동하면 목표 자체가 어긋난다.
  • PI 커버리지가 무너지면 서비스레벨도 같이 무너진다. 컨포멀은 현실적인 보정 옵션이다.

References

반응형