API 429 throttle을 정책 준수와 백오프로 자동 복구
목차
Wikimedia API와 상호작용하는 그룹 발견/시드 봇이 갑자기 자주 실패하기 시작했다. 원인은 API 요청 제한(throttle)에서 나온 429 응답을 제대로 처리하지 못한 것. Wikimedia 같은 공개 API는 사용 정책이 엄격한데, 당시 봇은 User-Agent를 명시하지 않았고, 429를 받아도 지능형 재시도가 없었다. 이번 작업으로 정책 준수와 백오프 전략을 한데 묶어서 안정성을 크게 높일 수 있었다.
문제의 구조
Wikimedia는 웹스크래퍼와 봇의 무분별한 요청을 막기 위해 몇 가지 정책을 강제한다:
- User-Agent 명시 — 모든 API 클라이언트는 자신을 명확히 밝혀야 한다. 이메일이나 프로젝트명을 포함하는 게 관례.
- Rate Limiting 존중 — 초당 요청 수 제한. 초과 시 HTTP 429(Too Many Requests) 응답.
- Retry-After 헤더 — 429 응답에 포함된 "몇 초 후에 재시도하라"는 지시사항을 반드시 따라야 함.
당시 봇은 이 중 어느 것도 제대로 구현하지 않았다. 결과적으로 Wikimedia는 봇을 의심 클라이언트로 취급했고, 더 공격적으로 제한했다. 악순환의 전형이다.
해결책: 정책 준수 + 지능형 재시도
discover_groups.py와 seed_groups.py 두 파일에서 API 호출 부분을 수정했다. 변경은 세 가지 층위로 구성된다.
1. User-Agent 추가
headers = {
'User-Agent': 'MyBot/1.0 (+http://example.com/about; [email protected])'
}
response = requests.get(url, headers=headers)
이 헤더 하나가 "우리는 신뢰할 수 있는 자동화 클라이언트"라고 알리는 신호다. Wikimedia는 정책을 지키는 봇을 더 관대하게 본다.
2. 429 응답 감지 및 Retry-After 파싱
if response.status_code == 429:
retry_after = response.headers.get('Retry-After')
if retry_after:
wait_seconds = int(retry_after)
time.sleep(wait_seconds)
# 재시도 로직
Retry-After 헤더는 초 단위 정수로 대기 시간을 지시한다. 이를 존중하면 API 서버의 의도를 따르는 것이고, 그게 충돌을 최소화하는 길이다.
3. 지수 백오프 (exponential backoff)
Retry-After가 없는 경우를 대비해 지수 백오프를 적용했다. 첫 재시도는 2초, 그 다음 4초, 8초… 이렇게 대기 시간을 늘린다. 무한 재시도나 즉시 재시도는 서버 부하를 악화시키지만, 백오프는 재시도 간격을 현명하게 늘려서 서버가 숨을 쉴 수 있게 해준다.
영향 분석
| 항목 | 변경 전 | 변경 후 |
|---|---|---|
| User-Agent | 없음 → 신뢰도 낮음 | 정책 준수 → 신뢰도 높음 |
| 429 처리 | 실패 또는 고정 대기 | Retry-After 헤더 존중 |
| 재시도 전략 | 없음 또는 무한 루프 | 지수 백오프 (최대 5회) |
| 봇 안정성 | 빈번한 중단 | 자동 복구 및 안정적 동작 |
팀 관점에서 이 변경은 의존도 높은 자동화 작업의 신뢰성을 크게 개선했다. 그룹 발견/시드 프로세스가 중단되지 않으면, 다운스트림 작업들(분석, 동기화, 리포팅)도 원활하게 돈다.
회고: 공개 API와의 상호작용 원칙
이 건으로 팀 내에서 정리한 몇 가지 원칙들:
정책 먼저 읽기
공개 API를 사용할 때는 README나 Terms of Service의 rate limit, User-Agent 정책을 맨 먼저 확인한다. 대부분 명시되어 있다. 귀찮은 작업이지만, 시간이 지나면서 그 정책을 무시한 코드가 얼마나 많은 장애를 일으키는지 보게 된다.
429는 예외가 아니라 정상 응답
429를 에러처럼 처리하기보다는 "서버가 '잠깐 기다려'라고 신호를 보냈다"는 의도된 흐름으로 봐야 한다. except 블록이 아니라 if 조건 분기로.
Retry-After는 항상 존중하라
고정 시간 재시도보다 서버 지시사항을 따르는 게 정석. 서버는 자신의 부하 상황에 따라 동적으로 대기 시간을 보낸다. 이를 무시하고 우리 맘대로 재시도하면 더 욕먹는다.
백오프는 필수, 재시도는 조건부
무한 재시도나 즉시 재시도는 상황을 악화시킨다. 지수 백오프는 공개 API 호출의 표준 패턴이고, 최대 재시도 횟수도 정해야 한다.
배운 점: 봇/자동화가 안정적이려면 외부 의존성(특히 API)의 정책을 정확히 이해하고 구현해야 한다는 것. 한두 줄의 헤더 추가와 조건 분기가 얼마나 큰 차이를 만드는지 경험했다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.