TIL

운송장 기반 배송조회 크롤링 자동화: 우리택배 연동 과정 정리

아임실버 2025. 6. 9. 16:19

택배 배송 이력을 자동으로 확인하는 기능을 운영하던 중, 기존에 정상적으로 연동되던 우리택배(D001)의 배송 조회가 갑자기 동작하지 않는 이슈를 발견했습니다.

확인해보니 기존에 사용하던 배송조회 URL이 더 이상 유효하지 않고, 다른 페이지로 리디렉션되는 구조로 변경되어 있었기 때문에 응답 데이터가 오지 않는 상황이었습니다.

 

해당 문제를 해결하기 위해 다음과 같은 과정을 거쳤습니다.

  1. F12 개발자 도구의 네트워크 탭을 활용해 실제 POST 요청이 발생하는 새로운 URL을 추적했고, 최종적으로 데이터를 주고받는 tracking_number.php라는 경로를 확인했습니다.
  2. 기존 로직에서 우리택배에 대응되는 step URL을 이 새 경로로 수정하였고, 다시 배송 이력 데이터를 정상적으로 받아올 수 있도록 고쳤습니다.

하지만 여기서 끝내지 않고,
"이런 URL 변경이 또 발생하면 어떻게 하지?" 라는 고민이 들었습니다.
그래서 택배사별 URL 설정을 한곳에서 관리하고, 필요 시 쉽게 업데이트할 수 있는 설정 기반 관리 로직을 추가했습니다.

 

이를 통해 추후에도 택배사별 URL이 변경될 경우,
전체 로직을 수정하지 않고 단일 설정 파일만 수정하면 대응할 수 있는 구조로 개선할 수 있었습니다.

 

이 글에서는 위 과정에서 어떻게 URL을 추적하고, 파싱 로직을 개선했으며,
URL 상태를 유연하게 관리할 수 있는 구조로 어떻게 전환했는지 기록해보려고 합니다.

 

1. 배송조회 페이지 분석

우리택배의 배송조회는 다음 URL에서 이루어집니다.

http://www.honamlogis.co.kr/page/index.php?pid=tracking_number&SLIP_BARCD=5027123456

하지만 이 URL은 단순히 프론트 페이지일 뿐, 실제 데이터를 가져오는 요청은 따로 존재합니다.

2. F12로 실제 요청 추적

📌 방법

  1. 위 링크에 접속
  2. F12 (개발자 도구) → 네트워크(Network)
  3. 운송장 번호 입력 후 조회 클릭
  4. XHR 요청 필터 확인

📌 실제 데이터 요청 URL

http://www.honamlogis.co.kr/tracking_number.php

 

  • 요청 방식: POST
  • 전송 데이터: SLIP_BARCD=운송장번호

3. 응답 데이터 구조

요청 후 반환되는 JSON 예시는 다음과 같습니다.

{
  "MSG_ID": "0000",
  "ODS0_TOTAL": 1,
  "ODS0": [
    {
      "SLIP_BARCD": "5027251233",
      "TRACKING_DTL": [
        {
          "SCAN_DM": "20250528100712",
          "SCAN_USER_NM": "안박스특판",
          "SCANGB_NM": "집하상차"
        },
        ...
      ]
    }
  ]
}

 

4. 자동화 및 URL 헬스 체크 로직 구현

4.1 자동화

axios와 querystring을 활용하여 Node.js에서 택배사 배송조회 API에 POST 요청을 보내고,
응답을 파싱해 배송 시간 / 위치 / 상태 정보를 추출하는 구조로 구현했습니다.

const res = await axios.post(
  "http://www.honamlogis.co.kr/tracking_number.php",
  qs.stringify({ SLIP_BARCD: wayBillNum }),
  {
    headers: { "Content-Type": "application/x-www-form-urlencoded" }
  }
);

const details = res.data?.ODS0?.[0]?.TRACKING_DTL;

const parsed = details.map((row) => ({
  time: formatDate(row.SCAN_DM),       // "20250528100712" → "2025-05-28 10:07"
  place: row.SCAN_USER_NM,
  status: row.SCANGB_NM
}));

 

4.2 URL 헬스 체크(Health Check) + 응답 구조 검증

자동화만으로는 충분하지 않았습니다.
택배사 측에서 URL이나 응답 구조를 예고 없이 변경하는 경우, 실서비스에서는 조회 실패가 발생할 수 있고, 이는 사용자 경험에 직접적인 영향을 미칩니다.

이 문제를 예방하기 위해, 주기적으로 등록된 택배사 API의 유효성을 점검하는 헬스 체크 로직을 추가로 도입했습니다.

도입 방식

  • 1달에 1번(또는 주기적) 실행되는 스크립트를 통해
  • 각 택배사의 URL로 테스트 송장번호를 POST 요청
  • 응답 구조가 예상과 다를 경우 관리자에게 경고 또는 알림 전송
// healthCheck.js
const couriers = require("./config/couriers");
const axios = require("axios");
const testWaybill = "5027123456"; // 테스트용 송장번호

async function checkCourierHealth() {
  for (const code in couriers) {
    const { url, endpoint, name } = couriers[code];
    try {
      const res = await axios.post(
        url + endpoint,
        `SLIP_BARCD=${testWaybill}`,
        {
          headers: { "Content-Type": "application/x-www-form-urlencoded" },
        }
      );

      const valid = res.data?.ODS0?.[0]?.TRACKING_DTL;
      if (!Array.isArray(valid)) {
        console.warn(`[경고] ${name}(${code}) 응답 구조 이상 또는 변경`);
        // 슬랙, 메일, 로그 기록 등 경고 전송
      }
    } catch (e) {
      console.error(`[에러] ${name}(${code}) 요청 실패:`, e.message);
    }
  }
}
💬 이렇게 하면 “어느 날 갑자기 URL이 바뀌어서 조회가 안 되는 문제”를 자동으로 감지하고
사람이 사전에 대응할 수 있게 알림을 주는 구조를 만들 수 있습니다.

 

5. 멀티 택배 fallback 처리

한 택배사에서 데이터가 없을 경우, 다른 코드로도 조회해보는 구조를 추가했습니다.

if (!parsedData || parsedData.length === 0) {
  // global.VarArray.delivery에 정의된 택배사 목록 순회
  for (const otherCourierCode of global.VarArray.delivery) {
    ...
  }
}

이를 통해 운송장 번호만 알면 자동으로 택배사를 재탐색하고,
changeCode로 최종 조회 성공한 택배사 정보를 함께 반환할 수 있도록 했습니다.

 

최종 결과 예시

[
  {
    "time": "2025-05-28 10:07",
    "place": "안박스특판",
    "status": "집하상차"
  },
  {
    "time": "2025-05-29 14:41",
    "place": "남울산",
    "status": "배송중"
  },
  ...
]

마무리

크롤링이 필요할 것처럼 보였던 택배 배송조회도,
F12 개발자 도구로 네트워크 요청을 추적하면 API를 직접 파악하고 자동화 로직으로 연동할 수 있습니다.

이런 경험을 통해 문서가 없는 API를 분석하고 활용하는 실무 역량을 키울 수 있었습니다.
앞으로 다른 비공식 연동도 이와 같은 흐름으로 시도해볼 수 있을 것 같습니다.