비용 최적화가이드
비용을 줄이려면 채팅 히스토리를 자르세요: 슬라이딩 윈도우 또는 요약
매 턴 다시 보내는 양을 제한하세요: 마지막 몇 메시지나 짧은 요약을 유지합니다. 50턴 채팅의 토큰 계산과 Python 헬퍼.

지원 봇이 50턴째 대화 중이고, 새 메시지마다 비용이 이전보다 커집니다. API는 아무것도 기억하지 않으므로 코드가 매번 전체 대화를 다시 보냅니다. 해결책은 보내는 양을 제한하는 것입니다. 시스템 프롬프트와 마지막 몇 턴만 유지하거나(슬라이딩 윈도우), 오래된 턴을 짧은 요약으로 바꾸는 것입니다. 아래는 50턴 대화의 계산과 복사해서 쓸 수 있는 헬퍼입니다.
DeepSeek의 멀티 라운드 채팅 가이드(api-docs.deepseek.com, 2026년 11월 1일 확인)는 분명히 말합니다. 서버는 이전 요청의 컨텍스트를 기록하지 않으므로 클라이언트가 매 호출마다 전체 messages 목록을 보냅니다. CheapTokens의 OpenAI 호환 형식도 같은 방식으로 동작합니다. 이게 처음이라면 긴 채팅이 더 비싼 이유와 messages 배열의 동작 방식부터 보세요.
50턴째에 실제로 보내는 것#
400토큰 시스템 프롬프트를 쓰는 지원 봇이 있다고 합시다. 일반적인 턴에서 사용자는 약 60토큰을 쓰고 봇은 약 190토큰으로 답합니다. 한 턴이 히스토리에 250토큰을 더합니다. 이는 가정이니, 자신의 응답에서 usage 필드의 숫자로 바꾸세요.
50턴째에 요청은 시스템 프롬프트, 이전 49턴, 새 메시지를 담습니다. 400 + 49 × 250 + 60 = 12,710 입력 토큰으로 190토큰 답을 얻는 것입니다. 전체 채팅을 합산해 봅시다. 시스템 프롬프트와 새 메시지는 매번 전송됩니다: 50 × 460 = 23,000. 반복되는 히스토리는 250 × 1,225 = 306,250을 더합니다. 합치면 23,000 + 306,250 = 329,250 입력 토큰 대 50 × 190 = 9,500 출력 토큰입니다.
각 요청의 히스토리는 턴마다 하나씩 늘어나므로, 총량은 채팅 길이의 제곱에 비례해 늘어납니다. 50턴에서 100턴으로 가면 반복 히스토리 부분은 대략 네 배가 됩니다.
직접 해보기직접 해보세요: 시스템 프롬프트, 마지막 4턴, 새 메시지만 보낸다면 50턴째 요청은 입력 토큰이 몇 개일까요?정답 보기
1,460(400 + 4 × 250 + 60)입니다. 전체 히스토리로는 12,710입니다. 같은 질문, 같은 답변 길이, 입력은 일부만.
옵션 1: 슬라이딩 윈도우#
아이디어: 항상 시스템 프롬프트를 보내고, 마지막 N턴 외에는 모두 버립니다. 전체 히스토리는 자신의 저장소에 보관하고 보내는 사본만 잘라냅니다.
def trim_history(messages, keep_pairs=4):
"""System prompt + the last keep_pairs turns + the new user message."""
system = [m for m in messages if m["role"] == "system"]
rest = [m for m in messages if m["role"] != "system"]
return system + rest[-(keep_pairs * 2 + 1):]사용자의 새 메시지를 추가한 뒤 호출하세요. keep_pairs=4로는 4개의 user/assistant 쌍에 새 메시지를 더해 9개 메시지가 되고, 슬라이스는 항상 user 메시지에서 시작합니다. 실제 호출에 연결한 모습입니다:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"
history = [{"role": "system", "content": "You are a concise support assistant."}]
def ask(text):
history.append({"role": "user", "content": text})
resp = client.chat.completions.create(
model=MODEL,
messages=trim_history(history),
max_tokens=500,
)
answer = resp.choices[0].message.content
history.append({"role": "assistant", "content": answer})
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)
return answerprint 줄이 유용합니다. 첫 번째 숫자를 보세요. 트리밍이 없으면 매 턴 올라갑니다. 윈도우를 쓰면 채팅이 4턴을 넘는 순간부터 증가가 멈춥니다.

숫자로 보면: 5턴부터 각 요청은 400 + 4 × 250 + 60 = 1,460 입력 토큰입니다. 처음 네 턴은 정상적으로 늘어나며 합계 3,340입니다. 전체 채팅: 3,340 + 46 × 1,460 = 70,500 입력 토큰으로, 전체 히스토리로 보내는 329,250의 약 5분의 1입니다. 출력은 50 × 190 = 9,500로 유지됩니다.

