본문으로 건너뛰기

챗봇 서비스를 위한 효과적인 사용자별 속도 제한(Rate Limit) 전략

Your chat bot needs a better rate limit strategy

작성자
발행일
2026년 03월 03일
https://stevepolito.design/blog/chat-bot-per-user-rate-limits

핵심 요약

  • 1 단순한 API 호출 횟수 제한을 넘어 토큰 사용량(TPM)을 개별 사용자 단위로 관리하여 전체 시스템의 가용성을 보호해야 합니다.
  • 2 Redis의 증감(INCR) 및 만료(EXPIRE) 기능을 활용하여 Ruby on Rails 환경에서 효율적인 고정 윈도우 방식의 속도 제한을 구현할 수 있습니다.
  • 3 속도 제한 초과 시 즉각적인 거부 대신 백그라운드 작업을 통한 재시도(Retry) 전략을 도입하여 사용자 경험의 단절을 최소화할 수 있습니다.

도입

OpenAI와 같은 대규모 언어 모델(LLM) API를 사용하는 챗봇 서비스에서 속도 제한(Rate Limit) 관리는 필수적입니다. 단순히 조직 전체의 제한을 준수하는 것만으로는 부족하며, 특정 사용자가 과도하게 자원을 소모하여 전체 서비스가 중단되는 '서비스 거부(DoS)' 상황을 방지하기 위해 개별 사용자별 제한 전략이 필요합니다. 본 글에서는 Ruby on Rails와 Redis를 활용하여 분당 요청 수(RPM)와 분당 토큰 수(TPM)를 효과적으로 제어하고, 이를 통해 안정적인 AI 서비스를 운영하는 구체적인 방법론을 제시합니다.

1. 챗봇 환경에서 속도 제한이 중요한 이유

일반적인 API와 달리 챗봇은 두 가지 차원에서 자원을 급격히 소모합니다. 첫째는 분당 요청 수(RPM)입니다. 대화형 인터페이스 특성상 사용자는 짧은 시간에 여러 번 메시지를 보낼 수 있습니다. 둘째는 분당 토큰 수(TPM)입니다. 대화가 길어질수록 컨텍스트 윈도우가 커지고, 첨부 파일이나 긴 메시지는 토큰 사용량을 기하급수적으로 늘립니다. 한 명의 사용자가 조직의 전체 할당량을 소모해 버리면, 해당 챗봇뿐만 아니라 동일한 API 키를 공유하는 사내의 다른 모든 AI 도구들이 마비되는 결과로 이어집니다. 따라서 개별 사용자의 남용이 전체 인프라에 영향을 주지 않도록 격리하는 전략이 필수적입니다.

2. Redis를 활용한 RPM(분당 요청 수) 제한 구현

Rails의 기본 rate_limit 기능은 컨트롤러 수준에서 유용하지만, 토큰 기반의 정교한 제어에는 한계가 있습니다. 이를 해결하기 위해 Redis의 INCREXPIRE 명령을 활용한 ‘고정 윈도우(Fixed-window)’ 방식을 권장합니다. * 구현 방식: Usage 클래스를 생성하여 사용자 ID별로 고유한 키를 생성하고 Redis 캐시 스토어를 주입합니다. * 동작 원리: 요청이 발생할 때마다 Redis의 카운터를 1씩 증가시키고, 1분 후 만료되도록 설정합니다. * 장점: Redis의 원자적(Atomic) 연산을 통해 데이터 무결성을 보장하며, 매우 빠른 성능으로 실시간 요청을 처리할 수 있습니다.

3. TPM(분당 토큰 수) 추적 및 제한

메시지 횟수만 제한하는 것은 불충분합니다. 단 한 번의 요청이라도 수만 개의 토큰을 사용할 수 있기 때문입니다. OpenAI API는 응답 객체에 usage 데이터를 포함하며, RubyLLM과 같은 라이브러리를 사용하면 입력(Input), 출력(Output), 추론(Thinking) 토큰을 쉽게 추출할 수 있습니다. * 토큰 데이터 확보: 응답에서 추출한 총 토큰 수를 Usage 인스턴스에 전달합니다. * 누적 추적: RPM과 동일하게 Redis를 사용하여 사용자가 소비한 총 토큰 수를 분 단위로 누적합니다. * 검증 로직: API 호출 전, 현재 사용자의 누적 토큰량이 설정된 임계값을 초과했는지 확인하여 초과 시 요청을 차단하거나 지연시킵니다.

4. 적절한 사용자별 임계값 산출 공식

조직 전체의 제한 수치를 개별 사용자에게 어떻게 배분할지는 서비스 초기 단계에서 매우 중요한 결정입니다. 다음과 같은 산출 공식을 제안합니다. * 공식: 사용자별 제한 = (조직 전체 제한 × 버퍼) / 예상 동시 접속자 수 * 예시: 조직의 RPM이 125이고 동시 접속자가 10명이며 20%의 여유(버퍼 0.8)를 둔다면, 사용자당 RPM은 10으로 설정하는 것이 안전합니다. 이 방식은 예상치 못한 트래픽 급증에 유연하게 대응할 수 있게 해줍니다.

5. 사용자 경험을 고려한 고급 전략: 백그라운드 큐잉

사용자의 요청을 단순히 거절하는 것은 좋지 않은 사용자 경험을 유발합니다. 대신 ActiveJob을 활용한 대기열 방식을 도입할 수 있습니다. * 재시도 메커니즘: 사용자가 제한을 초과했을 때 RateLimitExhaustedError를 발생시키고, 특정 시간(예: 15초) 후에 작업을 재시도하도록 설정합니다. * 워크플로우: 메시지 전송 → 로딩 상태 표시 → 백그라운드 작업 실행 → 제한 확인 → (초과 시) 대기 후 재시도 → 결과 브로드캐스트 순으로 진행됩니다. 이를 통해 사용자는 시스템이 중단된 것이 아니라 잠시 지연되고 있다는 느낌을 받게 됩니다.

결론

AI 기술의 발전으로 챗봇은 보편화되었지만, 그만큼 비용과 자원 관리의 중요성도 커졌습니다. 개별 사용자 단위의 RPM 및 TPM 제한은 시스템의 안정성을 보장하는 최소한의 안전장치입니다. 개발팀은 기술적인 구현을 넘어, 제한에 도달한 사용자에게 유료 플랜 업셀링을 제안하거나, 더 저렴한 모델(Fallback)로 전환하는 등 비즈니스 및 디자인 측면의 다각적인 대응 전략을 수립해야 합니다. 이러한 접근은 지속 가능한 AI 서비스를 만드는 초석이 됩니다.

댓글0

댓글 작성

댓글 삭제 시 비밀번호가 필요합니다.

이미 계정이 있으신가요? 로그인 후 댓글을 작성하세요.

0/1000
정중하고 건설적인 댓글을 작성해 주세요.