LabHub
배우기 러닝패스 코스

Idempotency — Two Clicks, One Charge

Design principles: Idempotent requests still need retry budgets

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

재시도는 ‘한 번 더’가 아니라 안전한 요청을 남은 시간과 횟수 안에서 다시 보내는 정책이다.

Flow map: 한 줄 요약 · 왜 이게 필요했나 · 어떻게 동작하나 · 현장에서 만나는 모습

왜 이게 필요했나

느린 서비스에 클라이언트가 한꺼번에 재시도하면 이미 밀린 큐에 요청이 더 쌓인다. 매 요청의 timeout을 5초로 두고 3회 시도하면 전체 작업은 5초 안에 끝나지 않는다. 처음에 마감 시각을 계산하고 각 호출과 대기 전에 남은 시간을 다시 구해야 한다. 멱등 키가 있어도 비용·부하·사용자 대기 시간까지 사라지지는 않는다.

어떻게 동작하나

send(남은 시간) → 응답 → 재시도할 상태인가? → 재생해도 안전한가?
                                                ↓
종료 ← 횟수 또는 전체 예산 소진 ← 지터 + Retry-After 대기 계산
                                                ↓
                                            sleep → 다음 호출

이 실습의 정책은 429·502·503·504만 재시도한다. GET·HEAD·PUT·DELETE는 이 API의 멱등 계약을 전제로 허용하고 POST는 공백이 아닌 키가 있을 때만 허용한다. 서버가 그 키를 실제로 원자적으로 처리하지 않는다면 클라이언트에 문자열을 붙이는 것만으로는 안전하지 않다. 이전 멱등성 실습이 바로 그 서버 쪽 전제를 다룬다.

현장에서 만나는 모습

지수 백오프에 지터를 주면 모든 클라이언트가 같은 시각에 깨는 현상을 줄인다. 서버의 Retry-After가 로컬 대기보다 길면 더 긴 값을 따른다. 전체 예산보다 긴 서버 대기를 임의로 줄여 일찍 재시도하지 않고 현재 응답을 반환한다. 여기서는 정수 초 형식만 지원하며 HTTP 날짜 형식은 지원하지 않는다는 제한을 명시한다.

다음 실습에서 할 것

가짜 단조 시계·sleep·send로 실제 대기 없이 8단계를 검증한다. send는 받은 남은 시간 이내에 응답하는 어댑터라는 전제다. 동기 함수가 영원히 블록되면 실행기가 강제로 중단할 수 없으므로 실제 HTTP 어댑터에는 별도 timeout 설정이 필요하다. 예산과 최대 횟수는 최초 시도를 포함한다. 모든 상태를 재시도하거나 412 충돌을 네트워크 장애로 취급하지 않는다.

참고: HTTP 멱등 메서드