에이전트 시리즈 (18): 비용 및 성능 최적화 — 더 저렴하고 더 빠르게
요약
AI 에이전트 운영 시 발생하는 비용과 지연 시간을 최적화하기 위한 전략을 다룹니다. 시스템 프롬프트 최적화, 프롬프트 캐싱, 그리고 모델 라우팅을 통해 토큰 사용량과 불필요한 에이전트 루프를 줄이는 구체적인 방법을 제시합니다.
핵심 포인트
- 시스템 프롬프트 최적화는 지연 시간보다 토큰 비용 절감에 효과적임
- 대규모 컨텍스트 사용 시 프롬프트 캐싱(Prompt Caching) 활용 권장
- 모델 라우팅을 통해 단순 쿼리에 대한 에이전트 오버헤드 방지 가능
- 지연 시간 측정 시 통계적 유의성을 위해 충분한 샘플 확보 필요
에이전트의 비용은 어디로 가는가?
에이전트 호출 1회당 비용 내역:
입력 토큰 (Input tokens):
시스템 프롬프트 (System prompt) 고정 — 매 호출마다 비용 발생
도구 스키마 (Tool schemas) 고정 — 등록된 도구당 항목 1개
...
모든 최적화는 두 가지 범주 중 하나에 속합니다: 토큰 수(token count) 감소 또는 대기 시간(wait time) 감소. 각 전략이 실제로 무엇을 제공하는지 정량화하기 위한 네 가지 실험을 진행합니다.
데모 1: 토큰 비용 분석 — 시스템 프롬프트 다듬기
시스템 프롬프트 (System prompt)는 매 호출마다 모델로 전송됩니다. 이는 가장 간과하기 쉬운 고정 비용입니다.
두 가지 버전을 비교합니다:
MINIMAL_PROMPT = "You are a helpful assistant."
# → 6 토큰
...
토큰 수 (Token counts):
Minimal ( 6 tokens): 'You are a helpful assistant.'
Verbose (107 tokens): 'You are an extremely helpful...'
호출당 추가 토큰: 101 tokens
101 토큰은 작게 들릴 수도 있습니다. GPT-4o 입력 가격($2.50 / 1M tokens) 기준으로는:
- 일일 1만 회 호출 → 일일 $0.25 추가 비용
- 일일 100만 회 호출 → 일일 $25, 월 $750 추가 비용
지연 시간(Latency) 측정 (동일 쿼리에 대해 2회 실행):
Agent Run 1 Run 2 Avg Answer
Minimal 6.90s 3.39s 5.15s The current weather in Beijing is 25°C...
Verbose 3.10s 4.21s 3.66s The current weather in Beijing is 25°C...
Verbose 버전이 Minimal 버전보다 평균적으로 낮은 지연 시간을 기록했습니다 — 이는 직관에 어긋나는 결과입니다.
설명: 2개의 샘플은 LLM 지연 시간을 측정하기에 턱없이 부족합니다. API 응답 시간은 서버 부하에 따라 ±50% 이상 차이가 날 수 있습니다. 안정적인 패턴을 확인하려면 최소 10~20개의 샘플과 중앙값(median)이 필요합니다. 여기서 나타난 차이는 순전한 노이즈(noise)입니다.
시스템 프롬프트 다듬기는 지연 시간이 아닌 토큰 비용을 절감합니다. 지연 시간 최적화에는 다른 도구가 필요합니다.
프롬프트 캐싱 (Prompt Caching) (심화): Claude 및 OpenAI API는 명시적인 프롬프트 캐싱을 지원합니다. Claude의 경우:
response = client.messages.create(
model="claude-sonnet-4-6",
system=[{
...
10K개 이상의 토큰을 포함하는 시스템 프롬프트(RAG 결과, 도구 문서, 배경 지식 등)를 사용하는 시스템의 경우, 프롬프트 캐싱 (Prompt Caching)은 활용 가능한 가장 강력한 최적화 방법입니다.
데모 2: 모델 라우팅 (Model Routing) — 단순 쿼리에 대한 에이전트 오버헤드 건너뛰기
핵심 아이디어: 저렴한 분류 (Classification) 호출을 한 번 수행하여 쿼리가 실제로 에이전트를 필요로 하는지 결정합니다. 도구가 필요하지 않은 쿼리는 직접 답변을 받아, 다회차 ReAct 루프를 건너뜁니다.
ROUTING_SYSTEM = """사용자 쿼리를 분류하세요. 오직 한 단어로만 답변하세요:
- "direct": 일반 지식으로 답변 가능한 경우 (실시간 데이터 불필요)
- "agent": 도구 호출이 필요한 경우 (날씨, 제품 가격, 계산 등)"""
...
5개의 테스트 쿼리:
쿼리 경로(Route) 총 소요시간 도구(Tools)
프랑스의 수도는 어디인가요? direct 2194ms []
머신러닝을 한 문장으로 설명해주세요. direct 2011ms []
...
분류 정확도: 5/5. 하지만 수치를 살펴보십시오:
direct쿼리: 총 ~2000ms — 여기에는 라우팅 호출(~1초)과 직접적인 LLM 답변(~1초)이 포함됩니다.agent쿼리: 총 4000–6000ms — 라우팅 호출(~1초)과 전체 에이전트 실행(~3–5초)이 포함됩니다.
라우팅의 숨겨진 비용: 모든 라우팅 결정은 추가적인 LLM 호출을 발생시킵니다. 반드시 에이전트를 거쳐야 하는 쿼리의 경우, 라우팅은 이득 없이 약 1초의 오버헤드만 추가합니다.
라우팅의 투자 대비 효과 (ROI)는 워크로드 내 "도구가 필요 없는 쿼리"의 비율에 달려 있습니다:
만약 쿼리의 40% 이상이 도구를 필요로 하지 않는다면:
라우팅 절감액: (direct_query_count × agent_overhead)
라우팅 비용: (all_queries × routing_call_cost)
...
라우팅 레이어를 배포하기 전에 실제 워크로드 분포를 측정하십시오.
데모 3: 병렬 도구 호출 (Parallel Tool Calls) — 3.0배 속도 향상
두 개 이상의 도구 호출이 서로 독립적이라면, 이를 순차적으로 실행할 이유가 없습니다.
async def fetch_weather_async(city: str) -> str:
await asyncio.sleep(0.1) # 100ms 시뮬레이션된 I/O 지연 시간
...
...
3개 도시 × 100ms 지연 시간, 각 3회 실행:
순차 실행 (Sequential) 평균: 300.4ms (예상치 ~300ms) ✓
병렬 실행 (Parallel) 평균: 101.4ms (예상치 ~100ms) ✓
속도 향상 (Speedup) : 3.0x (66% 더 빠름)
이론이 예측하는 바와 정확히 일치합니다. N개의 독립적인 도구 호출 (tool calls)을 병렬로 수행하면, 지연 시간 (latency)은 N×t에서 t로 감소합니다.
LangGraph는 이를 기본적으로 처리합니다. LLM이 단일 응답 턴 (response turn)에서 여러 개의 tool_calls를 생성하면, create_react_agent는 이를 자동으로 병렬 실행합니다. 별도의 asyncio 상용구 코드 (boilerplate)가 필요하지 않습니다 — 단순히 도구 함수를 async def로 선언하기만 하면 됩니다:
@lc_tool
async def get_weather(city: str) -> str: # ← async 선언
"""도시의 현재 날씨를 가져옵니다."""
...
전제 조건: LLM이 여러 도구 호출이 독립적임을 인식하고, 이를 한 번의 턴에 함께 생성해야 합니다. 성능이 낮은 모델은 여전히 도구들을 하나씩 순차적으로 호출할 수 있습니다.
데모 4: 도구 결과 캐싱 (Tool Result Cache) — 0ms vs 100ms
적용 시점: 짧은 시간 내에 동일한 인자 (arguments)로 동일한 도구가 여러 번 호출될 때 (예: 사용자가 동일한 도시의 날씨를 두 번 묻거나, 다단계 에이전트가 추론 과정의 서로 다른 시점에서 동일한 데이터가 필요할 때).
_cache: dict[str, tuple[str, float]] = {}
CACHE_TTL_S = 60.0
...
6회 호출, 3개의 고유 도시:
도시 (City) 상태 (Status) 시간 (Time) 비고 (Note)
Beijing MISS 100.2ms 1st call
Shanghai MISS 100.2ms 1st call
...
TTL 가이드라인:
| 데이터 유형 | TTL | 이유 |
|---|---|---|
| 날씨 (Weather) | 5–15분 | 변화가 느림; 사용자는 실시간 정밀도가 필요하지 않음 |
| ... |
부수 효과 (side effects)가 있는 도구는 절대 캐싱하지 마세요 (파일 쓰기, 이메일 전송, 데이터베이스 변경 등). 동일한 파라미터로 동일한 호출을 재실행하면 중복된 부수 효과가 발생하게 됩니다.
설계 체크리스트
토큰 최적화 (Token optimization)
- 시스템 프롬프트 (system prompt) 토큰 수를 계산하세요; 모든 문장에 대해 의문을 던지세요 ("이 문장이 정말로 필요한가?")
- 정적 참조 문서 (제품 매뉴얼, API 문서 등)를 RAG 검색 (RAG retrieval)으로 이동시키세요 — 필요할 때만 주입하세요
- 대화 기록 (conversation history)을 최근 10~20회 대화로 제한하세요; 삭제된 내용은 요약하세요
- 대량의 호출 + 큰 시스템 프롬프트가 발생하는 경우 → Claude/OpenAI의 프롬프트 캐싱 (Prompt Caching) ROI를 평가하세요
모델 라우팅 (Model routing)
- 라우터 (router)를 구축하기 전에 도구 (tools)가 필요 없는 쿼리의 비율을 측정하세요
- 라우팅 분류기 (Routing classifier) 프롬프트는 일반적인 '직접 응답/에이전트 분리'가 아니라, 실제 의도 경계 (intent boundary)를 반영해야 합니다
- 라우팅 오버헤드 (추가적인 LLM 호출 1회)를 에이전트 오버헤드 절감 효과와 비교하여 측정하세요
병렬 도구 호출 (Parallel tool calls)
- 도구 함수를
async def로 선언하세요; LangGraph는 독립적인 호출을 자동으로 병렬화합니다 - "반드시 순차적이어야 하는" 도구 (A의 출력이 B의 입력으로 들어가는 경우)와 진정으로 독립적인 도구를 식별하세요
- 멀티 프로바이더 (Multi-provider) 시나리오: 서로 다른 서비스로의 병렬 호출 → 총 지연 시간 (total latency) = 개별 지연 시간의 합이 아닌, 개별 지연 시간 중 최댓값(max)
도구 결과 캐싱 (Tool result caching)
- 멱등성 (idempotent) 도구 (동일한 입력 → 동일한 출력)를 우선시하세요
- 데이터 신선도 (data freshness) 요구 사항에 따라 도구별로 TTL (Time To Live)을 설정하세요; 모든 것에 하나의 TTL을 사용하지 마세요
- 쓰기/부수 효과 (write/side-effect)가 있는 도구는 절대 캐싱하지 마세요
- 프로덕션 환경: 멀티 인스턴스 간 캐시 공유를 위해 인메모리 딕셔너리 (in-memory dict) 대신 Redis를 사용하세요
요약 (Summary)
다섯 가지 핵심 요점:
- 토큰 비용 (Token cost)은 가장 통제 가능한 비용입니다: 시스템 프롬프트 (system prompt), 도구 스키마 (tool schemas), 대화 기록 (conversation history) — 이들은 각각 모델이나 아키텍처를 변경하지 않고도 측정 및 감소가 가능합니다.
- 지연 시간 (Latency) 측정에는 충분한 샘플이 필요합니다: 2회 실행 결과는 오해를 불러일으킬 수 있습니다 (여기서는 verbose 모드가 "더 빨랐음"); 10개 이상의 샘플과 중앙값 (median values)을 사용하여 안정화하세요.
- 모델 라우팅 (Model routing)에는 숨겨진 오버헤드가 있습니다: 라우팅은 쿼리당 하나의 LLM 호출을 추가합니다; 이는 쿼리의 40% 이상이 도구를 필요로 하지 않을 때만 이득이 됩니다.
- 병렬 도구 호출 (Parallel tool calls)은 가장 깔끔한 최적화 방법입니다: N개의 독립적인 호출 → 지연 시간이 N×t에서 t로 단축됩니다; LangGraph는 비동기 도구 함수 (async tool functions)를 통해 이를 기본적으로 지원합니다.
- 캐시 ROI (Cache ROI)는 적중률 (hit rate)에 달려 있습니다: 적중률이 30% 미만이면 캐싱의 복잡성이 이점보다 커집니다; 캐시 구현 자체보다 TTL (Time To Live) 설계가 더 중요합니다.
다음 예고: Harness Engineering — Complete System — 5가지 요소의 소개에서 확장하여, 액션 스페이스 레지스트리 (action space registry), 권한 예산 시스템 (permission budget system), 그리고 완전한 위협 모델 (threat model)을 포함하는 전체 8계층 프레임워크를 다룹니다.
참고 문헌 (References)
- Anthropic Prompt Caching documentation
- LangGraph tool calling concepts
- 이 시리즈의 전체 데모 코드: agent-17-cost-optimization
실제 기업급 워크플로우에서 검증된 AI 에이전트와 기술의 큐레이션 마켓플레이스인 PrimeSkills를 확인해 보세요. 군더더기 없이 실제로 작동하는 것들만 제공합니다.
제 홈페이지에서 더 유용한 지식과 흥미로운 제품들을 찾아보세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기