0. 들어가며
| 분야 | 설명 | 관련 키워드 |
|---|---|---|
| 1. Token 생성 & 표현 | 사람과 시스템의 데이터를 AI가 이해할 수 있는 token 단위로 변환하는 기반 기술 → 정보를 어떻게 token으로 바꿀까? |
Tokenizer, Multimodal Tokenization |
| 2. Token 입력 & Context 구성 |
제한된 token budget 안에서 모델이 답변에 필요한 정보만 받도록 구성하는 기술 → 어떤 token을 모델에 넣을까? |
Prompt Engineering, RAG, Agent Memory, Tool Schema |
| 3. Token 절감 & 재사용 | 같은 품질을 유지하면서 token 사용량과 반복 계산을 줄이는 최적화 기술 → token을 어떻게 덜 쓰고 다시 쓸까? |
Compression, Prompt Caching |
| 4. Token 계산 & 추론 최적화 |
token을 처리하고 생성하는 모델 추론 과정을 빠르고 저렴하게 만드는 기술 → token을 어떻게 빠르게 계산할까? |
KV Cache, Speculative Decoding, Batching, Model Routing |
| 5. Token 운영 & 거버넌스 | token을 비용, 보안, 품질 관리의 단위로 삼아 AI 서비스를 운영하는 기술 → token 사용량을 어떻게 관리할까? |
Metering, Quota, Cost Tracking, Evaluation |
이처럼 토큰 기술은 단순히 문장을 쪼개는 Tokenizer에만 머무르지 않고 어떤 정보를 Token으로 바꿀지, 어떤 Token을 모델에 넣을지, 어떻게 줄이고 재사용할지, 어떻게 빠르게 계산할지, 사용량과 비용은 어떻게 관리할지까지 포함하는 AI 운영 최적화 기술로 확장되고 있습니다.
한편 실제 기업 현장에서는 생성형 AI와 AI Agent 활용이 확대되면서 LLM 호출 횟수와 Token 사용량도 함께 증가하고 있습니다. 특히 AI Agent는 하나의 요청을 처리하는 과정에서 여러 차례 LLM을 호출하고 Tool을 사용하기 때문에, 단일 요청에도 많은 Token이 사용될 수 있습니다.
이러한 Token 사용량 증가는 곧 추론 비용과 운영 부담으로 이어질 수 있습니다. 따라서 이제는 단순히 AI를 많이 사용하는 것보다, 필요한 품질을 유지하면서 Token을 얼마나 효율적으로 잘 사용하는가가 중요해졌습니다.
이 글에서는 앞서 살펴본 여러 Token 기술 분야 중에서도 특히 비용과 직접 연결되는 Token 최적화 기술에 초점을 맞춰 이야기하겠습니다.
1. AI Agent Loop 동작과 Context 구성
무엇을 해야할지 판단 → 필요한 파일이나 데이터 찾기 → Tool 실행 → 실행 결과 읽기 → 결과를 바탕으로 다시 판단 → 필요한 경우, 또 다른 Tool 호출
AI Agent의 LLM Context는 사용자의 현재 질문뿐만 아니라 System 지시사항, 대화 이력, 검색 및 RAG 결과, Tool 정의와 Tool 실행 결과 등으로 함께 구성됩니다.
Agent가 작업을 반복할수록 새로운 Tool Result와 검색 결과가 Context에 추가되고, 일부 정보는 이후 LLM 호출에서도 다시 사용되면서 Token 사용량이 점차 누적됩니다.
따라서 Agent의 Token을 최적화하려면 단순히 사용자 Prompt를 줄이는 것만으로는 충분하지 않습니다. Context에 어떤 정보를 넣을지, 얼마나 가져올지, Tool Result를 어떻게 관리할지 등 Agent 전체 실행 단계에서 Token이 사용되는 지점을 함께 살펴볼 필요가 있습니다.
2. AI Agent 실행 단계별 Token 최적화 방법
AI Agent는 실행 단계마다 Token이 사용되는 방식과 증가 원인이 다릅니다. 따라서 실제 적용 시에는 어느 구간에서 Token이 많이 발생하는지 먼저 확인하고, 해당 구간의 원인에 맞는 기법을 선택하는 것이 중요합니다.
| 구간 | Token & 비용이 커지는 원인 |
확인할 질문 |
대표 기법, Tool |
|---|---|---|---|
| 전역 행동 제어 |
불필요한 구현이나 탐색, Tool 호출 -> 후속 작업과 Token 사용 증가 |
이 작업이나 구현이 정말 필요한가? 더 단순하게 처리할 수 있는가? |
Ponytail |
| 01. 입력·Context 구성 |
긴 Prompt, 불필요한 Tool Schema, 전체 File Read, 대규모 Context 등이 LLM 입력에 포함 |
LLM에 꼭 필요한 정보인가? 필요한 부분만 선택하거나 압축할 수 있는가? |
LLMLingua, Progressive Disclosure, Serena, Headroom |
| 02. 추론 최적화 |
동일한 Prefix를 반복 계산, 모든 요청을 고비용 모델로 처리 |
반복되는 계산을 재사용할 수 있는가? 요청 난이도에 맞는 모델을 선택할 수 있는가? |
Prompt Caching, Model Routing |
| 03. Tool 결과 / Context 관리 |
Log, JSON, CLI Output 등 대용량 Tool Result가 Context에 그대로 유입 |
Tool Result 전체를 LLM에 전달해야 하는가? 필요한 결과만 선택 및 압축하거나 Context 밖에서 처리할 수 있는가? |
RTK, Context Mode, Headroom |
| 04. 출력 최적화 |
불필요하게 긴 설명, 반복 및 수식 표현 등으로 Output Token 증가 |
같은 정보를 더 짧고 정보 밀도 높게 전달할 수 있는가? |
Caveman |
3. Token 최적화 기법 및 Tool 소개
3.1. 애초에 불필요한 일을 만들지 않기 - Ponytail
출처. https://github.com/DietrichGebert/ponytail
Token을 줄이는 가장 앞단의 방법은 이미 만들어진 Context를 압축하는 것이 아니라 불필요한 작업 자체가 발생하지 않도록 하는 것입니다.
Coding Agent가 요구사항보다 넓은 범위의 Abstraction, Helper, Configuration 등을 추가하면 코드 생성에 사용되는 Output Token뿐 아니라 이후 File Read, Test, Debug 과정에서 사용되는 Token까지 함께 증가할 수 있습니다.
Ponytail은 이러한 Over-engineering을 줄이기 위한 Coding Agent용 Ruleset입니다.[1]
새로운 구현 시작 전,
정말 필요한가? → 이미 존재하는가? → 표준 기능으로 해결할 수 있는가? → 더 단순하게 구현할 수 있는가? 를 확인=> YAGNI(You Aren't Gonna Need It) 원칙에 가까운 행동 유도
즉, Token을 직접 줄이는 방식이 아니라 Plugin, Skill, Hook 등을 통해 이러한 Ruleset을 Coding Agent의 지시사항에 주입하고, Agent가 코드를 작성하거나 Tool을 사용하기 전에 최소 구현을 우선하도록 행동을 제어하는 방식입니다.
3.2. 모든 Context를 처음부터 넣지 않기 - Progressive Disclosure
출처. Anthropic, Introducing advanced tool use on the Claude Developer Platform
Agent가 LLM을 호출하기도 전에 Context가 커지는 대표적인 원인 중 하나가 Tool Schema입니다.
(Tool Schema는 Tool의 이름, 설명, 입력 Parameter 구조 등 LLM이 Tool을 선택하고 호출하기 위해 필요한 정의 정보를 의미합니다.[2])
Tool이나 MCP Server가 많아질수록 현재 요청에서 사용하지 않을 Tool의 Schema까지 Context에 포함될 수 있습니다.
Progressive Disclosure는 모든 Tool Schema를 처음부터 제공하지 않고, 먼저 최소한의 탐색 정보만 제공한 뒤 실제 필요한 Tool의 상세 Schema를 필요한 시점에 불러오는 방식입니다.[3]
최소 Tool 정보 제공 → 필요한 Tool 탐색 → 상세 Tool Schema 로드 → Tool 호출
핵심은 정보를 압축하는 것이 아니라 필요하지 않은 Tool 정보를 애초에 Context에 넣지 않는 것입니다.
3.3. 파일 전체 대신 필요한 부분만 가져오기 - Serena
출처. https://github.com/oraios/serena
함수 하나를 수정하기 위해 수백~수천 줄의 파일 전체를 읽으면 실제로 필요한 코드보다 훨씬 많은 정보가 Context에 들어갑니다. 이후 해당 내용이 Conversation History에 남으면 뒤따르는 LLM 호출에도 영향을 줄 수 있습니다.
Serena는 Language Server Protocol(LSP)를 활용해 코드를 File이 아니라 Symbol 단위로 검색하고 편집할 수 있도록 하는 Coding Agent용 Toolkit입니다.[4]
Agent 요청 → Serena Tool 호출 → Language Server에서 Symbol 탐색 → 필요한 코드만 반환 → 필요한 경우 해당 Symbol만 편집
단순한 Compression Tool이라기보다, “전체를 읽고 필요한 부분을 찾는 방식”에서 “필요한 부분을 먼저 찾고 필요한 경우에만 주변 Context를 확장하는 방식”으로 Agent의 정보를 탐색하는 방식입니다.
3.4. 가져온 Context 자체를 줄이기 - LLMLingua, Headroom
필요한 정보만 선택적으로 가져오더라도 RAG Chunk, 긴 문서, JSON, Log, Tool Result처럼 가져온 데이터 자체가 큰 경우가 있습니다. 이때는 LLM에 전달하기 전에 Context의 크기 자체를 줄이는 Context Compression을 적용할 수 있습니다.
3.4.1. Token의 정보량을 판단해 덜 중요한 부분 제거 - LLMLingua
출처. https://github.com/microsoft/LLMLingua
Microsoft Research의 LLMLingua는 작은 Language Model을 이용해 Prompt 내 Token의 정보 중요도를 추정하고, 상대적으로 정보량이 낮은 Token을 제거하는 기법입니다.
Original Prompt → Compression Budget 설정 → 작은 LM으로 Token 중요도 계산 → 중요도가 낮은 Token 제거 → Compressed Prompt를 LLM에 전달
LLMLingua는 작은 LM의 Perplexity와 Token 간 조건부 확률을 이용해 Prompt 내 정보의 중복성과 상대적 중요도를 추정합니다. 또한 Prompt 전체를 동일한 비율로 줄이지 않고 Instruction, Example, Context 등에 서로 다른 Compression Budget을 배분한 뒤 Token 단위로 반복 압축하는 Coarse-to-Fine 방식을 사용합니다.[5]
즉, 자연스러운 문장으로 요약하는 것이 아니라, LLM이 문제를 해결하는 데 필요한 정보가 최대한 유지되도록 Prompt 자체를 더 짧게 만드는 방식입니다.
현재는 LongLLMLingua와 LLMLingua-2로 기술이 확장됐으며, LLMLingua-2는 Perplexity 기반 방식에서 더 나아가 학습된 Token Classification 방식으로 압축 대상을 선택하도록 발전했습니다.[6]
3.4.2. 데이터 유형에 맞게 압축하고 필요 시 원문 조회 - Headroom
출처. https://github.com/headroomlabs-ai/headroom
Headroom은 LLM에 전달되는 Tool Result나 Context의 형태와 구조를 파악한 뒤, ContentRouter가 데이터 유형에 적합한 Compressor를 선택해 압축합니다.[7]
Context 입력 → Content Type 감지 → Compressor 선택 → 압축 → LLM 전달
모든 입력을 동일한 방식으로 줄이는 것이 아니라, 예를 들어 JSON은 반복 구조를 활용해 압축하고, Log는 Error나 Stack Trace와 같은 핵심 Signal을 보존하며, Search Result는 관련성이 높은 결과를 중심으로 남기는 등 데이터 특성에 따라 다른 전략을 적용합니다
또한 CCR(Compress-Cache-Retrieve)을 사용하는 경우, 압축 전 원문을 Local Cache에 저장해두고 LLM이 추가 정보가 필요할 때 원문을 다시 조회할 수 있습니다.
즉, headroom은 데이터의 유형과 구조에 따라 압축 방식을 선택하고, CCR 사용 시 필요한 원문을 다시 조회할 수 있도록 구성된 Context Compression Layer입니다.
3.5 Tool Result를 Context에 넣기 전에 줄이기 - RTK, Context Mode
Coding Agent에서는 Tool이 반환하는 결과로 인해 Context가 커질 수 있습니다. 하지만, LLM이 실제 판단에 사용하는 정보는 전체 결과 중 일부인 경우가 많습니다.
3.5.1. Shell Command 단계에서 Output 정제하기 - RTK
출처. https://github.com/rtk-ai/rtk
RTK(Rust Token Killer)는 Coding Agent가 실행하는 Shell Command의 Output을 LLM에 전달하기 전에 정제하는 CLI Proxy입니다.[8]
Headroom처럼 LLM Context에 들어오는 다양한 데이터를 범용적으로 압축하는 방식이 아니라, git, pytest, docker, kubectl 등 Command 종류에 맞는 Filter를 적용해 불필요한 Output을 줄입니다.
Agent의 Shell Command → RTK를 거쳐 실제 Command 실행 → Command별 Filter 적용 → 정제된 Output을 Agent/LLM에 반환
RTK는 Command 종류에 따라 다음과 같은 방식을 사용합니다.
- Filtering: 주석, 공백, boilerplate 등 노이즈 제거
- Grouping: 유사한 Error나 File 정보를 묶어 표현
- Truncation: 필요한 Context를 유지하면서 긴 Output 제한
- Deduplication: 반복되는 정보를 축약
즉, RTK는 Shell Command가 반환한 Tool Result의 크기를 줄여 LLM에 전달되는 Token을 절감하지만,
범용적으로 Tool Result의 내용을 압축하는 것이 아니라, 어떤 Shell Command가 실행되었는지를 기준으로 Command별 Filter를 적용해 불필요한 정보를 제거하고 필요한 Signal 중심으로 정제하는 것 입니다.
Headroom은 LLM에 전달될 데이터의 Content Type을 판별해 적합한 Compressor를 선택한다면(Content-aware Context Compression 방식),
RTK는 실행된 Shell Command의 종류에 맞는 전용 Filter로 CLI Output을 정제합니다.(Command-aware 방식)
3.5.2. Raw Tool Result를 Context 밖에서 처리하고 필요한 결과만 가져오기 - Context Mode
출처. https://github.com/mksglu/context-mode
Context Mode는 Tool Output 자체를 압축하기보다 대용량 Raw Data를 가능한 한 처음부터 LLM Context에 넣지 않고 Sandbox에서 처리하는 방식을 사용합니다.[9]
Agent가 Tool 호출 → Context Mode가 호출을 Sandbox로 Routing → Raw Data를 Sandbox 내부에서 분석, 검색, 필터링 → 필요한 결과만 stdout으로 출력 → 해당 결과만 LLM Context에 전달
또한 원문을 나중에 다시 확인해야 하는 데이터는 SQLite의 Full-Text Search 기능인 FTS5 기반 Knowledge Base에 Indexing하고, 필요할 때 ctx_search를 통해 BM25 기반으로 관련 Chunk만 검색할 수 있습니다.
즉, Context Mode는 Summary Tool 이라기보다 Raw Data를 LLM Context 밖에서 처리하고 필요한 정보만 선택적으로 노출하는 Context Offloading 방식입니다.
3.6. 같은 작업을 더 저렴하게 처리하기 - Prompt Caching, Model Routing
Token Optimization은 반드시 Token 수 자체를 줄이는 것만을 의미하지 않습니다. 반복되는 입력의 계산을 재사용하거나, 요청의 난이도에 맞는 모델을 선택해 동일한 작업을 더 낮은 비용으로 처리하는 방법도 있습니다.
3.6.1. Prompt Caching - 반복되는 Prefix 계산 재사용
AI Agent는 여러 차례 LLM을 호출하면서 System Prompt, Tool Schema, 이전 대화 일부 등 동일한 Prefix를 반복해서 다시 전달하는 경우가 있습니다.
LLM은 입력을 처리하는 Prefill 단계에서 각 Token의 Attention 계산 결과를 KV Cache에 저장합니다. 모델 서빙 엔진의 Prefix Caching은 이전 요청과 동일한 Prefix가 다시 들어오면 해당 KV Cache를 재사용해, 반복되는 Prefix를 처음부터 다시 계산하지 않도록 합니다.
즉, Prompt Caching은 이전 호출과 동일한 Prefix의 처리 결과를 Cache해두고, 이후 동일한 Prefix가 다시 들어오면 이를 재사용하는 방식입니다. 즉, Token 자체를 삭제하는 것이 아니라 같은 입력을 매번 처음부터 다시 계산하지 않도록 해 비용과 Latency를 줄이는 것이 핵심입니다.[10][11]
반복 Prefix → Cache Hit → 기존 계산 재사용 → 나머지 입력만 새롭게 처리
3.6.2. Model Routing - 요청 난이도에 맞는 모델 선택
Model Routing은 모든 요청을 동일한 고성능 모델에 보내는 대신, 요청의 난이도나 특성, 예상 품질 등을 기준으로 적절한 모델을 선택해 전달하는 방식입니다. 예를 들어 상대적으로 단순한 요청은 작고 저렴한 모델로, 높은 성능이 필요한 요청은 고성능 모델로 Routing 할 수 있습니다.[12]
사용자 요청 → Router가 요청의 난이도 & 특성 판단 → 적절한 모델 선택 → 선택된 모델로 LLM 호출 → 응답 생성
즉, Token 수를 직접 줄이는 기술이라기보다, 모든 요청에 가장 비싼 모델을 사용하는 대신, 업무 특성에 맞는 비용·성능의 모델을 선택하는 Cost Optimization 방식 입니다.
3.7. Output Token 줄이기 - Caveman Skill
출처. https://github.com/JuliusBrussee/caveman
LLM이 생성하는 Output Token 역시 비용을 발생시키며, Agent 환경에서는 생성된 응답 일부가 다음 Turn의 Context에 포함될 수 있습니다. 따라서 불필요하게 긴 응답을 줄이는 것 역시 Token 최적화의 한 방법입니다.
Caveman Skill은 Agent의 응답 스타일을 제어하는 Prompt 기반 Skill입니다. 관사, 인사말, 완곡한 표현, 반복 설명 등 핵심 정보와 관련이 적은 표현을 줄이는 대신 기술적 내용, Code, Error Message 등은 유지하면서 더 짧고 정보 밀도가 높은 형태로 응답하도록 유도합니다.[13]
일반 응답 → Caveman Style 적용 → 불필요한 표현 제거 → 짧고 밀도 높은 응답
4. Headroom 솔루션 테스트
4.1 결과
| Task |
Baseline 대비 Agent 전체 Input Token 변화 |
headroom proxy 내부 압축률 |
Task 품질 |
|---|---|---|---|
| 1. 대용량의 반복 로그 처리 : log-summary-data-ranges |
영어 : 약 16.5% 감소 ↓ 한국어 : 약 15.5% 감소 ↓ |
영어 : 약 9.9% 한국어 : 약 5.3% |
영어 : 18/20 한국어 : 19/20 |
| 2. 코드 세부 로직을 이해하고 재구현 : cobol-modernization |
영어 : 약 43.5% 증가 ↑ 한국어 : 약 53.5% 증가 ↑ |
영어 : 약 1.8% 한국어 : 약 1.5% |
영어 : 18/20 한국어 : 19/20 |
| 3. 정확한 데이터와 복구 정보를 식별 필요 : db-wal-recovery |
영어 : 약 4.5% 감소 ↓ 한국어 : 약 15.5% 증가 ↑ |
영어 : 약 1.34% 한국어 : 약 6.1% |
영어 : 19/20 한국어 : 20/20 |
세 Task 모두 Headroom Proxy 내부에서는 일정 수준의 압축이 발생했지만, Agent 전체 Input Token은 Task에 따라 감소하기도 하고 오히려 증가하기도 했습니다.
4.2 정리
이번 테스트에서는 Headroom Proxy 내부에서 압축이 발생하더라도 Agent 전체의 Input Token이 반드시 감소하는 것은 아니었습니다.
대용량 반복 Log를 처리하는 log-summary-data-ranges에서는 영어와 한국어 모두 전체 Input Token이 약 15% 이상 감소했습니다.
반면 코드의 세부 로직을 이해하고 재구현해야 하는 cobol-modernization에서는 Proxy 내부에서 압축이 발생했음에도 오히려 전체 Input Token이 크게 증가했습니다.
db-wal-recovery에서는 영어는 감소하고 한국어는 증가하는 걸 확인했습니다. 즉, 동일한 Task에서도 다른 결과가 나왔습니다.
(다만, Agent는 실행마다 Tool 호출이나 탐색 경로가 달라질 수 있으므로 이번 결과만으로 언어 자체가 차이의 원인이라고 단정하기는 어렵습니다.)
이를 통해 다음과 같은 점을 확인할 수 있었습니다.
- Context Compression의 효과는 Workload에 따라 달라질 수 있습니다.
즉, Compression의 효과는 단순히 데이터 크기만이 아니라
데이터의 구조, Task 특성, 그리고 Agent가 해당 정보를 어떻게 탐색하고 사용하는지에 따라 달라질 수 있습니다.
- Proxy Compression Ratio와 Agent 전체 Input Token 변화는 동일하지 않습니다.
- Token 절감과 Task 품질을 함께 봐야 합니다.
5. 마치며
처음 Token Optimization을 살펴볼 때는 “얼마나 많이 압축할 수 있는가?”가 가장 중요한 질문처럼 보였습니다.
하지만 여러 기술을 조사하고 실제 Agent 환경에서 테스트해보니, Token을 효율적으로 사용하는 방법은 단순한 Compression만으로 설명하기 어려웠습니다.
불필요한 작업을 애초에 만들지 않는 것, 필요한 정보만 Context에 가져오는 것, 가져온 Context와 Tool Result를 줄이는 것, 반복되는 계산을 재사용하는 것, 요청 특성에 맞는 모델을 선택하는 것, 불필요한 Output을 줄이는 것 모두 Agent 실행의 서로 다른 지점에서 Token을 최적화합니다.
실제 Headroom 테스트에서도 같은 Compression 기술을 적용했지만, Task에 따라 Agent 전체 Input Token이 감소하기도 하고 오히려 증가하기도 했습니다.
따라서 가장 중요한 것은 특정 Tool의 공개된 압축률이 아니라, 우리 Agent에서 Token이 어디에서 발생하고 있는지 먼저 파악하고, 해당 지점과 Workload 특성에 맞는 최적화 방법을 적용하는 것 이라고 생각합니다.
또한 Token을 적게 사용하는 것 자체가 최종 목표가 되어서는 안 됩니다. Token, Cost, Quality, Latency와 Cache 효율을 함께 고려해, 필요한 품질을 유지하면서 Task를 더 적은 자원으로 수행하는 것이 실제 Token Optimization의 목표가 되어야 합니다.
앞으로는 다양한 Agent, 언어, 데이터 유형에 대한 반복 실험을 통해 각 최적화 기법이 언제 효과적이고 언제 오히려 불리한지를 구체화하고, 궁극적으로는 Workload 특성에 따라 적합한 Token 최적화 방식을 선택할 수 있는 방향으로 확장해보고자 합니다.
Reference
[1] Ponytail GitHub
[3] Anthropic, Introducing advanced tool use on the Claude Developer Platform.
[4] Serena GitHub
[6] Microsoft Research — LLMLingua Series
[7] Headroom GitHub
[8] RTK GitHub
[10] vLLM Automatic Prefix Caching
[12] RouteLLM GitHub
[13] Caveman GitHub