해상운임 예측 모델을 만들고 나면 보통 성능표가 남습니다. 그런데 현업의 질문은 조금 다릅니다. “어느 항로에서 오차가 큰가?”, “복합 위기가 오면 운임 변화를 제대로 잡는가?”, “지연 경보를 사람이 몇 건이나 검토해야 하는가?” 평균 오차 하나로는 답하기 어려운 질문들입니다.
그래서 30개 해상운임 시나리오와 항로 및 월별 오차, 모델 구조, 스트레스 재현력, 지연 경보 비용을 한 화면에 모았습니다. 완성한 대시보드는 Vercel에 배포했습니다.
완성된 대시보드: https://scm-freight-ml-dashboard.vercel.app/
실제 선사 견적이나 운영 데이터는 쓰지 않았습니다. 교육용 합성 데이터로 안전한 머신러닝 검증 절차와 의사결정용 대시보드 구성을 실험한 결과물입니다. 운영 예측 서비스는 아닙니다.
수요, 선복, 지정학, 연료, 기후, 노무, 환율, 장비, 계약, 복합 위기 등을 반영해 30개 시나리오를 구성했습니다. 시나리오마다 합성 견적 10,000건씩, 모두 300,000건입니다. 기간은 2022년부터 2025년까지이며 10개 항로를 포함했습니다.
화면에서는 시나리오별 P50, 평균, P90 운임을 같은 카드 구조로 보여줍니다. 이름으로 검색하거나 카테고리로 거를 수 있고, 평균 운임과 WAPE 기준 정렬도 가능합니다. 추세 및 버블 차트를 바꿔 볼 수 있으며 카드를 누르면 평균 운임, P90, Test WAPE, 스트레스 포착률이 한곳에 나타납니다.
가장 신경 쓴 부분은 데이터 누출이었습니다. 견적일에 알 수 있는 변수만 허용하고, 실제 도착일 및 실제 지연일 및 실현 운임처럼 결과가 나온 뒤 생기는 realized_* 18개 컬럼은 입력에서 뺐습니다.
Train, Validation, Test도 견적일 순서로 나눴습니다. 최대 리드타임을 반영해 구간 사이에 45일씩 비웠고, 세 구간의 날짜가 겹치지 않는지 검사했습니다. 모델과 임계값은 Validation에서 정했습니다. 최종 Test는 딱 한 번만 평가했습니다.
최근 180일 중앙값 기준선과 여러 회귀 및 분류 모델을 비교했고, 최종 회귀 Champion은 HistGradientBoosting이었습니다. RMSE, MAPE, R²만 보지 않고 설명가능성과 운영성도 함께 살폈습니다.
대시보드에는 상위 10개 순열 중요도, 항로별 WAPE와 Bias, 월별 실제 및 예측 운임, 롤링 백테스트를 넣었습니다. 시나리오별 실제 및 예측 변화와 스트레스 포착률, 3일 이상 지연 분류 혼동행렬, 검토율도 이어서 볼 수 있습니다. 마지막에는 지표의 뜻과 다음 행동을 짝지은 인사이트 9개를 배치했습니다.
프런트엔드는 React/Vite로 만들고 차트는 ECharts로 그렸습니다. 브라우저에 300,000건을 통째로 싣는 대신, 검증을 마친 집계 결과만 dashboard-data.json으로 분리했습니다. 원시 견적 행과 예측 샘플 행은 공개 배포 데이터에 넣지 않았습니다.
데이터 로딩에 실패하면 오류 상태와 다시 시도 버튼이 나타납니다. 현재 공개본은 검증된 정적 스냅샷을 읽는 구조이고, Vercel URL만 열면 결과를 확인할 수 있습니다.
최종 Test에서 HistGradientBoosting은 MAPE 22.75%, RMSE 1,181.38달러, R² 0.740, WAPE 20.58%, Bias +78.46달러를 기록했습니다. Validation RMSE는 최근 180일 중앙값 기준선보다 19.67% 낮았습니다.
하지만 이번 작업에서 가장 크게 배운 것은 보기 좋은 숫자 하나로 운영 가능성을 판단하면 안 된다는 점입니다.
3일 이상 지연 분류 모델의 Recall은 99.77%였습니다. 지연을 거의 놓치지 않은 셈입니다. 문제는 임계값 0.15에서 전체의 97.78%를 사람이 검토해야 한다는 점이었습니다. 과잉 경보는 21,817건, 지연 미탐은 44건이었습니다. Recall만 보면 성공처럼 보이지만 이 경보량은 그대로 운영하기 어렵습니다.
스트레스 테스트에서도 비슷한 한계가 보였습니다. 글로벌 경기 침체 시나리오에서 기준 대비 실제 변화는 -61.00달러였지만 예측 변화는 -6.51달러에 그쳤습니다. 변화폭 포착률은 10.67%였습니다. 평균 오차가 괜찮아도 충격의 방향과 크기를 충분히 재현하지 못할 수 있다는 뜻입니다.
처음 부딪힌 문제는 분할 방식이었습니다. 무작위 분할은 미래 정보가 섞일 수 있어 견적일 기준 시간 분할과 45일 purge로 바꿨습니다.
시나리오 30개를 모두 큰 차트로 펼치자 화면도 금세 복잡해졌습니다. 카드에는 동일한 핵심 지표만 남기고, 검색, 카테고리, 정렬 및 선택 상세 영역으로 역할을 나눴습니다.
배포 범위도 줄였습니다. 원시 데이터 300,000건을 그대로 올리면 로딩이 무거워지고 공개할 정보도 많아집니다. 웹 화면에 필요한 제한된 집계값만 따로 만들었습니다.
마지막은 지표 표현이었습니다. 높은 Recall만 강조하면 운영 부담이 가려집니다. 혼동행렬 옆에 검토율과 과잉 경보 건수를 함께 놓은 이유입니다.
실제 업무 데이터에 연결하기 전, 데이터 권한과 비식별 기준부터 정리할 계획입니다. 견적 시점 스냅샷도 함께 설계해야 합니다. 지연 경보 임계값은 오분류 비용뿐 아니라 운영자가 하루에 검토할 수 있는 건수를 제약조건으로 넣어 다시 계산하려고 합니다. 복합 위기에는 점예측 하나만 두지 않고 예측구간과 규칙 기반 충격값을 함께 보여주는 방법도 실험해 보겠습니다.
모델을 만드는 일만큼 중요한 것은 “어디까지 믿고, 어떤 조건에서 사람이 개입해야 하는지”를 드러내는 일이었습니다. 이번 대시보드는 그 질문에 답해 본 첫 결과물입니다.
<!-- HUMANIZE-SUMMARY
원본/윤문본: 측정 예정
변경률: 측정 예정
탐지: A-10, C-2, E-1, E-2, H-1 및 I-4 (before) → S1 0건, S2 2건 이하 (after)
자체검증: 6/6 통과
등급: A — 사실, 수치 및 고유명사를 보존하고 문장 리듬과 기계적 병렬만 완화
주요 변경:
-->
원문: 천동암, 지피터스 GPTers (2026.08.11) gpters.org 원문 보기