
Retry Pattern재시도 패턴
재시도 패턴(Retry Pattern)은 일시적인 오류 발생 시 자동으로 재시도하는 탄력성 패턴이다. 네트워크 순단, DB 연결 타임아웃, 일시적 서비스 과부하 등의 일시적 장애를 투명하게 처리한다.
재시도 전략
1. 즉시 재시도 (Immediate):
요청 → 실패 → 즉시 재시도
일시적 순단에 효과적, 과부하 시 악화 가능
2. 고정 지연 (Fixed Delay):
요청 → 실패 → 1초 대기 → 재시도
3. 지수 백오프 (Exponential Backoff):
1회 실패 → 1초, 2회 → 2초, 3회 → 4초, ...
지수 증가로 서버 부하 감소
4. 지터(Jitter) 추가:
지수 백오프 + 랜덤 지연
동시 재시도 집중 방지 (Thundering Herd)구현 예시
typescript
async function withRetry<T>(
fn: () => Promise<T>,
options: {
maxAttempts: number;
baseDelay: number; // ms
maxDelay: number; // ms
retryOn?: (err: Error) => boolean;
}
): Promise<T> {
const { maxAttempts, baseDelay, maxDelay, retryOn } = options;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxAttempts) throw error;
if (retryOn && !retryOn(error as Error)) throw error;
// 지수 백오프 + 지터
const exp = Math.min(baseDelay * 2 ** (attempt - 1), maxDelay);
const jitter = Math.random() * exp * 0.1;
await new Promise(r => setTimeout(r, exp + jitter));
}
}
throw new Error('Max retries exceeded');
}
// 사용
const result = await withRetry(
() => fetch('https://api.example.com/data'),
{ maxAttempts: 3, baseDelay: 500, maxDelay: 5000,
retryOn: (e) => e.message.includes('timeout') }
);Resilience4j 재시도
java
RetryConfig config = RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofMillis(500))
.retryExceptions(IOException.class, TimeoutException.class)
.ignoreExceptions(BusinessException.class)
.build();
Retry retry = Retry.of("apiCall", config);
CheckedSupplier<String> supplier =
Retry.decorateCheckedSupplier(retry, apiClient::getData);재시도하면 안 되는 경우
비멱등성(Non-Idempotent) 요청:
POST /payments → 중복 결제 위험
재시도 전 멱등성 키 사용
POST /payments
Idempotency-Key: uuid-1234 → 중복 방지
4xx 에러 (클라이언트 오류):
400 Bad Request → 재시도 무의미
401 Unauthorized → 인증 갱신 필요
429 Too Many Requests → 더 느리게 재시도