🔔 웹훅 구독 API 가이드 - 택배 상태 변경 자동 알림

📅 2026-01-13 ⏱️ 10분 읽기 🏷️ API 가이드, 웹훅, 실시간 알림

💡 이 가이드에서 배울 내용: 택배 상태가 변경될 때마다 자동으로 웹훅을 받는 방법, 웹훅 URL 등록부터 보안 검증까지 전체 플로우를 단계별로 설명합니다.

개요

웹훅 구독 API를 사용하면 택배사 송장번호를 등록하고, 배송 상태가 변경될 때마다 자동으로 알림을 받을 수 있습니다. 폴링(Polling) 방식 대신 이벤트 기반으로 알림을 받으므로 서버 리소스를 절약하고 실시간으로 배송 정보를 업데이트할 수 있습니다.

주요 특징

폴링 정책

폴링 주기

모든 활성 상태에 대해 1시간 주기로 폴링합니다.

배송 상태 폴링 주기 설명
PENDING, REGISTERED, PICKUP_READY, PICKED_UP, IN_TRANSIT, OUT_FOR_DELIVERY 1시간 활성 상태 — 주기적 폴링
DELIVERED, CANCELLED 중지 구독 자동 완료
FAILED, RETURNED, HOLD 1시간 예외 상태 — 상태 변경 감시

야간 중단 (KST 기준)

14일 자동 중단

구독 등록 후 14일이 경과하면 자동으로 폴링이 중단됩니다. 장기간 배송되지 않는 건에 대한 불필요한 조회를 방지하기 위한 정책입니다.

💡 예시
등록일: 2026-01-01
중단일: 2026-01-15 (14일 후)
14일째부터는 폴링이 더 이상 수행되지 않습니다.

1단계: 웹훅 URL 사전 등록

구독을 등록하기 전에, 알림을 받을 웹훅 URL을 먼저 등록해야 합니다. API Key당 최대 10개까지 등록 가능합니다.

POST /v1/webhooks/endpoints

요청 예시

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건까지 일괄 등록 가능합니다.

POST /v1/webhooks/register

요청 예시

curl -X POST "https://api.deliveryapi.co.kr/v1/webhooks/register" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer __API_KEY__:__SECRET_KEY__" \
  -d '{
    "endpointId": "ep_6b78d0e9eac154e129847aae",
    "items": [
      {
        "courierCode": "cj",
        "trackingNumber": "123456789012",
        "clientId": "order-001"
      }
    ],
    "recurring": true,
    "metadata": { "orderId": "ORD-001" }
  }'

요청 필드 설명

필드 필수 설명
endpointId 선택 사전 등록한 웹훅 URL의 ID. 미제공 시 웹훅 없이 크롤 후 GET으로 조회
items[].courierCode 필수 택배사 코드 (예: cj, hanjin, lotte)
items[].trackingNumber 필수 송장번호
items[].clientId 선택 클라이언트 매핑용 ID (예: 주문번호). 웹훅 발송 시 함께 전달됨
recurring 필수 true: 14일 구독형 (상태 변경마다 웹훅), false: 즉시 1회 크롤
metadata 선택 추가 정보 (JSON 객체). 웹훅 발송 시 함께 전달됨

응답 예시

{
  "isSuccess": true,
  "data": {
    "requestId": "req_cb0d4e05b5ca97f777b72215",
    "itemCount": 1,
    "recurring": true
  },
  "message": "추적 요청이 등록되었습니다. 결과는 웹훅으로 수신하거나 requestId로 조회할 수 있습니다."
}

✅ requestId: 응답의 requestId를 저장하세요. 이후 구독 상세 조회(GET /v1/webhooks/subscriptions/{requestId})나 취소(DELETE) 시 사용합니다.

3단계: 웹훅 수신 및 검증

배송 상태가 변경되면 등록한 URL로 웹훅이 전송됩니다.

웹훅 페이로드

{
  "event": "tracking.polled",
  "requestId": "req_cb0d4e05b5ca97f777b72215",
  "timestamp": "2026-01-13T10:30:00.000Z",
  "data": {
    "courierCode": "cj",
    "trackingNumber": "123456789012",
    "clientId": "order-001",
    "previousStatus": "IN_TRANSIT",
    "currentStatus": "DELIVERED",
    "hasChanged": true,
    "isDelivered": true,
    "trackingData": {
      "courierCode": "cj",
      "courierName": "CJ대한통운",
      "trackingNumber": "123456789012",
      "deliveryStatus": "DELIVERED",
      "isDelivered": true,
      "progresses": [...]
    }
  },
  "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단계: 구독 관리

구독 목록 조회

GET /v1/webhooks/subscriptions
curl "https://api.deliveryapi.co.kr/v1/webhooks/subscriptions?status=active&limit=20" \
  -H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"

구독 상세 조회

GET /v1/webhooks/subscriptions/{id}
# requestId로 조회
curl "https://api.deliveryapi.co.kr/v1/webhooks/subscriptions/req_cb0d4e05b5ca97f777b72215" \
  -H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"

구독 취소

DELETE /v1/webhooks/subscriptions/{id}
curl -X DELETE "https://api.deliveryapi.co.kr/v1/webhooks/subscriptions/req_cb0d4e05b5ca97f777b72215" \
  -H "Authorization: Bearer __API_KEY__:__SECRET_KEY__"

폴링 주기 정책

구독한 송장은 1시간 주기로 자동 조회됩니다. 야간(22:00~07:00 KST)에는 폴링이 일시 중단됩니다.

상태 폴링 주기 설명
활성 (PENDING, REGISTERED, IN_TRANSIT 등) 1시간 주기적으로 상태 확인
배송 완료 (DELIVERED, CANCELLED) 중지 구독 자동 완료
예외 (FAILED, RETURNED, HOLD) 1시간 상태 변경 감시

실패 처리 및 재시도

1. 웹훅 전송 실패 시

시도 횟수 대기 시간
1차 실패1분 후 재시도
2차 실패5분 후 재시도
3차 실패30분 후 재시도
4차 실패2시간 후 재시도
5차 실패구독 비활성화 (status: 'failed')

2. 택배 조회 실패 시 (크롤러 오류)

택배사 웹사이트 조회 실패 시 지수 백오프(Exponential Backoff) 방식으로 재시도합니다.

⚠️ 중요: 웹훅 전송 실패와 택배 조회 실패는 별도로 카운트됩니다. 웹훅만 실패해도 구독은 계속 유지되며, 다음 상태 변경 시 다시 웹훅을 시도합니다.

베스트 프랙티스

테스트 방법

  1. webhook.site에서 무료 테스트 URL 생성
  2. 생성된 URL로 웹훅 엔드포인트 등록
  3. 실제 송장번호로 구독 등록
  4. webhook.site에서 실시간으로 웹훅 수신 확인
  5. 웹훅 테스트 페이지에서 직접 테스트 가능

다음 단계

🎉 준비 완료! 이제 실시간 택배 알림 시스템을 구축할 수 있습니다. 궁금한 점은 문의하기로 연락주세요.