Retry Timeout Idempotency
3줄 요약
- Timeout은 느린 의존성을 끝까지 기다리지 않게 하는 장치이고, retry는 일시 실패를 다시 시도하는 장치이며, idempotency는 retry가 중복 처리로 바뀌지 않게 막는 장치다.
- 세 가지를 따로 적용하면 위험하다. timeout 없는 retry는 스레드를 붙잡고, idempotency 없는 retry는 결제, 주문, 포인트 같은 쓰기 작업을 중복 실행할 수 있다.
- 설계 판단의 핵심은 “다시 시도할 수 있는 실패인가?”, “얼마나 기다릴 것인가?”, “같은 요청이 두 번 들어오면 같은 결과를 줄 수 있는가?”를 API 계약에 남기는 것이다.
핵심 정리
- Timeout은 사용자 요청, 내부 서비스 호출, DB query, 외부 API 호출, message processing 단계마다 따로 잡아야 한다.
- 바깥 timeout보다 안쪽 timeout이 길면 이미 끊긴 요청 뒤에서 작업이 계속 실행될 수 있다. 보통 client timeout > gateway timeout > app timeout > downstream timeout 순서로 짧아져야 한다.
- Retry는 네트워크 순간 오류, 503, timeout 같은 일시 실패에만 제한적으로 적용한다. validation error, 권한 오류, 잔액 부족처럼 의미가 확정된 실패는 retry 대상이 아니다.
- Backoff와 jitter는 여러 인스턴스가 동시에 재시도해 장애를 증폭하는 상황을 줄인다.
- Idempotency key는 쓰기 API에서 “같은 의도”를 식별하는 key다. 같은 key로 다시 들어온 요청은 새 작업을 만들지 않고 저장된 결과나 처리 중 상태를 반환해야 한다.
- 개인 프로젝트에서는 최소한 외부 API timeout, retry 횟수, 결제/주문 idempotency key를 명시한다.
- 기업 운영에서는 retry budget, duplicate request rate, idempotency store TTL, 외부 API별 circuit breaker, 장애 중 retry 중단 절차까지 둔다.
상세본 구성
01. Timeout 계층 설계 상세.md는 client, gateway, Spring app, DB, 외부 API timeout의 순서와 예산을 다룬다.
02. Retry Backoff Jitter 상세.md는 어떤 실패를 다시 시도하고, 어떤 실패를 즉시 중단해야 하는지 판단한다.
03. Idempotency Key와 중복 요청 방어 상세.md는 쓰기 요청의 중복 실행을 막는 API 계약과 저장소 설계를 다룬다.
04. 외부 API 호출 안정성 상세.md는 결제, 배송, 알림 같은 외부 의존성을 내부 트랜잭션과 분리하는 기준을 정리한다.
05. 장애 증폭을 막는 호출 설계 상세.md는 retry, fanout, queue replay가 장애 중 부하를 키우는 구조를 막는 방법을 다룬다.
헷갈리는 지점
- Timeout을 길게 잡으면 안정적이라고 생각하기 쉽다. 느린 요청도 언젠가 성공할 수 있어 보이기 때문이다.
- 핵심은 긴 timeout이 스레드, 커넥션, 사용자 대기 시간을 함께 붙잡는다는 점이다.
- 안정성은 오래 기다리는 것이 아니라 정해진 시간 안에 실패를 제한하는 것이다.
- Retry를 넣으면 실패가 줄어든다고 생각하기 쉽다. 일시 오류가 성공으로 바뀌는 경험이 있기 때문이다.
- 핵심은 retry가 downstream에 추가 트래픽을 만든다는 점이다.
- retry는 idempotency, backoff, jitter, retry budget과 함께 있어야 한다.
- Idempotency key를 단순 request id로 오해하기 쉽다. 둘 다 요청을 식별하는 문자열이기 때문이다.
- 핵심은 request id는 추적용이고 idempotency key는 같은 비즈니스 의도를 중복 실행하지 않기 위한 계약이라는 점이다.
- 같은 결제 시도는 같은 idempotency key를 가져야 하고, 새 결제 시도는 새 key를 가져야 한다.
확인 질문
- 확인 질문: timeout, retry, idempotency를 함께 봐야 하는 이유는 무엇인가?
- 답변: timeout은 대기 시간을 제한하고 retry는 다시 시도하며 idempotency는 그 재시도가 중복 처리로 바뀌지 않게 막기 때문이다.
- 확인 질문: retry하면 안 되는 실패는 무엇인가?
- 답변: validation error, 인증/인가 실패, 잔액 부족, 존재하지 않는 리소스처럼 같은 요청을 반복해도 성공 가능성이 없는 의미적 실패다.
- 확인 질문: 결제 API에서 idempotency key가 없으면 어떤 문제가 생기는가?
- 답변: 네트워크 timeout 뒤 클라이언트가 같은 결제를 다시 보내면 서버나 외부 PG가 두 번 승인할 수 있다.
참고 자료 기준