코드에서는 전체 변경이 호출의 인자 하나입니다:
비교하기
한 줄 변경
변경 전
messages=history변경 후
messages=trim_history(history)주의점: 윈도우는 잊어버립니다. 사용자가 40턴째에 "내 주문 번호 뭐였지?"라고 묻는데 그 번호가 3턴에 있었다면, 모델은 그것을 본 적이 없습니다. 저렴한 해결책 두 가지. 이름, 주문 번호, 요금제 같은 안정적인 사실을 자신의 코드에서 채팅에서 뽑아 시스템 프롬프트에 덧붙이세요. 윈도우가 절대 자르지 않는 곳입니다. 아니면 요약을 추가하세요. 다음 옵션입니다.
옵션 2: 오래된 턴의 요약#
오래된 턴을 버리는 대신 압축합니다. 몇 턴마다 방금 윈도우에서 빠져나간 턴들과 현재 요약을 모델에 보내고 새롭고 짧은 요약을 요청합니다. 그런 다음 그 요약을 시스템 메시지에 넣습니다.
def summarize(summary, old_messages):
transcript = "\n".join(f"{m['role']}: {m['content']}" for m in old_messages)
prompt = (
f"Summary so far:\n{summary}\n\nNew turns:\n{transcript}\n\n"
"Rewrite the summary in under 200 words. "
"Keep names, numbers, decisions and open questions."
)
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return resp.choices[0].message.content
def build_messages(history, summary, keep_pairs=4):
system = history[0]["content"]
if summary:
system += "\n\nEarlier in this chat: " + summary
recent = history[1:][-(keep_pairs * 2 + 1):]
return [{"role": "system", "content": system}] + recent요약은 공짜가 아닙니다. 추가 모델 호출입니다. 약 300토큰 요약을 5턴마다 갱신한다고 가정하면(50턴에서 9회), 각 갱신은 약 1,600토큰(이전 요약 + 다섯 턴 + 지시문)을 읽고 300을 씁니다. 안전하게 가려면 5턴부터 모든 요청에 요약을 포함해 세세요(실제로는 첫 갱신 후에 나타나므로 약간 과대평가입니다): 400 + 300 + 4 × 250 + 60 = 1,760 입력 토큰.
채팅 총계: 메인 요청 3,340 + 46 × 1,760 = 84,300 입력 토큰, 요약 호출 9 × 1,600 = 14,400 입력 및 9 × 300 = 2,700 출력. 합쳐서 84,300 + 14,400 = 98,700 입력 및 9,500 + 2,700 = 12,200 출력 토큰입니다.
요약은 순수 윈도우보다 조금 더 비싸고, 그 대가로 모델은 3턴에 무슨 일이 있었는지 여전히 압니다.
세 가지 구성의 비용#
같은 50턴 채팅을 DeepSeek-V4-Flash에서 위 총계로 실시간 가격을 매기면:
가격은 실시간 가격표에서 오므로 요금이 바뀌면 숫자도 갱신됩니다. 순서는 바뀌지 않습니다. 윈도우가 가장 적게 보내고, 요약이 그 사이에 있고, 전체 히스토리가 가장 비쌉니다.
이런 채팅에는 CheapTokens에서 시작할 모델이 DeepSeek-V4-Flash입니다. 380K 컨텍스트 윈도우(트리밍하지 않아도 50턴 채팅이 들어감), 답변당 최대 32,768 출력 토큰, 하루 중 어느 시간이든 하나의 고정 가격, 그리고 입력과 출력을 합쳐 총액으로 OpenRouter보다 저렴합니다. 모델 id는 deepseek-입니다. 윈도우 구성(요청당 평균 입력 1,410토큰, 출력 190, 요청 50회)으로 모델을 비교하고 싶다면 실시간 표는 다음과 같습니다:
| 모델 | 입력 $/1M | 출력 $/1M | 요청당 | 50회 요청 | OpenRouter, 50회 요청 |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.000036 | $0.0018 | $0.0032 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00004 | $0.002 | $0.0063 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.000099 | $0.005 | $0.0594 |
요청당 입력 1,410개 및 출력 190개 토큰입니다. 100만 토큰당 가격은 현재 기준이며 당사 요금제에 따라 함께 변경됩니다. OpenRouter 열은 동일한 작업량에 대한 참고 가격을 보여줍니다.
GLM-5.3-Flash는 390K 컨텍스트, MiniMax-M2.7은 180K로 트리밍된 채팅에는 충분합니다. 현재 가격은 가격 페이지에 있고, 문서에서 첫 요청을 보내는 방법을 보여줍니다.
무엇을 고를까#
윈도우가 기본입니다. 코드 세 줄, 추가 호출 없음, 추가 실패 모드 없음. 지원 봇, 튜터, 역할극처럼 마지막 몇 턴이 대화를 이끌고 시스템 프롬프트가 규칙을 담는 경우에 쓰세요. 사용자가 오래전에 한 말을 다시 언급하는 경우, 예컨대 끝없는 대화 하나를 가진 개인 비서라면 요약을 추가하세요. 윈도우는 모델이 즉각적인 컨텍스트를 여전히 볼 수 있을 만큼 작게, 완전한 질문-답변 교환을 담을 만큼 크게 유지하세요. 애초에 얼마나 들어가는지는 별개의 한도이며 컨텍스트 윈도우란 무엇인가에서 다룹니다.
빠른 확인
사용자가 40턴째에 3턴에서 주어진 주문 번호를 묻습니다. 요약 없이 4턴 윈도우를 씁니다. 무슨 일이 일어날까요?
정답 보기
정답: 3턴이 요청에서 잘렸으므로 모델이 볼 수 없다
API는 상태가 없습니다. 모델은 요청에 있는 것만 보므로, 여전히 필요한 사실은 시스템 프롬프트나 요약에 남아 있어야 합니다.



