운송장 기반 배송조회 크롤링 자동화: 우리택배 연동 과정 정리
택배 배송 이력을 자동으로 확인하는 기능을 운영하던 중, 기존에 정상적으로 연동되던 우리택배(D001)의 배송 조회가 갑자기 동작하지 않는 이슈를 발견했습니다.
확인해보니 기존에 사용하던 배송조회 URL이 더 이상 유효하지 않고, 다른 페이지로 리디렉션되는 구조로 변경되어 있었기 때문에 응답 데이터가 오지 않는 상황이었습니다.
해당 문제를 해결하기 위해 다음과 같은 과정을 거쳤습니다.
- F12 개발자 도구의 네트워크 탭을 활용해 실제 POST 요청이 발생하는 새로운 URL을 추적했고, 최종적으로 데이터를 주고받는 tracking_number.php라는 경로를 확인했습니다.
- 기존 로직에서 우리택배에 대응되는 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로 실제 요청 추적
📌 방법
- 위 링크에 접속
- F12 (개발자 도구) → 네트워크(Network) 탭
- 운송장 번호 입력 후 조회 클릭
- 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를 분석하고 활용하는 실무 역량을 키울 수 있었습니다.
앞으로 다른 비공식 연동도 이와 같은 흐름으로 시도해볼 수 있을 것 같습니다.