🔔 웹훅 구독 API 가이드 - 택배 상태 변경 자동 알림
💡 이 가이드에서 배울 내용: 택배 상태가 변경될 때마다 자동으로 웹훅을 받는 방법, 웹훅 URL 등록부터 보안 검증까지 전체 플로우를 단계별로 설명합니다.
개요
웹훅 구독 API를 사용하면 택배사 송장번호를 등록하고, 배송 상태가 변경될 때마다 자동으로 알림을 받을 수 있습니다. 폴링(Polling) 방식 대신 이벤트 기반으로 알림을 받으므로 서버 리소스를 절약하고 실시간으로 배송 정보를 업데이트할 수 있습니다.
주요 특징
- 자동 폴링: 상태별 + 시간대별 폴링 (주간 30분~2시간, 야간 최소 2시간)
- 상태 변경 알림: 상태가 변경될 때만 웹훅 발송
- 선택적 구독: 원하는 상태(예: 배송중, 배송완료)만 알림 받기 가능
- Dual ID 지원: 서버 생성 ID 또는 클라이언트 지정 ID로 관리
- 보안 서명: HMAC-SHA256 서명으로 웹훅 검증
- 자동 재시도: 실패 시 최대 5회까지 자동 재시도
폴링 정책
상태별 폴링 주기
| 배송 상태 | 폴링 주기 | 설명 |
|---|---|---|
| PENDING, REGISTERED, PICKUP_READY | 2시간 | 상품 준비 단계 |
| PICKED_UP, IN_TRANSIT, OUT_FOR_DELIVERY | 30분 | 배송 진행 중 (빠른 업데이트) |
| DELIVERED, CANCELLED | 중지 | 구독 자동 완료 |
| FAILED, RETURNED, HOLD | 2시간 | 예외 상태 |
시간대별 폴링 조정 (KST 기준)
- 주간 (10:00~20:00): 상태별 주기 그대로 적용 (30분 또는 2시간)
- 야간 (20:00~10:00): 최소 2시간 주기로 조정
- 예: IN_TRANSIT(30분) → 야간에는 2시간으로 연장
- 예: PENDING(2시간) → 야간에도 2시간 유지
15일 자동 중단
구독 등록 후 15일이 경과하면 자동으로 폴링이 중단됩니다. 장기간 배송되지 않는 건에 대한 불필요한 조회를 방지하기 위한 정책입니다.
등록일: 2026-01-01
중단일: 2026-01-16 (15일 후)
15일째부터는 폴링이 더 이상 수행되지 않습니다.
1단계: 웹훅 URL 사전 등록
구독을 등록하기 전에, 알림을 받을 웹훅 URL을 먼저 등록해야 합니다. API Key당 최대 10개까지 등록 가능합니다.
요청 예시
curl -X POST "https://api.deliveryapi.co.kr/v1/webhooks/endpoints" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__" \
-d '{
"url": "https://your-domain.com/webhook",
"name": "주문 시스템"
}'
응답 예시
{
"isSuccess": true,
"data": {
"endpointId": "ep_6b78d0e9eac154e129847aae",
"url": "https://your-domain.com/webhook",
"name": "주문 시스템",
"webhookSecret": "whsec_91289c5160ec743e0721b4a23fb5d33c",
"dateCreated": "2026-01-13T10:30:33.292Z"
}
}
⚠️ 중요: webhookSecret은 최초 등록 시 딱 1회만 반환됩니다. 반드시 안전한 곳에 저장하세요. 이 값은 웹훅 서명 검증에 사용됩니다.
2단계: 구독 등록
등록한 웹훅 URL의 endpointId를 사용하여 송장번호를 구독합니다. 1회 요청으로 최대 100건까지 일괄 등록 가능합니다.
요청 예시
curl -X POST "https://api.deliveryapi.co.kr/v1/tracking/subscriptions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__" \
-d '{
"items": [
{
"id": "order-001",
"courierCode": "04",
"trackingNumber": "123456789012",
"endpointId": "ep_6b78d0e9eac154e129847aae",
"subscribedStatuses": ["IN_TRANSIT", "DELIVERED"],
"metadata": { "orderId": "ORD-001" }
}
]
}'
요청 필드 설명
| 필드 | 필수 | 설명 |
|---|---|---|
id |
선택 | 클라이언트가 지정하는 ID (예: 주문번호). API Key 내에서 유니크해야 함 |
courierCode |
필수 | 택배사 코드 (예: 04=CJ, 05=한진, 08=롯데) |
trackingNumber |
필수 | 송장번호 |
endpointId |
필수 | 사전 등록한 웹훅 URL의 ID |
subscribedStatuses |
선택 | 알림받을 상태 목록. 미지정 시 모든 상태 알림 |
metadata |
선택 | 추가 정보 (JSON 객체). 웹훅 발송 시 함께 전달됨 |
응답 예시
{
"isSuccess": true,
"data": {
"results": [
{
"id": "order-001",
"subscriptionId": "sub_cb0d4e05b5ca97f777b72215",
"success": true,
"currentStatus": "PENDING"
}
],
"summary": {
"total": 1,
"successful": 1,
"failed": 0
}
}
}
✅ Dual ID 시스템: 응답에서 id(클라이언트 지정)와 subscriptionId(서버 생성) 둘 다 반환됩니다. 이후 조회/취소 시 둘 중 어느 것을 사용해도 됩니다.
3단계: 웹훅 수신 및 검증
배송 상태가 변경되면 등록한 URL로 웹훅이 전송됩니다.
웹훅 페이로드
{
"event": "tracking.status_changed",
"subscriptionId": "sub_cb0d4e05b5ca97f777b72215",
"timestamp": "2026-01-13T10:30:00.000Z",
"data": {
"courierCode": "04",
"trackingNumber": "123456789012",
"previousStatus": "IN_TRANSIT",
"currentStatus": "DELIVERED",
"tracking": {
"courierCode": "04",
"trackingNumber": "123456789012",
"status": "DELIVERED",
"details": [...]
}
},
"metadata": { "orderId": "ORD-001" }
}
보안 서명 검증 (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(req, webhookSecret) {
const signature = req.headers['x-webhook-signature'];
const timestamp = req.headers['x-webhook-timestamp'];
const body = JSON.stringify(req.body);
// 타임스탬프 검증 (5분 이내)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
return false;
}
// HMAC 서명 계산
const payload = `${timestamp}.${body}`;
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
4단계: 구독 관리
구독 목록 조회
curl "https://api.deliveryapi.co.kr/v1/tracking/subscriptions?status=active&limit=20" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"
구독 상세 조회
# subscriptionId로 조회
curl "https://api.deliveryapi.co.kr/v1/tracking/subscriptions/sub_cb0d4e05b5ca97f777b72215" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"
# clientId로 조회 (둘 다 가능!)
curl "https://api.deliveryapi.co.kr/v1/tracking/subscriptions/order-001" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"
구독 취소
curl -X DELETE "https://api.deliveryapi.co.kr/v1/tracking/subscriptions/order-001" \
-H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"
폴링 주기 정책
구독한 송장은 배송 상태에 따라 자동으로 다른 주기로 조회됩니다:
| 상태 | 폴링 주기 | 설명 |
|---|---|---|
| 배송 준비 (PENDING, REGISTERED) | 2시간 | 상품 준비 단계 |
| 배송 중 (IN_TRANSIT, OUT_FOR_DELIVERY) | 30분 | 빠른 업데이트 필요 |
| 배송 완료 (DELIVERED) | 중지 | 구독 자동 완료 |
| 예외 (FAILED, RETURNED) | 2시간 | 상태 변경 대기 |
실패 처리 및 재시도
1. 웹훅 전송 실패 시
| 시도 횟수 | 대기 시간 |
|---|---|
| 1차 실패 | 1분 후 재시도 |
| 2차 실패 | 5분 후 재시도 |
| 3차 실패 | 30분 후 재시도 |
| 4차 실패 | 2시간 후 재시도 |
| 5차 실패 | 구독 비활성화 (status: 'failed') |
2. 택배 조회 실패 시 (크롤러 오류)
택배사 웹사이트 조회 실패 시 지수 백오프(Exponential Backoff) 방식으로 재시도합니다.
- 1차 실패: 2분 후
- 2차 실패: 4분 후
- 3차 실패: 8분 후
- 4차 실패: 16분 후
- 5차 실패: 30분 후 (최대값)
- 5회 연속 실패: status='failed'로 변경
⚠️ 중요: 웹훅 전송 실패와 택배 조회 실패는 별도로 카운트됩니다. 웹훅만 실패해도 구독은 계속 유지되며, 다음 상태 변경 시 다시 웹훅을 시도합니다.
베스트 프랙티스
- Idempotency: 같은 이벤트가 중복 전송될 수 있으므로,
subscriptionId+timestamp로 중복 체크 - 빠른 응답: 웹훅 수신 시 즉시 200 응답 후 비동기로 처리 (3초 이내 응답 권장)
- 서명 검증: 모든 웹훅에 대해 HMAC 서명 검증 필수
- Client ID 활용: 자체 주문번호를
id로 사용하면 별도 매핑 테이블 불필요 - 선택적 구독: 필요한 상태만
subscribedStatuses로 지정하여 불필요한 알림 방지
테스트 방법
- webhook.site에서 무료 테스트 URL 생성
- 생성된 URL로 웹훅 엔드포인트 등록
- 실제 송장번호로 구독 등록
- webhook.site에서 실시간으로 웹훅 수신 확인
- 웹훅 테스트 페이지에서 직접 테스트 가능
다음 단계
🎉 준비 완료! 이제 실시간 택배 알림 시스템을 구축할 수 있습니다. 궁금한 점은 문의하기로 연락주세요.