본문으로 건너뛰기

배송 서비스 (Shipping)

개요

배송 서비스는 주문 상품의 배송 생성, 추적, 상태 관리를 담당합니다. 국내 주요 택배사(CJ대한통운, 한진택배, 롯데택배)와 연동하여 실시간 배송 추적을 제공합니다.

항목
언어Python 3.11
프레임워크FastAPI
데이터베이스Aurora PostgreSQL
네임스페이스mall-services
포트8000
헬스체크GET /health

아키텍처

API 엔드포인트

배송 API

메서드경로설명
GET/api/v1/shipments/{order_id}주문별 배송 조회
POST/api/v1/shipments배송 생성
PUT/api/v1/shipments/{shipment_id}/status배송 상태 업데이트
GET/api/v1/shipments/{shipment_id}/tracking배송 추적 이력

요청/응답 예시

주문별 배송 조회

요청:

GET /api/v1/shipments/order_001

응답:

{
"id": "ship_001",
"order_id": "order_001",
"user_id": "user_001",
"shipping_address": "서울특별시 강남구 테헤란로 123, 456호",
"carrier": "CJ대한통운",
"tracking_number": "1234567890123",
"status": "IN_TRANSIT",
"tracking_history": [
{
"status": "PENDING",
"location": null,
"description": "배송 준비 중",
"timestamp": "2024-01-15T10:00:00Z"
},
{
"status": "PICKED_UP",
"location": "서울 송파 물류센터",
"description": "상품을 인수했습니다",
"timestamp": "2024-01-15T14:00:00Z"
},
{
"status": "IN_TRANSIT",
"location": "대전 허브터미널",
"description": "배송 중입니다",
"timestamp": "2024-01-16T08:00:00Z"
}
],
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-16T08:00:00Z"
}

배송 생성

요청:

POST /api/v1/shipments
Content-Type: application/json

{
"order_id": "order_002",
"user_id": "user_002",
"shipping_address": "부산광역시 해운대구 센텀로 456",
"carrier": "한진택배"
}

응답 (201 Created):

{
"id": "ship_002",
"order_id": "order_002",
"user_id": "user_002",
"shipping_address": "부산광역시 해운대구 센텀로 456",
"carrier": "한진택배",
"tracking_number": "9876543210987",
"status": "PENDING",
"tracking_history": [
{
"status": "PENDING",
"location": null,
"description": "배송 준비 중",
"timestamp": "2024-01-16T09:00:00Z"
}
],
"created_at": "2024-01-16T09:00:00Z",
"updated_at": "2024-01-16T09:00:00Z"
}

배송 상태 업데이트

요청:

PUT /api/v1/shipments/ship_002/status
Content-Type: application/json

{
"status": "OUT_FOR_DELIVERY",
"location": "부산 해운대 배송센터",
"description": "배송 기사님이 배송 출발했습니다"
}

응답:

{
"id": "ship_002",
"order_id": "order_002",
"user_id": "user_002",
"shipping_address": "부산광역시 해운대구 센텀로 456",
"carrier": "한진택배",
"tracking_number": "9876543210987",
"status": "OUT_FOR_DELIVERY",
"tracking_history": [
{
"status": "PENDING",
"location": null,
"description": "배송 준비 중",
"timestamp": "2024-01-16T09:00:00Z"
},
{
"status": "OUT_FOR_DELIVERY",
"location": "부산 해운대 배송센터",
"description": "배송 기사님이 배송 출발했습니다",
"timestamp": "2024-01-17T08:30:00Z"
}
],
"created_at": "2024-01-16T09:00:00Z",
"updated_at": "2024-01-17T08:30:00Z"
}

배송 추적 이력

요청:

GET /api/v1/shipments/ship_001/tracking

응답:

[
{
"status": "PENDING",
"location": null,
"description": "배송 준비 중",
"timestamp": "2024-01-15T10:00:00Z"
},
{
"status": "PICKED_UP",
"location": "서울 송파 물류센터",
"description": "상품을 인수했습니다",
"timestamp": "2024-01-15T14:00:00Z"
},
{
"status": "IN_TRANSIT",
"location": "대전 허브터미널",
"description": "배송 중입니다",
"timestamp": "2024-01-16T08:00:00Z"
},
{
"status": "DELIVERED",
"location": "서울 강남구",
"description": "배송이 완료되었습니다",
"timestamp": "2024-01-16T14:00:00Z"
}
]

데이터 모델

