튜토리얼약 4분 읽기

증권 API 레이트리밋과 재시도 설계 — 요청이 몰릴 때 계좌를 지키는 법

장 시작 직후 요청이 몰리면 벌어지는 일

장이 열리는 순간, 여러 종목을 동시에 조회하거나 여러 주문을 한꺼번에 넣으려는 코드는 짧은 시간에 API 요청이 몰리게 된다. 증권사 API는 대부분 초당·분당 요청 한도(레이트리밋)를 두고 있어서, 이 한도를 넘으면 요청이 거부되거나 일시 차단된다. 에러코드 핸들링에서 다룬 "일시적 에러" 그룹 중 상당수가 사실 이 레이트리밋 문제다.

이 글은 특정 증권사의 실제 요청 한도 수치를 다루지 않는다. 대신 한도가 얼마든 적용할 수 있는 재시도·백오프 설계를 다룬다.

무작정 재시도하면 안 되는 이유

레이트리밋에 걸렸는데 곧바로 다시 요청을 보내면, 한도가 풀리기 전에 또 걸린다. 더 나쁜 경우 이런 재시도가 쌓이면 요청 폭주 자체가 다음 한도 초과의 원인이 된다.

지수 백오프(Exponential Backoff)로 재시도 간격을 늘린다

python 코드 보기
def call_with_backoff(request_fn, max_retries=5, base_delay=1.0):
    for attempt in range(max_retries):
        response = request_fn()

        if response.is_success:
            return response

        if response.error_type != "rate_limited":
            raise ApiError(response.error_code)

        delay = base_delay * (2 ** attempt) + random_uniform(0, base_delay)
        sleep(delay)

    raise ApiError("재시도 한도 초과 - 요청 중단")

여기서 중요한 건 재시도할 때마다 대기 시간을 두 배씩 늘린다는 점이다. 이렇게 하면 한도가 실제로 풀릴 시간을 벌어주면서, 그 사이에도 계속 요청을 쏘는 상황을 막는다. delay 계산에 더한 무작위 지터(jitter)도 같은 이유다 — 같은 한도 초과를 겪은 여러 종목·여러 프로세스의 재시도가 정확히 같은 간격으로 동시에 몰리면, 두 배씩 늘려도 한 박자마다 다시 요청이 겹쳐 한도를 또 넘긴다. 대기 시간에 약간의 무작위성을 섞어 재시도 타이밍을 흩어놓는 것도 백오프 설계의 일부다.

애초에 요청을 몰리지 않게 만드는 큐 설계

재시도만으로는 부족하다. 여러 종목을 조회해야 할 때 한 번에 다 쏘지 않고, 요청을 큐에 넣고 정해진 속도로만 꺼내 보내는 방식이 근본적인 해법이다. 초당 처리 가능한 요청 수를 알고 있다면, 그 속도에 맞춰 큐에서 요청을 하나씩 꺼내는 구조를 만들면 애초에 레이트리밋에 걸릴 일이 줄어든다.

자주 하는 실수

  1. 재시도 간격을 고정값으로 둔다. 한도가 안 풀렸는데 같은 간격으로 계속 재시도해 오히려 상황을 악화시킨다.
  2. 재시도 횟수에 상한을 두지 않는다. 근본 원인이 해결되지 않는 상황에서 무한 재시도는 무인 운영에서 다룬 "조용히 멈춘 것처럼 보이는" 상태를 만든다.
  3. 레이트리밋 에러와 다른 종류의 에러를 같은 재시도 로직으로 처리한다. 인증 오류처럼 재시도로 해결되지 않는 에러까지 백오프에 태우면 문제 발견이 늦어진다.

오늘의 정리

  1. 증권사 API는 대부분 요청 한도를 두므로, 요청이 몰리는 장 시작 직후 등에는 레이트리밋에 걸릴 가능성을 항상 염두에 둬야 한다.
  2. 레이트리밋에 걸렸을 때 곧바로 재시도하면 상황이 악화되므로, 재시도 간격을 점점 늘리는 지수 백오프가 안전하다.
  3. 재시도만으로 해결하려 하지 말고, 요청 자체를 큐에 넣어 속도를 조절하는 설계가 근본적인 해법이다.
  4. 레이트리밋 에러와 다른 종류의 에러는 분리해서 처리해야, 재시도로 해결되지 않는 문제를 조기에 발견할 수 있다.

이 글의 코드는 재시도 설계를 설명하기 위한 의사코드이며 특정 증권사의 실제 요청 한도나 API 응답을 담고 있지 않습니다. 실제 연동은 반드시 해당 증권사 공식 API 문서를 기준으로 진행하시기 바랍니다. 이 글은 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 수익을 보장하지 않으며, 투자 손실에 대한 책임은 투자자 본인에게 있습니다.

← 전체 글 목록