Retry 설정으로 재시도 동작 제어하기

이 문서에서 배울 내용

  • @retry 데코레이터로 함수에 자동 재시도를 적용하는 방법

  • configure_retry로 전역 재시도 설정을 변경하는 방법

  • 설정 우선순위와 reset_retry_config를 통한 초기화

PyQQQ SDK의 retry 모듈은 네트워크 오류, API 일시 장애 등 일시적 실패 상황에서 함수를 자동으로 재시도하는 기능을 제공합니다. @retry 데코레이터로 개별 함수에 재시도를 적용하고, configure_retry로 프로젝트 전체의 재시도 동작을 일괄 제어할 수 있습니다.

@retry 데코레이터 기본 사용법

@retry 데코레이터를 함수에 적용하면, 지정한 예외가 발생했을 때 자동으로 재시도합니다.

from pyqqq.utils.retry import retry

@retry(Exception, total_tries=3, delay=1, backoff=2)
def fetch_price(ticker: str):
    """주가를 조회합니다. 실패 시 최대 3회 시도합니다."""
    response = requests.get(f"https://api.example.com/price/{ticker}")
    response.raise_for_status()
    return response.json()

파라미터 설명

파라미터

기본값

설명

exceptions

(필수)

재시도를 트리거할 예외 클래스 또는 튜플

total_tries

5

최초 시도를 포함한 총 시도 횟수

delay

0.5

첫 번째 재시도까지의 대기 시간(초)

backoff

2

재시도마다 대기 시간에 곱해지는 배수

silently

False

True면 재시도 시 경고 로그를 출력하지 않음

backoff 동작 예시

delay=1, backoff=2, total_tries=4인 경우 대기 시간은 다음과 같이 증가합니다:

1차 실패 → 1초 대기 → 2차 시도
2차 실패 → 2초 대기 → 3차 시도
3차 실패 → 4초 대기 → 4차 시도
4차 실패 → 예외 발생

특정 예외만 재시도하기

튜플을 사용하면 여러 예외 타입에 대해 재시도할 수 있습니다. 지정하지 않은 예외는 즉시 전파됩니다.

from pyqqq.utils.retry import retry
import requests

@retry((requests.ConnectionError, requests.Timeout), total_tries=5, delay=2, backoff=2)
def call_api():
    """네트워크 오류와 타임아웃만 재시도합니다."""
    resp = requests.get("https://api.example.com/data", timeout=5)
    resp.raise_for_status()
    return resp.json()

configure_retry로 전역 설정 변경하기

프로젝트 전체에서 @retry가 적용된 모든 함수의 재시도 동작을 한 번에 변경하려면 configure_retry를 사용합니다. 전역 설정은 데코레이터에 지정된 인자보다 우선 적용됩니다.

from pyqqq.utils.retry import configure_retry

# 모든 @retry 함수에 대해 총 시도 횟수를 10회, 초기 대기 시간을 2초로 변경
configure_retry(total_tries=10, delay=2)

RetryConfig 필드

필드

타입

설명

total_tries

int

시도할 총 횟수

delay

float

재시도 간 초기 지연 시간(초)

backoff

float

백오프 배수

silently

bool

True면 재시도 로그를 숨김

Important

configure_retry에 전달된 인자만 전역 설정에 반영되며, 전달하지 않은 인자는 기존 값을 유지합니다.

설정 우선순위

@retry 데코레이터가 실행될 때, 각 파라미터는 다음 순서로 결정됩니다:

  1. 전역 설정 (configure_retry) — 값이 설정되어 있으면 우선 사용

  2. 데코레이터 인자 — 전역 설정이 None인 필드에 대해 적용

from pyqqq.utils.retry import retry, configure_retry

configure_retry(total_tries=10)

@retry(Exception, total_tries=3, delay=1, backoff=2)
def my_func():
    raise Exception("fail")

# total_tries → 10 (전역 설정 우선)
# delay       → 1  (전역 설정 없음, 데코레이터 인자 사용)
# backoff     → 2  (전역 설정 없음, 데코레이터 인자 사용)

전역 설정 초기화

reset_retry_config를 호출하면 전역 설정을 모두 초기 상태(None)로 되돌립니다. 초기화 후에는 @retry 데코레이터에 지정된 기본값이 그대로 적용됩니다.

from pyqqq.utils.retry import configure_retry, reset_retry_config

configure_retry(total_tries=10, delay=5)

# 전역 설정 초기화
reset_retry_config()

# 이후 @retry 데코레이터는 각자 지정한 기본값으로 동작합니다.

활용 사례

전략 진입점에서 전역 설정 적용하기

전략 스크립트의 시작 부분에서 configure_retry를 호출하면, 이후 모든 API 호출 함수의 재시도 동작을 일괄 제어할 수 있습니다.

from pyqqq.utils.retry import configure_retry, retry

# 전략 시작 시 전역 retry 설정
configure_retry(total_tries=10, delay=1, backoff=2, silently=False)


@retry(Exception)
def get_market_data():
    ...


@retry(Exception)
def submit_order(ticker, qty, price):
    ...

운영 환경에 따라 설정 분리하기

개발 환경에서는 빠른 실패 확인을 위해 적은 재시도 횟수를, 운영 환경에서는 안정성을 위해 많은 재시도 횟수를 설정할 수 있습니다.

import os
from pyqqq.utils.retry import configure_retry

if os.getenv("ENV") == "production":
    configure_retry(total_tries=15, delay=2, backoff=2, silently=True)
else:
    configure_retry(total_tries=2, delay=0.1, backoff=1)

로그 숨기기

재시도 경고 로그가 과도하게 출력되는 경우, silently=True로 설정하면 재시도 과정의 로그를 숨길 수 있습니다. 단, 최종 실패 시에는 항상 에러 로그가 출력됩니다.

from pyqqq.utils.retry import configure_retry

configure_retry(silently=True)

다음 단계

  • retry API 레퍼런스RetryConfig, configure_retry, reset_retry_config, retry의 전체 시그니처와 파라미터 설명