tenacity는 함수 재시도 로직을 데코레이터로 선언하는 라이브러리입니다. 네트워크 호출처럼 일시적 실패가 잦은 코드에 try/except + for 루프를 직접 짜는 대신, 데코레이터 한 줄로 재시도 전략을 설정할 수 있습니다.
from tenacity import (
retry, # 데코레이터 본체 — 재시도 동작을 함수에 부착
retry_if_exception_type, # "어떤 예외일 때" 재시도할지 조건 설정
stop_after_attempt, # "몇 번까지" 재시도할지 제한
wait_exponential, # "얼마나 기다렸다가" 재시도할지 간격 설정
)
@retry(
retry=retry_if_exception_type((RateLimitError, APITimeoutError, APIConnectionError)),
wait=wait_exponential(multiplier=1, min=2, max=10),
stop=stop_after_attempt(3),
reraise=True,
)
def _call_api(messages, max_tokens):
...
retry=retry_if_exception_type(...)retry_if_exception_type((RateLimitError, APITimeoutError, APIConnectionError))
# 이 세 가지 예외가 발생했을 때만 재시도
# 그 외 예외 (ValueError, KeyError 등)는 즉시 올림 — 재시도 없음
# RateLimitError — API 호출 한도 초과
# APITimeoutError — 30초 타임아웃 초과
# APIConnectionError — 네트워크 연결 실패
wait=wait_exponential(multiplier=1, min=2, max=10)# 재시도 간격을 지수적으로 늘림
# multiplier=1, min=2, max=10 기준:
# 1회 실패 → 2초 대기
# 2회 실패 → 4초 대기
# 3회 실패 → 8초 대기 (max=10이므로 10초 상한)
# 계산식: min(multiplier * 2^attempt, max)
# = min(1 * 2^1, 10) = 2
# = min(1 * 2^2, 10) = 4
# = min(1 * 2^3, 10) = 8
stop=stop_after_attempt(3)# 최대 3회 시도 후 중단
# 1회 실패 → 대기 → 2회 실패 → 대기 → 3회 실패 → 포기
# stop_after_attempt(3)은 "3번 시도" 기준 (재시도 횟수가 아님)
reraise=True# 3회 모두 실패했을 때 원래 예외를 그대로 올림
# reraise=False(기본값)이면 tenacity 자체 예외(RetryError)로 감싸서 올림
# reraise=True → raise RateLimitError(...) ← 원래 예외 그대로
# reraise=False → raise RetryError(...) ← tenacity 래퍼 예외
# tenacity 없이 동일 로직을 직접 구현
import time
def _call_api_manual(messages, max_tokens):
max_attempts = 3
wait = 2
for attempt in range(1, max_attempts + 1):
try:
response = client.chat.completions.create(...)
return response.choices[0].message.content
except (RateLimitError, APITimeoutError, APIConnectionError) as e:
if attempt == max_attempts:
raise # 마지막 시도면 그냥 올림
time.sleep(wait)
wait = min(wait * 2, 10) # 지수 증가
# 그 외 예외는 except에 안 걸려서 즉시 올라감
# tenacity @retry 데코레이터가 위 로직을 대체
| 파라미터 | 역할 | 이 코드에서 설정값 |
|---|---|---|
retry | 재시도 조건 | Rate/Timeout/Connection 에러 3종 |
wait | 재시도 간격 | 2s → 4s → 8s (지수 증가) |
stop | 최대 시도 횟수 | 3회 |
reraise | 실패 시 예외 타입 | 원래 예외 그대로 |
한 줄 요약:
tenacity의@retry데코레이터는 지정한 예외 발생 시 exponential backoff 간격으로 최대 N회 재시도하는 로직을 선언적으로 표현하며,try/except+for루프를 직접 짜는 것보다 간결하고 오류가 적습니다.