SaaS APIProgress Table
배송 관리 개요
배송조회 자동 추적 시스템 전체 구조와 동작 방식
배송 관리 개요
운송장이 등록되면 배송 상태를 자동으로 추적·갱신하는 시스템입니다. 크리에이터에게 상품을 배송하는 캠페인에서, 운송장 입력 이후 배송완료까지 글로우비가 주기적으로 택배사를 조회해 상태를 따라갑니다.
Base URL: /ai/progress-table · 배송 데이터 저장소: TB_APPLICATION_DELIVERY
왜 만들었나
기존에는 운송장을 등록해도 이후 배송 상태가 자동으로 바뀌지 않아, 실제로는 배송완료된 건도 DB에는 계속 "배송중"으로 남아 있었습니다. 이 시스템은 그 간극을 메워 상태를 실제 배송과 동기화합니다.
아키텍처
[glowb-server]
10분 주기 폴링 스케줄러
│ (배송중 + 지원택배사 + 등록 14일 이내 송장 조회)
│ GraphQL 호출 (서비스 계정 ID 토큰 인증)
▼
[Cloud Run: glowb-delivery-tracker] ← 오픈소스 delivery-tracker 자체 운영
│ 택배사 조회 페이지 스크래핑 + 표준 코드로 정규화
▼
[CJ / 롯데 / 로젠 / 한진 / 우체국 ...]
│ 전체 배송 이벤트(집화·간선상차·간선하차·배송출발·배송완료 등) 반환
▼
[glowb-server]
· 전체 응답을 tracking_detail(JSON)에 통째로 저장
· 마지막 이벤트로 delivery_status 갱신
· 상태 전이 시 도메인 이벤트 발행 → 배송완료 시 제출 일정 재계산 + 트리거 로그 기록- 외부 유료 API 대신 오픈소스(delivery-tracker)를 Cloud Run에 직접 띄워 운영합니다.
- 택배사별로 제각각인 표현("배송완료/배달완료/배송완료 사진확인" 등)은 Cloud Run의 OSS가 표준 상태 코드(
DELIVERED등)로 정규화해 주므로, 서버는 코드만 보고 판정합니다.
배송 상태 (deliveryStatus)
| 값 | 의미 | 전환 시점 |
|---|---|---|
beforeDelivery | 배송 전 | 초기값 (운송장 없음) |
shipping | 배송 중 | 지원택배사(kr.*) 운송장 입력 시 자동 전환 (폴링 대상). 조회 안 됨(NOT_FOUND)도 여기 유지 |
delivered | 배송 완료 | 폴링이 택배사 DELIVERED 이벤트 감지 |
wrongTrackingNumber | 잘못된 운송장 번호 | 폴링 시 형식 오류(BAD_REQUEST) — 명백히 잘못된 번호, 정정 재입력 필요 |
invalidTracking | 배송조회 미지원 | 추적 미지원 택배사(OTHER/한글명) 운송장 입력 시 |
폴링 동작 규칙
- 주기: 10분마다 (
scheduler.delivery-polling.enabled로 토글) - 대상:
shipping+ 운송장 있음 + 지원 택배사(courier_code가kr.*) + 운송장 등록 시각(tracking_registered_at) 14일 이내 - 제외:
shipping이 아닌 상태(완료·미지원·잘못된번호·배송전), 기타(OTHER) 택배사, 14일 경과 건 — 모두 자동 제외 - 기준 시각: 14일 컷은 운송장 등록 시각(
tracking_registered_at) 기준입니다. 행 생성 시각(createdAt=선정 시점)과 다르며, 선정 후 며칠 뒤 운송장을 입력해도 입력 시점부터 계산됩니다. (등록 시각이 없는 legacy 건은createdAt로 폴백) - 조회 결과 처리
- 형식 오류(
BAD_REQUEST) → 즉시wrongTrackingNumber(명백히 잘못된 번호) - 조회 안 됨(
NOT_FOUND) →shipping유지, 다음 사이클 재시도. 지연일 수도 오타일 수도 있어 단정하지 않으며, 14일 컷오프까지 계속 시도(이후엔 폴링 빠지고shipping으로 남음) - 택배사/네트워크 일시 장애 → 상태 유지, 다음 사이클 재시도
- 형식 오류(
배송완료 → 일정 자동 재계산·트리거 로그 (TASK-071)
배송 상태 전이는 폴링 트랜잭션 커밋 후 비동기 이벤트로 처리되며, 전이 종류에 따라 TASK-071 일정/트리거 로그에 연결됩니다.
- 지원택배사 배송완료(
delivered) 감지 시 (Trigger 1-A): 제출 마감을 실제 배송완료일 기준으로 재산정(크리에이터 개별 + 캠페인).TRIGGER_1A_DELIVERY_INPUT가TB_TRIGGER_LOG에 기록됩니다. - 추적 미지원(
OTHER) 운송장 입력 시 (Trigger 1-A 추정): 실제 완료일을 알 수 없어 입력일 + 배송영업일 추정으로 제출 마감을 산정합니다.TRIGGER_1A_DELIVERY_ESTIMATE가 기록되고,deliveryStatus는invalidTracking(배송조회 미지원)으로 표기됩니다. - 그 외 전이(
wrongTrackingNumber등): 일정에는 영향이 없으며,TB_TRIGGER_LOG에DELIVERY_*(예:DELIVERY_WRONG_TRACKING_NUMBER) forensic 이력 1행만 append됩니다.
지원택배사는 입력 시 추정 없이 폴링이 실제 배송완료를 감지할 때만 일정을 확정합니다(1-A). 같은 운송장이라도 1-A와 1-A 추정은 동시에 발화하지 않습니다. 추적 미지원(OTHER)만 입력 시 추정으로 산정합니다. — ApplicationScheduleService/CampaignScheduleService의 임시 산정 TODO를 배송조회 연동으로 완성.
저장 데이터 (TB_APPLICATION_DELIVERY)
| 컬럼 | 설명 |
|---|---|
delivery_status | 배송 상태 (위 표) |
tracking_number | 운송장 번호 |
courier_code | 택배사 코드(kr.xxx) 또는 기타 한글명/OTHER |
tracking_detail | 배송조회 전체 응답(JSON). 폴링마다 최신 전체로 덮어씀. 단계별 타임라인 렌더링용 |
tracking_registered_at | 운송장 (재)입력 시각. 폴링 14일 컷오프의 기준 시각 (선정 시점 createdAt과 구분) |
shipped_at | 배송 시작(첫 추적=집화) 시각. 폴링 첫 정상 조회 시 1회 설정. 추적 불가 시 null |
delivered_at | 배송 완료 시각. 폴링이 DELIVERED 감지 시 해당 이벤트 시각 |
지원 택배사 (courierCode)
kr.* 코드만 자동 추적 대상이며, 그 외/OTHER는 추적되지 않습니다.
| 코드 | 표시명 |
|---|---|
kr.cjlogistics | CJ대한통운 |
kr.lotte | 롯데택배 |
kr.hanjin | 한진택배 |
kr.logen | 로젠택배 |
kr.epost | 우체국택배 |
kr.coupangls | 쿠팡(CLS) |
kr.cvsnet | GS편의점(CVSnet) |
kr.kdexp | 경동택배 |
kr.daesin | 대신택배 |
OTHER | 기타 (한글 자유입력 가능, 추적 제외) |
엔드포인트
| 메서드 · 경로 | 설명 |
|---|---|
PUT /application/delivery/tracking | 운송장+택배사 저장/수정 (저장 시 shipping 자동 전환) |
PUT /application/delivery/status/bulk | 배송 상태 일괄 변경 |
GET /application/{applicationId}/delivery | 배송 상세 조회 (courierCode·tracking_detail 포함) |
GET /collab/{collabNo}/delivery-addresses | 선정 크리에이터 배송지 목록 |
PUT /items/{id}/delivery-status · /items/{id}/tracking-number | (레거시) 진행표 항목 직접 수정 |
자동 추적은 운송장 등록 시 courierCode가 함께 저장된 건만 동작합니다. courierCode 없이 등록된 송장(예: 기존 데이터)은 폴링되지 않습니다.