자동화에 재시도(Retries)를 추가했더니 실패율이 두 배로 증가했다
요약
자동화 파이프라인에 무차별적인 재시도(retry) 기능을 적용했더니 오히려 실패율이 증가하고 데이터 중복 문제가 발생했습니다. 핵심은 모든 작업을 재시도하는 것이 아니라, 읽기 작업과 쓰기 작업을 분리하여 Idempotency Key를 사용하는 등 안전한 작업만 재시도해야 한다는 것입니다.
핵심 포인트
- 쓰기(writes) 단계는 Idempotency Key 사용 또는 재시도 금지
- 재시도가 필요한 곳을 명확히 구분하는 것이 가장 중요함
- 백오프 전략에 무작위 지터(jitter)를 추가하여 부하 분산 효과 극대화
재시도 기능을 넣은 Playwright 작업이 더 좋아지기는커녕 오히려 나빠졌습니다. 일주일 만에 실패율이 3.1%에서 6.7%로 상승했습니다. 문제의 원인은 불안정한(flaky) 코드가 아니었습니다. 재시도가 필요 없는 것을 계속 재시도했기 때문입니다.
저는 계정 자동화 파이프라인의 모든 단계에 무차별적인 재시도(retry) 래퍼를 연결한 후, 이 힘든 과정을 거쳐서야 이 문제를 발견했습니다. 무엇이 망가졌고, 무엇이 실제로 해결책이었는지 알려드리겠습니다.
1. 재시도가 '이미 완료됨'을 '두 번 완료됨'으로 만들었다
최악의 실패 유형은 네트워크와는 아무 관련이 없었습니다. 어떤 단계에서 응답 시간 초과(time out)가 발생하면, 제 래퍼가 재시도를 했고, 그 단계는 두 번째로 실행되었습니다. 왜냐하면 첫 번째 시도는 서버 측에서는 실제로 성공했기 때문입니다.
저는 이틀 만에 같은 계정에 상품을 중복으로 게시했고, 한 플랫폼에 가입 신청도 중복으로 보냈습니다. 예외(exception)도, 오류 로그도 없었습니다. 그저 조용한 중복만 발생했습니다.
# 잘못된 방식: 모든 예외에서 재시도하며, Idempotency Key가 없음
def step(action):
for _ in range(3):
...
2. 실제로 필요했던 규칙: Idempotent한 작업만 재시도하기
저는 모든 단계를 두 개의 버킷으로 나누었습니다:
- 재시도가 안전함 — 읽기(reads), GET 요청, 확인(checks). 자유롭게 재시도할 수 있습니다.
- 재시도가 위험함 — 쓰기(writes), 게시(posts), 전송(sends). Idempotency Key를 사용하거나 아예 재시도하지 않아야 합니다.
쓰기 단계에는 명시적인 키(account_id + action + date)가 부여되어, 재실행 시 중복되는 대신 거부되도록 했습니다.
3. 지터(Jitter)가 없는 백오프(Backoff)는 재시도를 동기화했다
모든 실패한 작업은 같은 지수적 스케줄(exponential schedule)로 재시도했기 때문에, 잠깐의 API 불안정함만으로도 20개의 워커들이 정확히 같은 초에 엔드포인트를 강타하게 만들었습니다. 여기에 무작위 값 0–500ms를 추가하는 지터(jitter)를 넣자 작업이 분산되었고, 2차적인 실패를 절반 이상 줄일 수 있었습니다.
time.sleep(2 ** attempt + random.uniform(0, 0.5))
4. 수정 후의 수치들
| Metric | Before | After |
|---|---|---|
| Failure rate | 6.7% | 2.9% |
| ... |
The 가장 중요했던 변화는 재시도 횟수나 백오프 곡선이 아니었습니다. 무엇을 아예 재시도할 가치가 있는지 결정하는 것이었습니다.
저는 idempotency-key 헬퍼를 공유 utils 모듈에 유지했습니다. 이제 파이프라인의 모든 쓰기 단계(write step)에서 기본값입니다. 다음으로는 가입 흐름(signup flow)에도 동일한 분할을 적용할 예정인데, 여기에는 여전히 캡차 시간 초과로 인해 전체 양식이 재전송되는 단일 병목 지점(hot spot)이 있습니다.
여러분의 자동화에서 무분별하게 재시도하는 곳은 어디인가요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기