색인 생성 경로 오류 복구, API 호출 실패 방어
목차
이번엔 빌드·크롤링 시스템에서 쌓인 두 가지 안정성 문제를 한 번에 처리했다. 웹사이트 색인 생성 빌드의 경로가 잘못 지정된 부분과, 소셜 브로드캐스트 의존성으로 인한 연쇄 장애를 방어하는 것이었다.
웹사이트 색인 생성 시스템의 경로 정정
빌드 자동화 파이프라인을 운영하다 보면, 한 두 문자의 경로 오류가 얼마나 큰 배포 장애로 번진다는 걸 자주 경험한다. 이번엔 werebridge 라는 사이트맵·색인 생성 시스템에서 그런 문제가 있었다. 주로 build-sitemap.js, indexnow-ping.js, publish.sh 같은 빌드 스크립트들이 상대 경로나 절대 경로를 잘못 참조하고 있어서, 실행 디렉토리에 따라 파일을 못 찾거나 잘못된 위치에 아티팩트를 출력하던 상황이었다.
이런 경로 오류는 겉으로는 조용한데, 실제로는:
- CI/CD 파이프라인에서 "build success" 로그가 떠도 실제로는 색인이 생성되지 않는 경우
- 로컬 테스트에선 잘 되는데 서버 배포에선 실패 (상대 경로의 전형적인 함정)
- 몇 번의 성공 후 갑자기 실패하거나 부분 실패 (환경 변수나 실행 위치 변경으로 유발)
같은 시스템을 여러 팀이 의존하고 있으면, 이런 문제가 "어디선 잘못됐지?"를 서로 미루면서 확산된다.
Social 브로드캐스트의 호출 실패 방어
동시에 더 깊은 문제가 있었다. insurance/generate.py, money/generate.py, ssul/publish_crawl.py 같은 여러 크롤링·발행 시스템들이 social-broadcast 라는 외부 서비스를 직접 호출하고 있는데, 그 서비스가 무응답이거나 느려지면 전체 발행 파이프라인이 막혔다. "죽은 호출 가드"라고 표현한 것이 바로 이 부분인데, 외부 API 의존성으로 인한 장애 전파를 막기 위해 방어 로직을 추가한 것이다.
| 파일 | 역할 | 이번 변경의 의미 |
|---|---|---|
insurance/generate.py |
보험 도메인 크롤링·발행 | social-broadcast 호출 실패 시 재시도/타임아웃 추가 |
money/generate.py |
금융 도메인 크롤링·발행 | 동일한 방어 로직 적용 |
ssul/publish_crawl.py |
자체 서비스 발행 | 외부 의존성 격리 처리 |
werebridge-build/build-sitemap.js |
사이트맵 생성 | 경로 정정 (상대 → 절대 경로) |
werebridge-build/indexnow-ping.js |
검색엔진 색인 업데이트 | 경로 일관성 수정 |
werebridge-build/publish.sh |
빌드 배포 스크립트 | 작업 디렉토리 정규화 |
왜 이 우선순위였나
이 두 가지 문제를 한 커밋으로 묶은 이유는 단순했다. 색인 생성 시스템이 제대로 작동하지 않으면 SEO가 바뀌지 않는 것은 당연하고, social-broadcast 의존성이 없으면 그나마 발행은 빨리 완료된다. 하지만 둘 다 "조용히 실패"하는 문제여서, 실제로 배포 후 한두 시간 뒤에야 "어? 색인이 안 갱신됐네?"라는 신고가 들어오는 유형이었다.
팀 차원에서는 이런 문제들을 볼 때마다 "왜 지금까지 못 봤나?"라는 반성이 있다. 로그를 더 주의 깊게 봤으면, 모니터링 알림을 더 세밀하게 설정했으면 하는 마음이다. 특히 외부 API 호출처럼 팀 외부의 요소에 의존하는 부분은, 그것이 실패했을 때의 영향도 문서화하고 fallback 패턴을 명시적으로 해둬야 한다.
방어 코드 패턴
social-broadcast 호출 같은 경우, 흔한 패턴이 이렇다:
try:
broadcast_result = call_broadcast_service(payload)
log_success(broadcast_result)
except (TimeoutError, ConnectionError) as e:
log_warning(f"Broadcast failed, continuing anyway: {e}")
# 발행은 진행, 브로드캐스트는 스킵
except Exception as e:
log_error(f"Unexpected error: {e}")
# 외부 에러인지 자체 에러인지 판별
단순해 보이지만, 이 패턴이 없으면 한 팀의 서비스 장애가 다섯 팀의 발행을 모두 멈춘다. 그래서 "죽은 호출을 가드한다"는 것은, 진짜로는 "우리 시스템의 자율성을 지킨다"는 뜻이다.
회고
이번 작업에서 배운 점은, 대충 "작동한다"고 생각하는 시스템일수록 경로 문제나 외부 의존성 문제가 숨어있다는 것이다. 특히 여러 파일에서 반복되는 패턴(지금의 경우 경로 오류와 API 호출)은 "코드 리뷰 시점에 봤어야 했다"는 아쉬움이 남는다. 앞으로는 크롤링/발행 시스템 추가할 때 체크리스트를 먼저 정하는 쪽으로 가야 할 듯하다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.