LLM 에이전트 파이프라인 토큰 비용 50% 줄이기: 요약 에이전트 vs 청크 주입 vs 프롬프트 캐싱 실전 비교
10단계짜리 에이전트 파이프라인을 처음 프로덕션에 올렸을 때, 단일 요청 하나에 $0.80이 청구됐다. 하루 1,000건 요청이면 월 $24,000. 파이프라인 자체는 잘 돌아갔지만, API 비용이 사업 모델을 위협하고 있었다. 원인을 파보니 답은 단순했다 — 매 요청마다 이전 대화 전체, 시스템 프롬프트, 검색 결과가 통째로 반복 전송되고 있었다.
이 글은 LangChain, LlamaIndex, 또는 직접 API를 호출해 멀티스텝 에이전트를 운영 중인 개발자를 위한 실전 가이드다. 컨텍스트 압축의 세 가지 핵심 전략 — 요약 에이전트, 청크 주입, 프롬프트 캐싱 — 을 실행 가능한 코드와 함께 비교한다. 세 전략을 계층적으로 조합하면 토큰 비용을 50~90% 절감할 수 있다.
핵심 개념
왜 에이전트 파이프라인에서 컨텍스트가 폭증하는가
LLM API는 매 요청마다 입력 토큰 전체에 비용을 청구한다. 에이전트가 10단계를 실행할 때 1단계의 결과가 2단계의 입력에, 2단계의 결과가 3단계의 입력에 누적되면 — 마지막 단계의 입력 크기는 모든 이전 단계의 합이 된다. 여기에 세 가지 구조적 문제가 겹친다.
| 원인 | 설명 | 위험 |
|---|---|---|
| 누적 컨텍스트 | 이전 대화 전체가 매 요청마다 재전송 | 단계 수에 비례해 비용 폭증 |
| 컨텍스트 윈도우 한계 | 모델의 최대 토큰을 초과하면 에이전트 실패 | 서비스 중단 |
| 중간 손실 (Lost in the Middle) | 컨텍스트가 길수록 핵심 정보 집중도 저하 | 품질 저하 |
컨텍스트 압축(Context Compression) 은 단순 텍스트 줄이기가 아니다. 선택적 청크 드롭, 의미 보존 요약, KV 캐시 재사용을 포괄하는 에이전트 메모리 관리 전략이다.
세 전략 한눈에 비교
| 전략 | 핵심 아이디어 | 비용 절감 | 구현 복잡도 | 정보 손실 위험 |
|---|---|---|---|---|
| 요약 에이전트 | 대화 이력을 주기적으로 요약본으로 교체 | 최대 90% | 낮음 | 높음 |
| 청크 주입 | 쿼리 관련 청크만 벡터 DB에서 선택 주입 | 40%+ | 높음 | 낮음 |
| 프롬프트 캐싱 | 반복되는 고정 컨텍스트를 서버 측 재사용 | 50~90% | 매우 낮음 | 없음 |
실전 적용
예시 1: 요약 에이전트 — 슬라이딩 윈도우 요약
대화가 임계치(예: 8,000 토큰)에 도달하면 별도 LLM 호출로 핵심을 압축한다. 원본 6,000 토큰 이력 → 500 토큰 요약으로 90% 압축이 가능하다.
from anthropic import Anthropic
client = Anthropic()
def summarize_history(messages: list[dict], max_tokens: int = 8000) -> list[dict]:
"""누적 메시지가 임계치를 넘으면 요약본으로 압축한다."""
# 토큰 수 추정 (실제 구현에서는 tiktoken 등으로 정확히 계산)
estimated_tokens = sum(len(m["content"].split()) * 1.3 for m in messages)
if estimated_tokens < max_tokens:
return messages
# 최근 2개 메시지는 유지, 나머지를 요약
recent = messages[-2:]
to_summarize = messages[:-2]
summary_response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="당신은 대화 요약 전문가입니다. 핵심 사실, 결정 사항, 맥락만 보존하여 간결하게 요약하세요.",
messages=[
{
"role": "user",
"content": f"다음 대화를 500토큰 이내로 요약하세요:\n\n{str(to_summarize)}"
}
]
)
summary_text = summary_response.content[0].text
# 요약본을 첫 메시지로 교체
return [
{"role": "user", "content": f"[이전 대화 요약]\n{summary_text}"},
{"role": "assistant", "content": "요약된 맥락을 파악했습니다. 계속하겠습니다."},
*recent
]
# 에이전트 루프 예시
messages = []
for step in pipeline_steps:
messages = summarize_history(messages) # 매 단계 전 압축 체크
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
messages=messages + [{"role": "user", "content": step}]
)
messages.append({"role": "user", "content": step})
messages.append({"role": "assistant", "content": response.content[0].text})| 측면 | 결과 |
|---|---|
| 6,000 토큰 이력 → 요약 | ~500 토큰 (92% 압축) |
| 추가 LLM 호출 비용 | 요약 1회 ≈ $0.002 (Sonnet 기준) |
| 세부 정보 손실 | 요약 품질에 따라 5~20% |
예시 2: 청크 주입 — 계층화 RAG 압축
LangChain의 ContextualCompressionRetriever를 사용한다. 선택(저비용 필터) → 추출(고비용 LLM) 순으로 적용하여 비용과 정확도를 모두 잡는다.
from langchain_anthropic import ChatAnthropic
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor, LLMChainFilter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
llm = ChatAnthropic(model="claude-sonnet-4-6")
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings)
# 1단계: 관련 없는 문서 전체를 저비용으로 제거
filter_compressor = LLMChainFilter.from_llm(llm)
# 2단계: 남은 문서에서 쿼리 관련 문장만 추출 (고비용이지만 이미 걸러진 후)
extractor_compressor = LLMChainExtractor.from_llm(llm)
# 계층화: filter 먼저, extract 나중
from langchain.retrievers.document_compressors import DocumentCompressorPipeline
pipeline_compressor = DocumentCompressorPipeline(
transformers=[filter_compressor, extractor_compressor]
)
compression_retriever = ContextualCompressionRetriever(
base_compressor=pipeline_compressor,
base_retriever=vectorstore.as_retriever(search_kwargs={"k": 10})
)
# 사용 예시
query = "프롬프트 캐싱 적용 방법"
compressed_docs = compression_retriever.get_relevant_documents(query)
# 10개 문서 검색 → 쿼리 관련 핵심 문장만 반환 (평균 40~60% 토큰 감소)청크 선택 기준을 직접 제어하고 싶다면 유사도 점수 기반 필터를 추가한다.
from langchain_core.documents import Document
def filter_by_similarity(docs_with_scores: list[tuple], threshold: float = 0.75) -> list[Document]:
"""코사인 유사도 임계치 이하 문서 제거 (BM25 점수와 조합 가능)"""
return [doc for doc, score in docs_with_scores if score >= threshold]
# 벡터스토어에서 유사도 점수와 함께 검색
docs_with_scores = vectorstore.similarity_search_with_score(query, k=10)
filtered_docs = filter_by_similarity(docs_with_scores, threshold=0.75)예시 3: 프롬프트 캐싱 — Anthropic cache_control
동일한 시스템 프롬프트나 긴 문서를 반복 전송할 때 가장 강력하다. 캐시 쓰기는 1.25배 비용이지만, 캐시 읽기는 0.1배 — 단 1회 재사용으로 비용이 회수된다.
import anthropic
client = anthropic.Anthropic()
# 긴 시스템 프롬프트나 문서를 캐싱 (최소 1,024 토큰 필요)
SYSTEM_PROMPT = """당신은 코드 리뷰 전문가입니다...
[2,000 토큰 이상의 상세한 가이드라인]
"""
def analyze_with_cache(code_snippet: str) -> str:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"} # 5분 TTL 캐시
}
],
messages=[{"role": "user", "content": f"다음 코드를 리뷰해주세요:\n{code_snippet}"}]
)
# 캐시 히트율 확인
usage = response.usage
print(f"캐시 읽기 토큰: {usage.cache_read_input_tokens}")
print(f"캐시 쓰기 토큰: {usage.cache_creation_input_tokens}")
print(f"일반 입력 토큰: {usage.input_tokens}")
cache_hit_rate = usage.cache_read_input_tokens / (
usage.cache_read_input_tokens + usage.cache_creation_input_tokens + usage.input_tokens
) * 100
print(f"캐시 히트율: {cache_hit_rate:.1f}%")
return response.content[0].text
# 동일 시스템 프롬프트로 반복 호출 — 2번째 요청부터 캐시 히트
for code in code_snippets:
result = analyze_with_cache(code)TypeScript에서는 LangChain의 미들웨어로 기존 코드를 거의 수정하지 않고 적용할 수 있다.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
// 2,000 토큰짜리 시스템 프롬프트를 캐싱
const CACHED_SYSTEM = `당신은 기술 문서 작성 전문가입니다...
[상세 가이드라인 — 최소 1,024 토큰]`;
async function generateWithCache(userPrompt: string): Promise<string> {
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 2048,
system: [
{
type: "text",
text: CACHED_SYSTEM,
cache_control: { type: "ephemeral" },
},
],
messages: [{ role: "user", content: userPrompt }],
});
const usage = response.usage as any;
console.log(`캐시 읽기: ${usage.cache_read_input_tokens ?? 0} 토큰`);
return response.content[0].type === "text" ? response.content[0].text : "";
}실제 절감 사례:
| 시나리오 | 캐싱 전 | 캐싱 후 | 절감율 |
|---|---|---|---|
| PDF 50개 반복 분석 | $3.00 | $0.15 | 95% |
| 6인 팀 8주 Claude 사용 | $2,400/월 | $680/월 | 72% |
| 2,000토큰 시스템 프롬프트, 10회/시간 | 기준 | 1/8 비용 | 87.5% |
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 요약 에이전트 | 구현 직관적, 컨텍스트 윈도우 문제 근본 해결, 대화 흐름 자연스럽게 유지 |
| 청크 주입 | 정확도 유지(필요 정보만 포함), 대규모 문서 처리 가능, 다른 전략과 조합 가능 |
| 프롬프트 캐싱 | 최고 비용 효율성(최대 90%), 지연 시간 최대 85% 감소, 코드 변경 최소화 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 요약 에이전트 | 세부 정보 영구 손실 위험 | 원본 이력을 별도 스토리지에 보관, 중요 사실은 구조화된 형태로 추출 |
| 요약 에이전트 | 요약용 추가 LLM 호출 비용 | 소형 모델(Haiku) 사용, 임계치를 높여 호출 빈도 감소 |
| 청크 주입 | 벡터 DB 운영 오버헤드 | 관리형 서비스(Pinecone, Weaviate Cloud) 사용 |
| 청크 주입 | Indirect Prompt Injection 취약점 | 검색된 청크를 신뢰 경계 내에서 샌드박싱 |
| 프롬프트 캐싱 | 최소 1,024 토큰 이상 필요 | 짧은 프롬프트는 시맨틱 캐싱(Redis) 조합 |
| 프롬프트 캐싱 | 컨텍스트 변경 시 캐시 무효화 | 자주 변경되는 부분을 프롬프트 끝으로 이동 |
실무에서 가장 흔한 실수
- 세 전략을 동시에 도입하는 것 — 어느 전략이 비용 절감에 기여했는지 측정 불가능해진다. 반드시 하나씩 순차적으로 적용하고, 각 단계에서
usage메트릭으로 효과를 측정한 뒤 다음 전략으로 넘어가라. - 청크 크기를 고정값으로 설정하는 것 — 코드는 작은 청크(512토큰), 서사형 문서는 큰 청크(1,500토큰)가 효과적이다. 단일 청크 크기는 어느 도메인에서도 최적이 아니다.
RecursiveCharacterTextSplitter로 콘텐츠 타입별 전략을 분리하라. - 캐시 히트율을 모니터링하지 않는 것 —
usage.cache_read_input_tokens를 추적하지 않으면 캐시가 실제로 작동하는지 알 수 없다. 히트율이 50% 미만이라면 프롬프트 구조를 재검토해야 한다 — 자주 바뀌는 부분이 캐싱 대상 앞에 위치하고 있을 가능성이 높다.
마치며
에이전트 파이프라인의 토큰 비용 문제는 모델 교체가 아니라 컨텍스트 관리 전략으로 해결된다. 요약 에이전트는 구현이 쉽지만 정보 손실이 있고, 청크 주입은 정확도가 높지만 인프라 복잡도가 따라오며, 프롬프트 캐싱은 비용 효율이 최고지만 고정된 컨텍스트에만 유효하다. 프로덕션에서 세 전략을 계층적으로 조합하면 50~90% 절감이 현실적으로 가능하다.
지금 바로 시작하는 3단계:
- 이번 주 — 프롬프트 캐싱 적용: 기존 에이전트의 시스템 프롬프트에
cache_control: {"type": "ephemeral"}한 줄 추가.usage.cache_read_input_tokens로 히트율 측정. 코드 변경 최소, 즉각적인 비용 절감 효과. - 다음 주 — 요약 에이전트 추가: 대화 이력이 8,000 토큰을 초과할 때 소형 모델(claude-haiku-4-5)로 요약 압축 적용. 1주 데이터로 요약 품질 평가 후 임계치 조정.
- 이번 달 — 청크 주입 도입: 문서 검색이 포함된 에이전트에
ContextualCompressionRetriever적용. 유사도 임계치(0.75)와 계층화 파이프라인으로 정확도와 비용 두 마리 토끼를 잡는다.
다음 글: Anthropic의 공식 컨텍스트 엔지니어링 프레임워크 — Write / Select / Compress / Isolate 4전략을 실제 멀티에이전트 시스템에 적용하는 방법
참고 자료
- Context Compression Techniques: Reduce LLM Costs by 50% | SitePoint
- How I Reduced LLM Token Costs by 90% | Medium
- Automatic Context Compression in LLM Agents | AI Forum Medium
- Acon: Optimizing Context Compression for Long-horizon LLM Agents | arXiv
- Effective Context Engineering for Agents | Anthropic
- Context Engineering for Agents | LangChain Blog
- Prompt caching 공식 문서 | Anthropic
- LLMLingua 공식 사이트 | Microsoft
- How xMemory cuts token costs | VentureBeat
- LongLLMLingua Prompt Compression Guide | LlamaIndex
- Don't Break the Cache: Prompt Caching for Long-Horizon Agentic Tasks | arXiv
- AI Agent Token Cost Optimization: Complete Guide | fast.io
- Chunking Strategies for RAG | Weaviate
- Prompt Caching vs Semantic Caching | Redis