---
sidebar_label: "재시도와 장애 허용"
title: "재시도와 장애 허용 - CyberGo HTTPC | 백오프와 재시도"
description: "HTTPC 재시도와 장애 허용 가이드: 기본 지수 백오프 재시도 전략과 RetryConfig 설정, 408/429/5xx 자동 재시도, 커스텀 RetryPolicy, Retry-After 파싱과 요청별 재시도 제어를 다룹니다."
sidebar_position: 5
---

# 재시도와 장애 허용

## 기본 재시도

```go
cfg := httpc.DefaultConfig()
cfg.Retry.MaxRetries = 3           // 최대 3 회
cfg.Retry.Delay = 1 * time.Second  // 초기 지연 1s
cfg.Retry.BackoffFactor = 2.0      // 지수 백오프 2x
cfg.Retry.EnableJitter = true      // 지터 활성화

client, err := httpc.New(cfg)
if err != nil {
    log.Fatal(err)
}
defer client.Close()
```

기본 재시도 지연 시퀀스: `1s → 2s → 4s` (랜덤 지터 포함)

### 재시도 조건

기본적으로 다음 오류가 재시도를 트리거합니다:

| 조건 | 재시도 |
|------|--------|
| 네트워크 오류 (연결 거부, 임시/타임아웃 DNS 실패) | 예 |
| 타임아웃 오류 | 예 |
| 5xx 서버 오류 (500/502/503/504) | 예 |
| 408 Request Timeout / 429 Too Many Requests | 예 |
| 기타 4xx 클라이언트 오류 | 아니요 |
| 컨텍스트 취소 | 아니요 |
| 설정 검증 오류 | 아니요 |

## 커스텀 재시도 전략

`RetryPolicy` 인터페이스를 구현하여 재시도 동작을 완전히 제어합니다:

:::warning 내부 타입
RetryPolicy.ShouldRetry 의 `resp` 매개변수 타입 ResponseReader 는 내부 인터페이스 (`internal/types` 패키지에 정의) 이므로 외부 패키지에서 직접 참조할 수 없습니다. 커스텀 `RetryPolicy`는 `httpc`와 같은 모듈 내 패키지에서 구현해야 합니다. 대부분의 시나리오는 `RetryConfig` 필드 설정으로 충분합니다.
:::

```go
// 주의: ResponseReader 는 내부 타입 (internal/types 패키지) 입니다.
// 이 코드는 github.com/cybergodev/httpc 모듈 내부에서만 컴파일됩니다.
// 대부분의 사용자는 RetryConfig 와 WithMaxRetries 로 재시도를 설정해야 합니다.

type MyRetryPolicy struct {
    maxAttempts int
}

// 재시도 여부 판단
func (p *MyRetryPolicy) ShouldRetry(resp ResponseReader, err error, attempt int) bool {
    if attempt >= p.maxAttempts {
        return false
    }
    // 네트워크 오류는 재시도
    if err != nil {
        return true
    }
    // 502, 503, 504 만 재시도
    return resp.StatusCode() == 502 || resp.StatusCode() == 503 || resp.StatusCode() == 504
}

// 재시도 지연 반환
func (p *MyRetryPolicy) GetDelay(attempt int) time.Duration {
    return time.Second * time.Duration(attempt+1)
}

// 최대 재시도 횟수
func (p *MyRetryPolicy) MaxRetries() int {
    return p.maxAttempts
}

// 커스텀 전략 적용
cfg := httpc.DefaultConfig()
cfg.Retry.CustomPolicy = &MyRetryPolicy{maxAttempts: 5}
```

## 요청별 제어

```go
// 개별 요청 5 회 재시도
result, err := client.Get(url, httpc.WithMaxRetries(5))

// 재시도 비활성화
result, err := client.Get(url, httpc.WithMaxRetries(0))

// 컨텍스트 타임아웃과 함께 사용
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
result, err := client.Request(ctx, "GET", url, httpc.WithMaxRetries(3))
```

## Retry-After 지원

HTTPC 은 서버가 반환한 `Retry-After` 응답 헤더를 자동으로 파싱합니다:

```go
// 서버 반환: Retry-After: 120
// HTTPC 은 최대 60 초까지만 대기 후 재시도 (서버가 지정한 120s 는 안전 상한 60s 로 잘림)

// 서버 반환: Retry-After: Fri, 25 Apr 2026 12:00:00 GMT
// HTTPC 은 지정된 시간까지 대기 후 재시도 (60s 이상 남은 경우 60s 로 잘림)
```

:::tip
`Retry-After`는 재시도 가능한 모든 응답 (408, 429, 500, 502, 503, 504) 에서 적용되며, 지수 백오프 지연보다 우선순위가 높습니다.
:::

## 백오프 전략

### 지수 백오프

```go
cfg.Retry.BackoffFactor = 2.0
// 지연 시퀀스: delay, delay*2, delay*4, delay*8...
```

### 고정 지연

```go
cfg.Retry.BackoffFactor = 1.0
// 지연 시퀀스: delay, delay, delay...
```

### 선형 증가

```go
// 커스텀 RetryPolicy 구현 필요:
// delay * (attempt + 1)
// 고급 예제의 커스텀 재시도 전략 참조
```

### 랜덤 지터

지터를 활성화하여 "썬더링 허드 (Thundering Herd)" 현상을 방지합니다:

```go
cfg.Retry.EnableJitter = true
// 기본 지연에 랜덤 오프셋 추가, 모든 클라이언트가 동시에 재시도하는 것을 방지
```

## 오류 처리와 재시도

```go
result, err := client.Get(url)
if err != nil {
    var clientErr *httpc.ClientError
    if errors.As(err, &clientErr) {
        if clientErr.Type == httpc.ErrorTypeRetryExhausted {
            log.Printf("%d회 재시도 후에도 실패", clientErr.Attempts)
        }
    }
    return err
}
```

## 모범 사례

| 시나리오 | 권장 사항 |
|----------|-----------|
| API 호출 | MaxRetries=3, Delay=1s, Backoff=2.0 |
| 마이크로서비스 통신 | MaxRetries=2, Delay=500ms |
| 파일 다운로드 | MaxRetries=5, Delay=2s, Backoff=2.0 |
| 멱등성 작업 | 안심하고 재시도 가능 |
| 비멱등성 작업 (POST) | 네트워크 오류 시에만 재시도 권장 (기본값은 5xx/408/429도 재시도; 커스텀 RetryPolicy 로 좁히기 필요) |

:::warning
비멱등성 POST 요청도 기본적으로 재시도됩니다. 정밀한 제어가 필요한 경우 커스텀 `RetryPolicy`를 구현하세요.
:::

## 다음 단계

- [오류 처리](../advanced/error-handling) - 완전한 오류 처리 가이드
- [설정 API](../api-reference/client-config/config) - 재시도 설정 참조
- [인터페이스 정의](../api-reference/types/interfaces) - RetryPolicy 인터페이스 참조
