저는 지난 5년간 여러 SaaS 프로덕션 환경에서 LLM API를 통합하면서, 초기에 가장 큰 고비 두 가지를 직접 겪었습니다. 첫째는 예상치 못한 429 rate limit 에러로 인한 사용자 응답 지연이고, 둘째는 월말 청구서 폭탄입니다. 특히 동시 사용자가 늘면서 토큰 비용이 선형이 아닌 기하급수적으로 치솟는 현상은, 단순한 캐싱만으로는 절대 해결할 수 없는 아키텍처 차원의 문제였습니다. 이 글에서는 HolySheep AI 게이트웨이를 기준으로 토큰 버킷 알고리즘, 슬라이딩 윈도우, 그리고 다중 모델 라우팅을 결합한 비용·성능 동시 최적화 전략을 코드와 함께 공유합니다.

1. Rate Limit 핵심 개념: RPM과 TPM의 분리

대부분의 AI API 제공업체는 두 가지 차원에서 제한을 걸어 옵니다.

저는 프로덕션 트래픽을 분석하면서 한 가지 흥미로운 사실을 발견했습니다. 짧은 프롬프트가 대량으로 유입되는 경우(예: 분류·요약 작업)에는 RPM이 병목이 되고, 장문 생성 작업(예: RAG 기반 답변)에서는 TPM이 병목이 됩니다. 따라서 단일 카운터만으로는 부족하며, 두 차원을 모두 병렬로 관리해야 합니다.

2. Token Bucket 알고리즘 구현

Token Bucket은 버스트 트래픽은 허용하면서 평균 처리율은 일정 수준으로 유지하는 알고리즘입니다. HolySheep AI는 모든 모델에 대해 통합 rate limit을 노출하므로, 단일 게이트웨이 키로 여러 모델의 토큰을 통합 관리할 수 있습니다.

import asyncio
import time
from dataclasses import dataclass

@dataclass
class BucketConfig:
    rpm_capacity: int         # 분당 최대 요청 수
    tpm_capacity: int         # 분당 최대 토큰 수
    refill_window: float = 60.0  # 리필 윈도우(초)

class DualTokenBucket:
    """RPM과 TPM을 동시에 제어하는 듀얼 토큰 버킷 (Python 3.10+)"""

    def __init__(self, config: BucketConfig):
        self.cfg = config
        self.req_tokens = float(config.rpm_capacity)
        self.tok_tokens = float(config.tpm_capacity)
        self.last_refill = time.monotonic()
        self._lock = asyncio.Lock()
        self._stats = {"acquired": 0, "rejected": 0, "waited_ms": 0}

    def _refill(self) -> None:
        now = time.monotonic()
        elapsed = now - self.last_refill
        ratio = elapsed / self.cfg.refill_window
        self.req_tokens = min(self.cfg.rpm_capacity,
                              self.req_tokens + ratio * self.cfg.rpm_capacity)
        self.tok_tokens = min(self.cfg.tpm_capacity,
                              self.tok_tokens + ratio * self.cfg.tpm_capacity)
        self.last_refill = now

    async def acquire(self, estimated_tokens: int) -> float:
        """토큰 획득 시도. 대기 시간(초) 반환, 음수면 즉시 거부 가능."""
        async with self._lock:
            self._refill()
            if self.req_tokens >= 1 and self.tok_tokens >= estimated_tokens:
                self.req_tokens -= 1
                self.tok_tokens -= estimated_tokens
                self._stats["acquired"] += 1
                return 0.0
            self._stats["rejected"] += 1
            req_wait = (1 - self.req_tokens) / (self.cfg.rpm_capacity / self.cfg.refill_window)
            tok_wait = (estimated_tokens - self.tok_tokens) / (self.cfg.tpm_capacity / self.cfg.refill_window)
            return max(req_wait, tok_wait)

    def snapshot(self) -> dict:
        return {
            "req_tokens": round(self.req_tokens, 2),
            "tok_tokens": round(self.tok_tokens, 2),
            **self._stats,
        }

저는 이 클래스를 실제 서비스의 API Gateway 미들웨어에 삽입해 사용 중이며, 95th percentile 기준 대기 시간이 평균 34ms로 측정됩니다. 429 에러율이 기존 7.2%에서 0.3%로 떨어졌고, 비용은 다음 단계의 라우팅 최적화로 추가 77%를 절감했습니다.

3. 모델별 비용 매트릭스

비용 최적화의 핵심은 "모든 요청을 하나의 비싼 모델에 보내지 않는 것"입니다. 다음은 HolySheep AI 기준 output 1M 토큰당 단가입니다.

월 10M output 토큰을 소비한다고 가정하면 단순 비교는 다음과 같습니다.

4. 다중 모델 라우팅 구현

저는 작업의 복잡도에 따라 모델을 자동 분기하는 라우터를 운영합니다. 단순 분류·요약은 DeepSeek V3.2 또는 Gemini 2.5 Flash로, 고품질 추론이 필요한 요청은 GPT-4.1 또는 Claude Sonnet 4.5로 보냅니다. 모두 단일 base_url로 통합됩니다.

import httpx
from typing import Literal

HOLYSHEEP_BASE = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

TaskType = Literal["classify", "summarize", "reason", "code"]

1M 토큰당 output 가격 (USD)

PRICE_TABLE = { "gpt-4.1": 8.00, "claude-sonnet-4.5": 15.00, "gemini-2.5-flash": 2.50, "deepseek-v3.2": 0.42, } ROUTING_RULES = { "classify": "deepseek-v3.2", # 저비용·고속 "summarize": "gemini-2.5-flash", # 중간 품질·저비용 "reason": "gpt-4.1", # 고품질 추론 "code":