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가 두 번 승인할 수 있다.

참고 자료 기준