GPT API 호출 함수를 배포했습니다. 스테이징에서는 정상인데, 프로덕션에서 첫 100명이 접근하자 로그가 429 Too Many Requests로 가득 찹니다. 이때 확인해야 할 것은 “429가 났다”가 아니라 RPM, TPM, Daily Cap, 티어, 모델별 제한 중 무엇에 걸렸는지입니다.
이 글은 최신 GPT 모델에서 자주 마주치는 속도 제한을 구분하고, Apidog에서 몇 번의 API 호출과 작은 부하 테스트로 실제 한도를 확인하는 방법을 정리합니다. 목표는 추측이 아니라, 팀에서 재사용할 수 있는 요청 컬렉션과 반복 가능한 테스트 워크플로우를 만드는 것입니다.
OpenAI를 사용해 봤다면 모델이 바뀔 때마다 속도 제한 확인이 더 중요해진다는 것을 알 수 있습니다. GPT-5.5는 GPT-4.1과 제한이 다를 수 있고, 이미지 모델은 텍스트 모델과 다른 방식으로 계산되며, 지출 증가에 따라 사용량 티어도 조용히 변경될 수 있습니다. Apidog를 사용하면 각 요청의 응답 헤더를 확인하고, 동시 트래픽을 시뮬레이션하며, 코드를 배포하기 전에 어떤 제한에 걸리는지 확인할 수 있습니다.
실제로 중요한 네 가지 제한
OpenAI는 GPT API 키에 여러 속도 제한을 적용합니다. 프로덕션에서 주로 확인해야 할 항목은 다음 네 가지입니다.
- RPM: Requests Per Minute. 분당 전송할 수 있는 API 호출 수입니다.
- TPM: Tokens Per Minute. 분당 처리할 수 있는 입력 토큰과 출력 토큰의 합입니다.
- RPD: Requests Per Day. 무료 및 낮은 티어에서 자주 만나는 일일 요청 상한입니다.
- IPM / TPD / 배치 큐 제한: 이미지, 오디오, 임베딩, 배치 엔드포인트에 적용되는 모델별 제한입니다.
요청이 거부되면 API는 보통 HTTP 429와 함께 다음과 같은 JSON을 반환합니다.
{
"error": {
"message": "Rate limit reached for gpt-5.5 in organization org-abc on tokens per min (TPM): Limit 30000, Used 28432, Requested 3120.",
"type": "tokens",
"param": null,
"code": "rate_limit_exceeded"
}
}
여기서 가장 먼저 볼 부분은 message와 type입니다.
-
tokens이면 TPM 문제일 가능성이 큽니다. -
requests이면 RPM 문제일 가능성이 큽니다. -
quota또는 결제 관련 메시지이면 속도 제한이 아니라 사용량/결제 한도 문제일 수 있습니다.
모든 429가 같은 원인은 아닙니다. 해결 방법도 다릅니다.
HTTP 429의 의미는 MDN 429 문서와 RFC 6585 사양을 참고하세요. OpenAI의 재시도 헤더와 티어 관련 동작은 공식 속도 제한 문서를 확인하는 것이 가장 안전합니다.
티어 작동 방식과 승격되는 조건
GPT API 키는 OpenAI 사용량 티어에 속합니다. 티어는 RPM과 TPM의 실제 수치를 결정합니다. 계정의 누적 지출과 첫 결제 이후 경과 시간에 따라 티어가 올라갑니다.
텍스트 모델 기준으로 대략적인 형태는 다음과 같습니다.
| 티어 | 지출 조건 | 대기 조건 | 텍스트 RPM | 텍스트 TPM |
|---|---|---|---|---|
| 무료 | 없음 | 없음 | 3 | 40k |
| 1 | $5 지불 | 없음 | 500 | 모델별 30k–200k |
| 2 | $50 지불 | 7일 | 5,000 | 450k |
| 3 | $100 지불 | 7일 | 5,000 | 1M |
| 4 | $250 지불 | 14일 | 10,000 | 2M |
| 5 | $1,000 지불 | 30일 | 10,000 | 2M+ |
위 값은 예시입니다. 정확한 한도는 시간이 지나면서 바뀔 수 있고 모델마다 다릅니다. 실제 워크로드를 측정하기 전에는 대시보드 또는 API 응답 헤더에서 현재 한도를 직접 확인하세요.
실무적으로는 두 가지를 기억하면 됩니다.
결제 조건을 만족하면 자동으로 승격됩니다.
별도 마이그레이션 단계 없이 다음 요청부터 새로운 한도가 적용될 수 있습니다.계정 상태에 따라 제한이 낮아질 수도 있습니다.
결제 실패, 장기 비활성화, 조직 설정 변경 후에는 프로덕션 배포 전에 다시 테스트해야 합니다.
다른 모델 제공업체의 티어 시스템과 비교하려면 OpenAI API 사용자 속도 제한 설명, Claude API 속도 제한 가이드, Grok-3 API 속도 제한 가이드를 참고하세요.
응답 헤더에서 실시간 제한 확인하기
현재 제한을 확인하기 위해 항상 대시보드를 열 필요는 없습니다. GPT API 응답 헤더에는 속도 제한 정보가 포함됩니다.
주로 확인할 헤더는 다음 네 가지입니다.
x-ratelimit-limit-requests
x-ratelimit-remaining-requests
x-ratelimit-limit-tokens
x-ratelimit-remaining-tokens
추가로 다음 헤더도 자주 함께 반환됩니다.
x-ratelimit-reset-requests
x-ratelimit-reset-tokens
이 값은 요청 또는 토큰 버킷이 다시 채워질 때까지 남은 시간을 나타냅니다. 예를 들어 6s, 1m30s처럼 표시될 수 있습니다.
단계 1: Apidog에서 GPT 요청 구성하기
Apidog에서 새 프로젝트를 만들고 새 요청을 추가합니다.
Method: POST
URL: https://api.openai.com/v1/chat/completions
Headers 탭에는 다음 값을 설정합니다.
| 키 | 값 |
|---|---|
Authorization |
Bearer {{OPENAI_API_KEY}} |
Content-Type |
application/json |
{{OPENAI_API_KEY}}는 Apidog 환경 변수입니다. API 키를 요청 본문이나 컬렉션에 직접 저장하지 않고, 환경별로 안전하게 관리할 수 있습니다.
Body 탭에서 JSON을 선택하고 다음을 입력합니다.
{
"model": "gpt-5.5",
"messages": [
{
"role": "user",
"content": "ping"
}
],
"max_tokens": 10
}
Send를 클릭한 뒤 응답 패널의 Headers 탭을 엽니다. 그리고 x-ratelimit-* 헤더를 확인합니다.
이때 확인해야 할 기준선은 다음입니다.
x-ratelimit-limit-requests
x-ratelimit-remaining-requests
x-ratelimit-limit-tokens
x-ratelimit-remaining-tokens
이 값이 현재 계정, 조직, 모델, 엔드포인트에 적용되는 실제 한도입니다.
ChatGPT API 요청 설정, 인증, 스트리밍, 도구 호출까지 함께 확인하려면 Apidog로 ChatGPT API를 테스트하는 방법 가이드를 참고하세요.
단계 2: 작은 버스트 테스트로 RPM 확인하기
단일 요청으로는 한도 근처에서 어떤 일이 발생하는지 알 수 없습니다. 실제로 스로틀링이 발생하는지 보려면 작은 버스트 테스트를 실행해야 합니다.
Apidog에서 저장한 요청을 열고 Send 옆 드롭다운에서 Run in Test Scenario를 선택합니다.
예시 설정은 다음과 같습니다.
반복 횟수: 50
동시성: 10
반복 간 지연: 0 ms
실행 후 결과를 봅니다.
가능한 결과는 보통 두 가지입니다.
일부 요청이 429를 반환한다.
응답 헤더에 표시된 제한과 실제 계정 상태가 일치한다는 뜻입니다.모든 요청이 성공한다.
현재 RPM이 예상보다 높을 수 있습니다. 각 응답의remaining-requests감소를 확인하세요.
Apidog 테스트 러너는 각 응답을 기록합니다. 상태 코드로 정렬하면 429 응답만 모아서 볼 수 있습니다. 429 응답의 본문에서 message를 확인하면 RPM, TPM, Daily Cap 중 무엇을 초과했는지 알 수 있습니다.
429 원인별 대응은 속도 제한 초과 가이드도 참고할 수 있습니다.
단계 3: RPM 초과와 TPM 초과 구분하기
앞의 테스트는 각 요청이 작기 때문에 주로 RPM을 확인합니다. TPM을 확인하려면 요청 수는 줄이고, 요청당 토큰 수를 늘려야 합니다.
예를 들어 요청 본문을 다음처럼 바꿉니다.
{
"model": "gpt-5.5",
"messages": [
{
"role": "system",
"content": "<3,000 tokens of context here>"
},
{
"role": "user",
"content": "Summarise the above in one sentence."
}
],
"max_tokens": 200
}
이번에는 다음처럼 실행합니다.
반복 횟수: 20
동시성: 5
반복 간 지연: 0 ms
티어 1에서 TPM 한도가 30k라면, 요청 수 제한에 도달하기 전에 토큰 제한에 먼저 도달할 수 있습니다.
이 구분은 매우 중요합니다.
RPM 문제라면 해결책은 다음에 가깝습니다.
- 요청 큐잉
- 워커 수 제한
- 배치 처리
- 호출 간격 조정
TPM 문제라면 해결책은 다릅니다.
- 시스템 프롬프트 축소
- RAG 컨텍스트 길이 제한
- 문서 분할
- 캐싱 사용
-
max_tokens현실적으로 낮추기
단계 4: 동시 사용자 시뮬레이션하기
버스트 테스트는 상한선을 빠르게 확인하는 데 좋습니다. 하지만 실제 프로덕션 트래픽은 더 복잡합니다.
일반적으로 다음이 섞입니다.
- 짧은 요청
- 중간 크기 요청
- 긴 컨텍스트 요청
- 사용자별 랜덤한 호출 간격
- 특정 시간대의 트래픽 피크
Apidog에서는 요청 변형을 여러 개 만들어 테스트 시나리오에 넣을 수 있습니다.
예를 들어 다음 세 가지 요청을 만듭니다.
small-message
medium-context
large-context
그리고 시나리오에서 반복 실행합니다.
테스트 러너의 JavaScript 사전/사후 요청 스크립트를 활용하면 다음 작업도 가능합니다.
- 반복마다 랜덤 메시지 길이 선택
- 응답 후
x-ratelimit-remaining-tokens읽기 - 남은 토큰이 임계값 아래로 떨어지면 테스트 중단
- 200 응답과 429 응답의 지연 시간 분리 기록
테스트가 끝나면 상태 코드 히스토그램을 확인합니다. 이 결과는 런북에 붙여두기 좋습니다. 누군가 “지금 속도 제한에 걸린 건가요?”라고 물으면 같은 시나리오를 다시 실행해서 비교할 수 있습니다.
스로틀링에 걸렸을 때 해야 할 일
한도를 측정한 뒤에는 보통 세 가지 선택지가 있습니다.
1. 지연 재시도 적용하기
모든 GPT 호출을 지수 백오프 재시도로 감쌉니다.
가능하면 429 응답의 다음 헤더를 읽어 첫 재시도 지연 시간으로 사용하세요.
x-ratelimit-reset-tokens
x-ratelimit-reset-requests
단순한 예시는 다음과 같습니다.
async function callWithRetry(fn, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await fn();
if (res.status !== 429) {
return res;
}
const resetTokens = res.headers.get("x-ratelimit-reset-tokens");
const resetRequests = res.headers.get("x-ratelimit-reset-requests");
const delayMs = parseResetHeader(resetTokens || resetRequests) ?? Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
throw new Error("Rate limit retry attempts exceeded");
}
function parseResetHeader(value) {
if (!value) return null;
if (value.endsWith("ms")) {
return Number(value.replace("ms", ""));
}
if (value.endsWith("s")) {
return Number(value.replace("s", "")) * 1000;
}
if (value.endsWith("m")) {
return Number(value.replace("m", "")) * 60 * 1000;
}
return null;
}
실제 운영에서는 jitter를 추가해 여러 워커가 동시에 재시도하지 않도록 하는 것이 좋습니다.
2. 큐로 처리량 제한하기
트래픽이 버스트성이라면 요청을 큐에 넣고 한도보다 약간 낮은 속도로 처리합니다.
예를 들어 TPM 제한이 있다면 토큰 버킷 방식으로 처리량을 제한할 수 있습니다.
허용 처리량 = 실제 TPM 한도 * 0.8
안전 계수를 두면 갑작스러운 프롬프트 증가나 스트리밍 예약 토큰으로 인한 429를 줄일 수 있습니다.
구현 방식은 API 속도 제한을 구현하는 방법과 API에서 속도 제한 구현하기를 참고하세요.
3. 배치 API로 이동하기
사용자 응답에 즉시 필요하지 않은 작업은 동기 GPT 호출에서 분리할 수 있습니다.
예시는 다음과 같습니다.
- 야간 데이터 보강
- 문서 분류
- 임베딩 재생성
- 대량 요약
- 백오피스용 태깅 작업
이런 작업은 배치 API로 이동하면 사용자 대면 트래픽을 위한 동기 할당량을 더 안정적으로 확보할 수 있습니다.
스로틀링과 속도 제한의 차이를 더 명확히 이해하려면 스로틀 vs 속도 제한을 참고하세요.
일반적인 GPT 429 오류와 의미
실무에서 자주 보는 429는 대부분 다음 세 가지입니다.
Rate limit reached ... on requests per min (RPM)
분당 호출 수가 너무 많다는 뜻입니다.
대응 방법:
- 동시성 제한
- 워커 풀 크기 제한
- 큐 도입
- 짧은 요청을 묶어서 처리
- 병렬
map직접 실행 금지
예를 들어 레코드 1,000개를 한 번에 병렬 처리하지 말고, 워커 수를 제한하세요.
import pLimit from "p-limit";
const limit = pLimit(5);
await Promise.all(
records.map((record) =>
limit(() => callOpenAI(record))
)
);
Rate limit reached ... on tokens per min (TPM)
요청당 토큰이 너무 크거나, 동시에 처리되는 토큰 총량이 너무 많다는 뜻입니다.
대응 방법:
- 시스템 프롬프트 축소
- RAG 컨텍스트 상한 설정
- 긴 문서 chunking
-
max_tokens낮추기 - 캐싱 적용
특히 시간이 지나면서 시스템 프롬프트가 계속 커지는 경우 TPM 초과가 자주 발생합니다.
You exceeded your current quota, please check your plan and billing details
429처럼 보이지만, 실제 원인은 속도 제한이 아니라 결제 또는 사용량 한도일 수 있습니다.
가능한 원인:
- 월별 지출 한도 도달
- 등록된 카드 결제 실패
- 선불 잔액 소진
- 조직 결제 설정 문제
이 경우 코드를 수정해도 해결되지 않습니다. 결제 대시보드를 확인해야 합니다.
팀에서 재사용할 체크리스트
프로덕션 배포 전에는 다음 순서로 확인하세요.
- Apidog에서 단일 GPT 요청 실행
-
x-ratelimit-limit-*헤더 기록 - 작은 요청으로 RPM 버스트 테스트
- 큰 요청으로 TPM 버스트 테스트
- 실제 요청 크기 3~4개로 동시 사용자 시나리오 생성
- 429 응답 본문의
message저장 - 재시도, 큐, 배치 중 대응 방식 결정
- 요청과 테스트 시나리오를 팀 프로젝트에 저장
이렇게 해두면 다음에 모델을 바꾸거나 티어가 변경되어도 같은 시나리오를 다시 실행해 비교할 수 있습니다.
자주 묻는 질문
GPT 속도 제한을 테스트하는 데 Apidog 비용이 드나요?
무료 플랜에서도 단일 요청 테스트와 소규모 동시 테스트 실행이 가능합니다. 더 큰 테스트 부하, 팀 작업 공간, 예약 실행이 필요할 때 유료 플랜을 검토하면 됩니다. 자세한 내용은 Apidog 가격 책정을 참고하세요.
실제 토큰을 사용하지 않고 속도 제한을 테스트할 수 있나요?
부분적으로 가능합니다.
가장 저렴한 기준선 확인은 다음처럼 작은 요청을 보내는 것입니다.
{
"model": "gpt-5.5",
"messages": [
{
"role": "user",
"content": "x"
}
],
"max_tokens": 1
}
이 요청은 비용이 매우 낮고, 응답 헤더는 정상적으로 반환됩니다.
완전히 오프라인으로 재시도 로직만 검증하고 싶다면 Apidog의 목 서버를 사용해 429 응답 형태를 시뮬레이션할 수 있습니다.
티어 1 키가 동료의 티어 1 키보다 느리게 느껴지는 이유는 무엇인가요?
티어 한도는 키 단위가 아니라 조직 단위로 적용될 수 있습니다. 같은 조직 안에서 다른 사용자가 많은 트래픽을 보내고 있다면, 같은 한도를 공유하게 됩니다.
확인 방법은 간단합니다.
- 두 키로 같은 요청을 실행합니다.
-
x-ratelimit-remaining-tokens를 비교합니다. - 같은 조직의 다른 트래픽 때문에 값이 빠르게 줄어드는지 확인합니다.
어떤 모델이 어떤 제한을 가지고 있는지 어떻게 확인하나요?
응답 헤더를 읽는 것이 가장 정확합니다.
블로그의 일반 표나 오래된 문서보다 현재 API 응답 헤더가 더 신뢰할 수 있습니다. Apidog에서 모델별로 작은 요청을 하나씩 보내고 다음 값을 기록하세요.
x-ratelimit-limit-requests
x-ratelimit-limit-tokens
같은 모델 이름이라도 스냅샷 버전이 다르면 제한이 다를 수 있습니다.
스트리밍 요청은 다르게 계산되나요?
TPM 측면에서는 다르게 체감될 수 있습니다. 스트리밍 요청은 max_tokens를 기준으로 토큰을 예약할 수 있기 때문에, 실제 응답이 짧더라도 max_tokens가 크면 TPM 예산을 많이 사용할 수 있습니다.
따라서 스트리밍에서도 max_tokens를 현실적인 상한으로 낮추는 것이 좋습니다.
스트리밍 동작은 Apidog로 ChatGPT API를 테스트하는 방법에서 더 자세히 볼 수 있습니다.
Apidog 속도 제한 테스트를 팀과 공유할 수 있나요?
가능합니다. 요청과 테스트 시나리오를 공유 프로젝트에 저장하면 됩니다. 팀원은 각자 환경 변수만 바꿔 자신의 키로 같은 테스트를 실행할 수 있습니다.
이렇게 하면 “내 키가 문제인가요, 조직 한도가 문제인가요, 모델 제한이 바뀐 건가요?”라는 질문을 빠르게 확인할 수 있습니다.
Top comments (0)