재시도는 언제 도움이 되고, 언제 장애를 키울까
분산 시스템에서 실패는 피할 수 없다. 그래서 많은 시스템은 실패에 대비해 Retry를 사용한다. 그러나 Retry는 잘못 사용하면 장애를 완화하는 것이 아니라 오히려 증폭시킨다. 이 문제를 해결하기 위해 함께 사용되는 패턴이 서킷 브레이커(Circuit Breaker) 다. 이 글에서는 서킷 브레이커와 Retry를 어떻게 조합해야 하는지, 설계 관점에서 정리한다.
Retry는 왜 필요한가
Retry는 일시적인 실패를 복구하기 위한 가장 단순한 전략이다.
다음과 같은 상황에서는 Retry가 효과적이다.
- 네트워크 순간 장애
- 일시적인 타임아웃
- 짧은 부하 스파이크
이 경우 한두 번의 재시도로 정상 응답을 받을 수 있다.
Retry가 위험해지는 순간
Retry는 모든 실패에 대해 유효하지 않다.
다음 상황에서 Retry는 문제를 키운다.
- 외부 시스템이 이미 장애 상태
- DB 커넥션 풀 고갈
- 응답 지연이 누적되는 상황
이때 Retry는 실패 요청을 기하급수적으로 증가시켜 장애를 전파한다.
서킷 브레이커가 필요한 이유
서킷 브레이커는 실패가 반복될 때 호출 자체를 차단한다.
이 패턴의 목적은 다음과 같다.
- 더 이상의 재시도 중단
- 빠른 실패 처리
- 리소스 보호
즉, Retry의 남용을 제어하는 역할을 한다.
Retry와 서킷 브레이커의 역할 분리
두 패턴은 해결하려는 문제가 다르다.
- Retry
- 일시적인 실패 복구
- 서킷 브레이커
- 반복 실패 차단
이 역할을 혼동하면 설계가 무너진다.
잘못된 조합: 무제한 Retry
가장 흔한 실수는 Retry만 사용하는 구조다.
이 구조의 문제는 다음과 같다.
- 장애 시스템에 요청 폭주
- 스레드, 커넥션 고갈
- 장애 범위 확대
Retry에는 반드시 중단 조건이 필요하다.
올바른 기본 조합 구조
가장 기본적인 조합은 다음과 같다.
- 요청 수행
- 실패 시 제한된 Retry 시도
- 실패율 증가 감지
- 서킷 브레이커 Open
- 이후 요청은 즉시 실패
이 흐름을 통해 장애 전파를 차단할 수 있다.
Retry는 언제까지 허용해야 하는가
Retry는 반드시 제한되어야 한다.
일반적인 기준은 다음과 같다.
- Retry 횟수 제한
- Retry 간격 증가(Backoff)
- 전체 타임아웃 제한
무한 Retry는 설계 오류다.
Backoff가 중요한 이유
Backoff는 Retry 간 대기 시간을 점진적으로 늘리는 전략이다.
이를 적용하면 다음 효과가 있다.
- 요청 폭주 완화
- 외부 시스템 회복 시간 확보
- 리소스 사용량 감소
즉각적인 연속 Retry는 가장 피해야 할 패턴이다.
서킷 브레이커 상태 전환과 Retry
서킷 브레이커의 상태는 Retry와 밀접하다.
- Closed
- Retry 허용
- Open
- Retry 차단
- 즉시 실패
- Half-Open
- 제한된 Retry 허용
- 복구 여부 판단
이 구조를 통해 정상 복구 시점을 판단한다.
Retry를 허용하면 안 되는 실패 유형
모든 실패가 Retry 대상은 아니다.
Retry를 피해야 할 대표적인 경우는 다음과 같다.
- 인증 실패
- 잘못된 요청 파라미터
- 비즈니스 로직 오류
Retry는 기술적 실패에만 적용해야 한다.
서킷 브레이커 + Retry가 Scale Out과 만나는 지점
Scale Out 환경에서는 실패 요청 수 자체가 빠르게 증가한다.
- Pod 수 증가
- Retry 요청 증가
- 외부 시스템 과부하
서킷 브레이커가 없으면 Scale Out이 장애 증폭기로 작동할 수 있다.
실무에서 자주 발생하는 설계 실수
다음과 같은 조합은 위험하다.
- Retry 먼저, 서킷 브레이커 없음
- Retry 횟수 과도
- Backoff 미적용
- 모든 API에 동일한 설정 적용
조합 설계는 호출 대상의 특성에 따라 달라야 한다.
기본 설계 가이드라인
실무에서 자주 사용하는 기준은 다음과 같다.
- Retry는 짧고 제한적으로
- Backoff 필수 적용
- 서킷 브레이커로 반복 실패 차단
- 빠른 실패 응답 설계
이 기준만 지켜도 장애 전파 위험은 크게 줄어든다.
정리
Retry는 일시적인 실패를 복구하는 도구지만, 무분별하게 사용하면 장애를 증폭시킨다. 서킷 브레이커는 반복 실패를 감지하고 호출을 차단해 시스템을 보호한다. 두 패턴은 함께 사용될 때 의미가 있으며, Retry는 제한적으로, 서킷 브레이커는 명확한 기준으로 설계해야 한다. 분산 시스템에서 안정성을 확보하려면 이 조합에 대한 이해는 필수다.