왜 토큰 카운팅이 문제가 되는가

LLM API는 요청/응답 토큰 수에 비례해 과금되고, 모델마다 컨텍스트 상한이 있다. 그런데 많은 서비스가 "문자 수 / 4" 같은 근사식으로 토큰을 추정한다. 영어는 그럭저럭 맞지만 한국어·코드·이모지·URL이 섞이면 20~50%까지 오차가 난다. 결과는 두 가지다. 상한을 넘겨 400 context_length_exceeded로 요청이 통째로 실패하거나, 여유를 과도하게 잡아 컨텍스트를 낭비한다. 특히 RAG처럼 런타임에 문서를 끼워 넣는 구조에서는 실제 조립된 프롬프트의 토큰을 호출 직전에 정확히 알아야 한다.

근사식이 무너지는 지점

토크나이저는 BPE 계열이라 언어와 내용에 따라 문자당 토큰 비율이 크게 달라진다. 아래는 동일 길이 문자열에서 근사식과 실제 토크나이저가 얼마나 벌어지는지 보여주는 대략적 경향이다.

입력 유형문자/4 추정실제 토큰오차 경향
영어 산문비슷기준±5%
한국어 문장과소추정더 많음+30~50%
소스 코드과소추정더 많음+10~30%
반복 공백/JSON과대추정더 적음-10~20%

즉 한국어 서비스에서 "문자/4"는 거의 항상 과소추정이라 상한 초과 위험이 크다. 정확도를 원한다면 실제 토크나이저를 써야 한다.

실제 토크나이저로 세기

Anthropic SDK는 서버 측 카운팅 엔드포인트를 제공한다. 로컬 추정과 달리 실제 청구 기준과 일치하며, 시스템 프롬프트·툴 정의까지 포함해 계산할 수 있다.

from anthropic import Anthropic

client = Anthropic()

resp = client.messages.count_tokens(
    model="claude-opus-4-8",
    system="너는 한국어 요약 도우미다.",
    messages=[{"role": "user", "content": prompt_text}],
)
print(resp.input_tokens)  # 실제 청구 기준 입력 토큰

이 호출은 별도 과금이 없고 지연도 짧아, 대형 프롬프트를 보내기 전 게이트로 쓰기 좋다. 로컬에서 근사가 필요하면 OpenAI 계열은 tiktoken을 쓰되, 모델별 인코딩을 정확히 지정해야 한다.

사전 예산 검증 게이트

핵심 패턴은 "조립 → 카운팅 → 예산 비교 → 초과 시 축소"다. 응답 여유분(max_tokens)까지 상한에서 빼고 남은 예산 안에 입력을 맞춰야 한다.

MODEL_LIMIT = 200_000
RESERVE_OUTPUT = 8_000
SAFETY = 0.9  # 예상치 못한 확장 대비 완충

def fits_budget(input_tokens: int) -> bool:
    budget = (MODEL_LIMIT - RESERVE_OUTPUT) * SAFETY
    return input_tokens <= budget

tokens = client.messages.count_tokens(
    model="claude-opus-4-8", messages=msgs
).input_tokens

if not fits_budget(tokens):
    msgs = trim_context(msgs, tokens)  # 오래된 문서/턴부터 제거

SAFETY 완충을 두는 이유는 툴 스키마 변경이나 리트라이 시 프롬프트가 커질 수 있기 때문이다.

축소 전략과 캐시 연동

예산 초과 시 무작정 자르면 품질이 급락한다. 우선순위를 정해 축소한다. RAG 문서는 관련도 하위부터, 대화 히스토리는 오래된 턴부터 제거하되 시스템 프롬프트와 최근 사용자 발화는 보존한다. 반복 호출되는 시스템 프롬프트·툴 정의는 프롬프트 캐싱으로 묶으면 토큰 자체는 동일하게 계산되지만 비용이 크게 줄어든다. 카운팅 로직과 캐시 경계를 함께 설계하는 것이 좋다.

운영 시 주의점

  • 토큰 수는 모델·API 버전에 따라 달라진다. 상한과 카운팅에 쓰는 모델 ID를 반드시 일치시킨다.
  • 서버 카운팅에 의존한다면 네트워크 실패 대비로 로컬 근사식을 폴백으로 둔다. 단 폴백은 항상 보수적(과대추정)으로 잡아 초과를 막는다.
  • 스트리밍 응답의 실제 출력 토큰은 예약분과 다를 수 있으니, 사용량 메트릭은 응답의 usage 값으로 사후 검증한다.
  • 이미지·파일 등 멀티모달 입력은 문자 기반 추정이 전혀 통하지 않으므로 반드시 서버 카운팅을 쓴다.

결국 정확한 카운팅은 비용 예측과 장애 예방을 동시에 해결한다. 근사식은 로그·모니터링용으로만 남기고, 실제 호출 경로에는 토크나이저 기반 게이트를 두는 것이 안전하다.