소개
저는 축산물 운송 플랫폼 구축중입니다.
배차 프로그램은 시장에 많지만, 일반 화물용 TMS는 우리 도메인에 잘 안 맞아요. 축산물 운송은 다음과 같은 법적·생물학적 제약을 동시에 만족해야 합니다.
축산법 제17조의3 — 가 축운반차량 GPS 의무장착 (미장착 과태료 300만원)
가축전염병 예방법 제19조 — ASF/구제역/AI 발생지 반경 10km 이동 제한
축산물 위생관리법 — 냉장 0~4℃, 냉동 -18℃ 이하 유지
동물보호법 제11조 — 생체 운송 시 연속 운행 시간 제한
화물자동차 운수사업법 표준운임 — 표준운임 + 부가세 전자발행
기존 TMS는 위 제약 중 어느 것도 자동 반영을 못 하니, "오더 검증 → 차량 매칭 → 라우팅 → 운임 산출 → 모니터링"을 각각 도메인 지식을 가진 멀티에이전트로 분리해서 만들어보자는 게 출발점이었습니다.
목표는 거창했지만 저는 코딩이 능숙하지 않습니다. 그래서 Claude Code에 자연어로 요청하면서 처음부터 끝까지 만들어 봤고, 그 과정을 공유합니다.
진행 방법
사용한 도구
도구
용도
Claude Code (Opus 4.7)
메인 — 자연어로 코드·디버깅·문서화
카카오 디벨로퍼스
지도 SDK + 모빌리티 길찾기 API (실거리·도로 vertex)
Streamlit
운영 대시보드 UI
Google OR-Tools
멀티디포 CVRP 라우팅 솔버
Python 3.12 (python-embed)
런타임
핵심 프롬프트와 진행 흐름
1) 시작 — "배차 프로그램 가동할수 있어?"
세션을 이 한 줄로 시작했습니다. Claude가 프로젝트 구조를 읽고 시드 데이터로 한 번 돌려본 다음, 가장 먼저 만난 문제가 시드 차량 12대의 소독필증이 모두 만료돼서 "차량 0대"로 OR-Tools가 죽는 상황이었어요. 코드가 아니라 데이터 문제를 짚어주는 게 인상적이었습니다.
2) 스케일 업 — "100대 가상데이터 가동하여 설계 해줘. 그리고 대시보드로 실제로 카카오 모빌리티에서 구현하도록 해줘"
이 한 줄에 Claude가 작업을 분해했습니다.
결정적 난수 기반 시드 생성기 (
data/generate_seed.py) — 차량 100대 + 오더 200건, 한국 축산 거점(농장/LPC/공판장/마트) 좌표 hotspot으로 분포 생성카카오 지도 SDK + 폴리라인 + 범례 + 마커 + InfoWindow
키 없을 때 자동 폴백(Folium/OSM)
# 차량 시드 생성 — 5% 의도적 자격미달(필터 검증용)
is_noncompliant = rng.random() < 0.05
if is_noncompliant:
disinfect_until = future_date(rng, today, -180, -30) # 만료
gps = False
else:
disinfect_until = future_date(rng, today, 30, 540)
gps = True
3) "실제로 차량경로는 직선이 아니고 실제도로 주행하는 것인데 지도상에 나타난 것은 그렇지 않아"
가장 중요한 한마디였습니다. 처음에는 단순히 두 좌표를 직선으로 잇고 있었는데, 이걸 보고 카카오 모빌리티 길찾기 API를 통합했어요. 그리고 Claude가 한발 더 나갔습니다 — "시각화만의 문제가 아니라 거리·시간·운임 계산 전부 직선 기준이라 잘못 나와있다"고 짚어주면서 2-pass 구조로 재설계.
# 좌표 4자리 반올림(±11m)으로 캐시 키 → 같은 OD는 1회만 호출
def _cache_key(o_lat, o_lng, d_lat, d_lng):
return f"{_round(o_lat)},{_round(o_lng)}->{_round(d_lat)},{_round(d_lng)}"
# ThreadPoolExecutor로 8 워커 병렬 + 진행률 콜백
def build_matrix(pairs, max_workers=8, progress_cb=None):
...
결과: 실제 도로 거리가 직선 거리의 1.16~1.32배. 운임이 그만큼 저평가되고 있었던 거예요.
4) "순차적으로 만들어 줘"
남은 작업을 한 번에 처리. 도중에 "미배차는 용차 차량을 더 투입해서 처리하면 시나리오 추가"라는 도메인 요구사항을 던졌고, Claude가 SPOT-001~108 가상 용차를 자동 투입하는 시나리오를 즉시 구현했습니다.
# 미배차 오더에 가상 용차(SPOT) 일대일 배정 — 단가 +20% 할증
spot_vehicle = {
"vehicle_id": f"SPOT-{i:03d}",
"carrier_name": "외주 (용차)",
"current_lat": order["shipper_lat"], # 픽업 지점 현장 배차 가정
"is_spot": True,
}
subtotal = int(cost["subtotal"] * (1 + surcharge)) # +20%
OR-Tools도 멀티디포 CVRP + 픽업-배송 페어 + 8시간 운행 제약 + 미배차 페널티로 정상화했고, 차량당 8시간 초과 0건으로 들어왔습니다.
캡처
[직접 첨부 — 다음 캡처를 추천]
한반도 지도에 차량별 컬러 폴리라인이 도로를 따라가는 모습
운임 분석 차트 (자가 vs 용차)
카카오 모빌리티 적용 전/후 비교 (직선 → 도로 형태)
결과와 배운 점
최종 결과
지표
값
차량 시드
100대 (92대 적격 + 8대 의도적 자격미달)
오더 시드
200건 (돼지 118 / 한우 46 / 육계 36)
OR-Tools 라우팅
자가 52대 배정 / 8시간 초과 0건
용차 자동 투입
SPOT-001~107로 미배차 잔여 처리
미배차
0건 (목표 달성)
운임 (자가 + 용차 +20%)
약 2.46억원
카카오 모빌리티 API 호출
OD 약 350쌍 (캐시 적중 시 0건)
시행착오 (이게 가장 도움될 부분)
Python 환경 segfault —
.venv가 손상된 시스템 Python을 가리켜 모든 명령이 죽었어요. Claude가 다른 정상 Python(python-embed)을 찾아 우회. 코드가 아닌 환경 문제를 의심하는 습관이 중요.Streamlit이 카카오 SDK를 차단 —
st.components.v1.html이 만드는 srcdoc iframe은 외부 스크립트를 못 받아옵니다. 새 탭에서 SDK URL을 열면 정상 JS가 오는데 iframe 안에서만 안 됐어요. 해결:enableStaticServing=true+ui/static/폴더에 HTML 파일로 떨어뜨려/app/static/경로로 일반 iframe.카카오 도메인 등록 누락 —
domain mismatched! caller=http://localhost:8501. 콘솔에서 앱 설정 → 플랫폼 키 → JavaScript SDK 도메인에http://localhost:8501정확히 등록(슬래시 끝 X, https 아님)하고 저장 버튼까지 눌러야 적용. 입력만 하고 저장 안 한 게 문제였어요.직선 거리로 운임 계산 — 화면에 직선이 보여서 그제야 "이거 운임도 잘못 계산되는 거 아닌가?" 깨달았습니다. 실거리는 1.2
1.3배라서 운임이 2030% 저평가됨. AI에게 결과를 의심하는 질문을 던지는 게 큰 개선으로 이어졌습니다.
꿀팁 5가지
에러 메시지에서 멈추지 말고 서버 응답을 직접 확인하세요.
curl로 카카오 SDK에Referer: http://localhost:8501헤더 붙여 보내면 401과domain mismatched메시지가 바로 나옵니다. Claude가 이렇게 디버깅하는 걸 보고 배웠어요."이거 잘못된 거 아닌가요?" 같은 질문이 가장 큰 개선을 만듭니다. AI가 만든 결과를 의심하는 한마디가 코드 한 줄 짜는 것보다 임팩트 큽니다.
시드 데이터를 결정적 난수로 만드세요.
random.seed(20260524)한 줄 추가하면 매번 똑같은 데이터가 나와 검증·재현·시연이 쉬워집니다.API 캐싱은 좌표 반올림 + 영구 캐시로. 좌표 소수 4자리(±11m)면 같은 곳으로 취급, JSON 파일에 누적 저장하면 두 번째 실행부터 0 API 호출.
도메인 전문가의 한마디가 코드 100줄보다 가치 있습니다. "용차 시나리오 추가"라는 한 줄 요구사항이 미배차 113건을 0건으로 바꿨어요. AI에게 도메인 지식을 자연어로 던지는 게 최고의 프롬프트입니다.
도움이 필요한 부분
OR-Tools 튜닝: 자가 차량 92대 중 52대만 사용되고 40대가 유휴 상태입니다. 시드의 지리적 편향(충남·전남 집중) 때문인데, 더 효율적인 분배 알고리즘을 아시는 분 조언 환영합니다.
실시간 GPS 연동: 지금은 시뮬레이션 슬라이더로 추적합니다. 실제 GPS 디바이스 → MQTT/WebSocket 스트림을 어떻게 가장 가볍게 받을지 고민 중입니다.
카카오 모빌리티 무료 한도(일 50K) 이후 비용 구조 — 실제 운영 단계에서는 OD 매트릭스를 자체 PostGIS + OSRM으로 가져가야 할지 검토 중입니다.
앞으로의 계획
KAHIS Open API 연동 — 지금은 수동 입력인 방역대를 실시간으로 가져오기
mtrace.go.kr 축산물이력제 API — 오더 입력 시 이력번호 자동 검증
국세청 e세로 — 운임 확정 후 전자세금계산서 자동 발행
MCP 서버화 — 각 외부 API를 MCP로 래핑해서 Claude Agent SDK로 본격 전환
도움 받은 글
Streamlit Static File Serving —
[server] enableStaticServing = true
한국사이트 스크린샷
숫자 목록이 포함된 한국어 앱 스크린샷
한국음악의 인기를 보여주는 그래프
한국 증권 거래소의 스크린샷
검은 화면에 표시된 한국어 앱 스크린샷
다양한 위치가 있는 한국 지도