ShipmentStatus (Enum)

class ShipmentStatus(str, Enum):
PENDING = "PENDING" # 배송 준비 중
PICKED_UP = "PICKED_UP" # 상품 인수
IN_TRANSIT = "IN_TRANSIT" # 배송 중
OUT_FOR_DELIVERY = "OUT_FOR_DELIVERY" # 배송 출발
DELIVERED = "DELIVERED" # 배송 완료

Shipment

class Shipment(BaseModel):
id: Optional[str] = None
order_id: str
user_id: str
shipping_address: str
carrier: Optional[str] = None
tracking_number: Optional[str] = None
status: ShipmentStatus = ShipmentStatus.PENDING
tracking_history: list[TrackingEvent] = []
created_at: datetime
updated_at: datetime

TrackingEvent

class TrackingEvent(BaseModel):
status: ShipmentStatus
location: Optional[str] = None
description: Optional[str] = None
timestamp: datetime

ShipmentCreate

class ShipmentCreate(BaseModel):
order_id: str
user_id: str
shipping_address: str
carrier: Optional[str] = None

PostgreSQL 테이블 스키마

CREATE TABLE shipments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_id VARCHAR(50) NOT NULL UNIQUE,
user_id VARCHAR(50) NOT NULL,
shipping_address TEXT NOT NULL,
carrier VARCHAR(50),
tracking_number VARCHAR(50),
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE tracking_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
shipment_id UUID REFERENCES shipments(id),
status VARCHAR(20) NOT NULL,
location VARCHAR(200),
description TEXT,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_shipments_order_id ON shipments(order_id);
CREATE INDEX idx_shipments_user_id ON shipments(user_id);
CREATE INDEX idx_tracking_events_shipment_id ON tracking_events(shipment_id);

이벤트 (Kafka)

구독 토픽

토픽이벤트설명
orders.confirmed주문 확정재고 확보 후 배송 생성 트리거

발행 토픽

토픽이벤트설명
shipping.created배송 생성배송 정보 생성 시 발행
shipping.status-updated상태 변경배송 상태 변경 시 발행
shipping.delivered배송 완료배송 완료 시 발행

이벤트 페이로드 예시

orders.confirmed (구독):

{
"event_type": "order.confirmed",
"order_id": "order_001",
"user_id": "user_001",
"shipping_address": "서울특별시 강남구 테헤란로 123",
"items": [
{"product_id": "prod_001", "quantity": 2}
],
"timestamp": "2024-01-15T10:00:00Z"
}

shipping.status-updated (발행):

{
"event_type": "shipping.status-updated",
"shipment_id": "ship_001",
"order_id": "order_001",
"user_id": "user_001",
"status": "OUT_FOR_DELIVERY",
"carrier": "CJ대한통운",
"tracking_number": "1234567890123",
"timestamp": "2024-01-16T08:30:00Z"
}

환경 변수

변수명설명기본값
SERVICE_NAME서비스 이름shipping
PORT서비스 포트8080
AWS_REGIONAWS 리전us-east-1
REGION_ROLE리전 역할 (PRIMARY/SECONDARY)PRIMARY
DB_HOSTAurora PostgreSQL 호스트localhost
DB_PORTAurora PostgreSQL 포트5432
DB_NAME데이터베이스 이름shipping
DB_USER데이터베이스 사용자mall
DB_PASSWORD데이터베이스 비밀번호-
KAFKA_BROKERSKafka 브로커 주소localhost:9092
LOG_LEVEL로그 레벨info

서비스 의존성

의존하는 서비스

  • Aurora PostgreSQL: 배송 데이터 저장
  • MSK Kafka: 이벤트 발행/구독
  • Order Service: orders.confirmed 이벤트 수신

의존받는 서비스

  • Notification Service: 배송 상태 알림 발송
  • Analytics Service: 배송 현황 대시보드
  • Order Service: 배송 완료 시 주문 상태 업데이트

택배사 연동

지원 택배사

택배사코드API 연동
CJ대한통운CJ실시간 추적
한진택배HANJIN실시간 추적
롯데택배LOTTE실시간 추적

배송 상태 매핑

배송 상태CJ대한통운한진택배롯데택배
PENDING접수접수완료접수
PICKED_UP집하상품인수집화처리
IN_TRANSIT이동중배송중간선상차
OUT_FOR_DELIVERY배송출발배달출발배달출발
DELIVERED배달완료배달완료배달완료