재시도만 걸면 장애가 해결된다고 믿는 개발자에게
by 그릿 | GROWTH_ESSAY | 2026-11-10
#백엔드 #장애대응 #아키텍처외부 API를 호출하다가 타임아웃이 나면 가장 먼저 무엇을 하십니까.
코드에 재시도 어노테이션을 붙이거나 반복문으로 세 번 다시 쏘게 만듭니다. "네트워크는 언제든 불안정할 수 있으니 재시도 로직을 넣었습니다." 멘토링에서 이력서나 코드를 볼 때 열 명 중 여덟 명이 이렇게 답합니다.
하지만 재시도는 장애를 해결하는 만병통치약이 아닙니다. 사유 없는 재시도는 오히려 시스템 전체를 무너뜨리는 뇌관이 됩니다.
상대 서버는 이미 한계에 도달했습니다
원격 서버가 제시간에 응답하지 못하는 이유는 둘 중 하나입니다. 네트워크 회선이 일시적으로 튄 것이거나, 트래픽이 몰려 서버가 지친 상태입니다.
후자의 상황에서 동일한 요청을 즉시 세 번 연속 날리면 어떻게 되겠습니까. 죽어가던 상대 서버에 확인 사살을 가하는 꼴입니다. 이를 재시도 폭풍(Retry Storm)이라고 부릅니다.
타임아웃이 났다는 사실이 상대 서버가 작업을 처리하지 못했다는 뜻은 아닙니다. 처리는 이미 끝났는데 응답 패킷만 지연되었을 수 있습니다. 그 상태에서 같은 요청을 다시 보내면 결제가 두 번 승인되고 주문이 중복 생성됩니다.
멱등성 없는 재시도는 사고입니다
멘토링에서 만난 3년 차 백엔드 개발자 K씨는 결제 연동 장애 회고를 들고 왔습니다. 결제 모듈에 재시도를 걸어두었는데, 특정 시간대에 고객 계좌에서 이중 출금이 발생한 사건이었습니다.
원인은 명확했습니다. 네트워크 타임아웃이 났을 때 재시도를 시도했지만, 요청에 고유한 멱등 키(Idempotency Key)가 없었습니다. 결제 대행사는 이전 요청을 정상 처리했는데, 서버는 타임아웃을 실패로 단정하고 새 요청을 다시 밀어 넣은 것입니다.
재시도를 코드에 적기 전에 반드시 물어야 합니다. "이 요청은 열 번을 다시 실행해도 시스템 데이터가 처음 한 번 실행했을 때와 완전히 같은가?" 이 질문에 즉시 답할 수 없다면 그 코드에 재시도를 걸어서는 안 됩니다.
재시도보다 앞서는 것은 안전한 실패입니다
실무에서 분산 시스템의 네트워크 장애를 다루는 기준은 명확합니다.
첫째, 무작정 다시 쏘지 말고 지수 백오프(Exponential Backoff)와 무작위 지터(Jitter)를 적용해야 합니다. 동시에 실패한 요청들이 일제히 같은 주기로 다시 쏟아지는 참사를 막아야 합니다.
둘째, 상태를 바꾸는 요청이라면 반드시 고유한 멱등 키를 설계해 중복 실행을 막아야 합니다.
셋째, 상대 서버가 정상화될 기미가 없다면 서킷 브레이커(Circuit Breaker)로 즉시 요청을 차단하고 안전하게 실패를 반환해야 합니다. 무조건 성공시키겠다는 집착을 버려야 시스템이 삽니다. 때로는 빠르게 포기하고 명확한 실패를 알리는 설계가 서비스 전체를 지킵니다.
어노테이션 하나 추가한다고 네트워크의 불확실성이 사라지지 않습니다. 도구 뒤에 숨겨진 시스템의 동작 원리를 집요하게 파고들어야 합니다.
지금 내가 걷고 있는 기술의 방향이 본질을 향하고 있는지 확인하십시오.
https://teamgrit.co/direction