신뢰성을 희생하지 않고 AI API 비용을 95% 절감한 방법
요약
AI API 비용을 95% 절감하기 위해 모델 선택 대신 계층적 라우팅(Tiered Routing) 아키텍처를 도입한 사례를 소개합니다. 작업 복잡도에 따라 모델을 적절히 배분하는 '모델 적정 규모 산정(Model Right-Sizing)'을 통해 신뢰성을 유지하며 비용을 최적화하는 방법을 다룹니다.
핵심 포인트
- 단일 모델 사용 대신 계층적 라우팅 전략을 통해 비용 최적화
- 작업 복잡도에 맞춘 모델 적정 규모 산정(Right-Sizing)의 중요성
- 프리미엄 모델 사용률을 5% 미만으로 낮추어 비용 극적 절감
- 정확도 하락을 최소화하면서 운영 비용을 효율적으로 관리
사실은 이렇습니다: 저는 신뢰성을 희생하지 않고 AI API 비용을 95% 절감했습니다.
3개월 전, 저희 CFO는 테이블 너머로 스프레드시트를 밀어 넣으며, 왜 우리의 LLM(대규모 언어 모델) 청구액이 실제 제품 트래픽보다 4배나 더 빠르게 증가했는지 설명해 달라고 요청했습니다. 타당한 질문이었습니다. 저에게는 좋은 답변이 없었습니다. 그래서 저는 이후 8주 동안 우리의 추론 계층 (inference layer)을 완전히 해체하고, AWS 상에서 다른 프로덕션 서비스(production service)를 구축하는 방식과 동일하게 — 티어 (tiers), SLA (서비스 수준 협약), 폴백 경로 (fallback paths), 그리고 p99 지연 시간 (p99 latency) 예산과 함께 — 재구축했습니다. 그 결과: 우리의 월간 AI 지출은 공개적으로 밝히지 않을 정도의 금액에서, 마침내 손익계산서 (P&L) 한 줄에 들어갈 만한 수준으로 떨어졌습니다. 그 과정에서 아키텍처 (architecture)는 덜 신뢰할 수 있게 된 것이 아니라, 오히려 더 신뢰할 수 있게 되었습니다.
제가 한 일은 다음과 같습니다. 지금 이 순간에도 똑같은 회의실에 앉아 식은땀을 흘리고 있을 다른 엔지니어들이 있을 것이기에, 이 내용을 기록해 둡니다.
모델 선택이 아닌 계층적 라우팅 (Tiered Routing)부터 시작하라
제가 읽어본 모든 "비용 최적화 (cost optimization)" 블로그 포스트들은 "더 저렴한 모델을 선택하라"는 말로 시작합니다. 그것은 순서가 틀렸습니다. 프로덕션 시스템 (production system)에서 여러분은 하나의 모델을 선택하는 것이 아니라, _라우팅 전략 (routing strategy)_을 선택하는 것입니다. 모델은 하위 단계의 문제입니다. 특정 요청에 대해 0.01달러를 쓸지 10달러를 쓸지를 결정하는 것은 바로 아키텍처입니다.
제가 구축한 라우팅 계층은 다음과 같습니다. 이는 우리 플랫폼의 모든 LLM 호출 전방에서 실행되며, 요청을 분류하고, 이를 처리할 수 있는 가장 저렴한 티어 (tier)로 전달합니다. 오직 가장 어려운 5%의 요청만이 우리의 프리미엄 모델 (premium model)에 도달합니다.
import httpx
import hashlib
import json
...
프로덕션 환경에서 이 패턴은 고객 지원 챗봇의 비용을 월 420달러에서 28달러로 낮추었습니다. 왜냐하면 쿼리의 약 85%는 100만 토큰당 0.01달러인 Qwen3-8B 이상의 것이 전혀 필요하지 않기 때문입니다. 나머지 15%는 표준 티어 (standard tier)를 사용합니다. 프리미엄 티어 (premium tier)는 거의 실행되지 않습니다.
모델 적정 규모 산정 (Model Right-Sizing)은 여전히 가장 큰 레버이다
라우팅 아키텍처가 골격이라면, 여러분은 여전히 올바른 뼈를 골라야 합니다. 모델 적정 규모 산정 (Model right-sizing) — 즉, 작업 복잡도에 맞춰 역량을 매칭하는 것 — 이야말로 진정으로 터무니없는 절감이 발생하는 지점입니다. 저는 개별 요청 클래스(request classes)에서 97% 이상의 절감을 말하고 있는 것입니다.
팀원들이 "왜 모든 것에 그냥 GPT-4o를 사용하지 않나요?"라고 물을 때 제가 공유하는 표는 다음과 같습니다:
| 작업 (Task) | 비용이 많이 드는 선택 | 스마트한 선택 | 절감액 |
|---|---|---|---|
| 단순 채팅 (Simple chat) | GPT-4o ($10/M) | DeepSeek V4 Flash ($0.25/M) | 97.5% |
| ... |
그 분류 행을 다시 읽어보세요. 98.3%입니다. 우리는 감성 분석 (sentiment analysis)을 위해 $0.60/M를 지불하고 있었습니다. 이제 우리는 $0.01/M를 지불합니다. 우리의 평가 세트 (eval set)에 대한 정확도는 1.4포인트 하락했습니다. 아무도 눈치채지 못했습니다. 모델 품질에 대해 저에게 메시지를 보내던 제품 관리자 (product manager)도 더 이상 메시지를 보내지 않습니다.
만약 이 글에서 단 한 가지만 실천한다면, 바로 이것을 하십시오. 작업 유형 (task type)을 키로 하는 MODEL_MAP을 구축하십시오. 엔지니어가 이 맵을 거치지 않고 "그냥 GPT-4o를 호출하는 것"을 불가능하게 만드십시오.
공격적으로 캐싱하되, 올바른 것을 캐싱하라
캐싱 (Caching)은 클라우드 아키텍트 (cloud architect)가 가장 선호하는 레버입니다. 왜냐하면 더 강하게 밀어붙일수록 비용이 적게 들기 때문입니다. 모든 캐시 히트 (cache hit)는 네트워크를 타지 않고, 가용 영역 (availability zone)을 넘지 않으며, p99 테일 (p99 tail)에 기여하지 않는 요청입니다.
비결은 무엇을 캐싱할지 아는 것입니다. 동일한 컨텍스트 (context)를 가진 동일한 프롬프트 (prompts)는 명백한 승리입니다. FAQ 조회, 문서 Q&A, 결정론적인 (deterministic) 모든 것 — 제 경험상 이러한 것들은 통상적으로 50~80%의 캐시율을 기록합니다. 안정적인 시스템 지침 (system instructions)을 가진 가변적 프롬프트 (variable prompts)도 시스템 프롬프트와 정규화된 사용자 쿼리 (normalized user query)를 해싱 (hash)한다면 여전히 캐싱이 가능합니다.
import hashlib
import json
import time
...
실전 현장에서 얻은 몇 가지 운영 노트입니다:
- 작업 유형별 TTL. FAQ 답변은 24시간 동안 캐싱할 수 있습니다. 실시간 데이터 조회는 절대 캐싱해서는 안 됩니다. 하나의 전역 TTL (global TTL)을 사용하지 마십시오.
- 인메모리 (in-memory)가 아닌 분산 캐시 (Distributed cache). 멀티 리전 (multi-region)으로 확장되면, 프로세스 내 딕셔너리 (in-process dict)는 캐시가 아니라 부채 (liability)가 됩니다. 저는 메타데이터 레이어에서만 리전 간 복제 (cross-region replication)를 수행하는 Redis를 세 개의 리전에서 운영하며, 페이로드 캐싱 (payload caching)은 리전별로 수행합니다.
- 네거티브 캐싱 (Negative caching). 모델이 "모르겠습니다"라고 응답한다면, 그것도 캐싱하십시오. 분당 200번씩 똑같은 대답할 수 없는 질문을 다시 던지는 상황을 방지해 줍니다.
일반적인 쿼리에 대한 캐시 히트율 (Cache hit rates) 50–80%는 모든 비용 최적화 보고서에서 볼 수 있는 20–50%의 추가 절감액으로 직결됩니다. 이는 실재하는 수치입니다. 이 목록에서 가장 얻기 쉬운 승리입니다.
프롬프트 압축 (Prompt Compression): 숨겨진 승수
이 방법은 편법처럼 느껴지기 때문에 대부분의 팀이 건너뛰는 부분입니다. 하지만 건너뛰지 마세요. 2,000 토큰의 시스템 프롬프트 (system prompt)를 400 토큰으로 압축하면 DeepSeek V4 Flash 기준으로 요청당 0.024달러를 절약할 수 있습니다. 이를 하루 10,000번의 요청으로 계산하면 단일 워크로드(workload)에서 하루 240달러, 즉 연간 87,600달러를 아끼는 셈입니다.
패턴은 간단합니다. 비싼 모델이 소비할 컨텍스트 (context)를 요약하기 위해 저렴한 모델을 사용하는 것입니다. 이는 끝없이 반복되는 구조(turtles all the way down)이지만 효과적입니다.
def compress_prompt(text: str, target_ratio: float = 0.5) -> str:
if len(text) < 500:
return text
...
저는 운영 환경에서 세 가지를 압축합니다:
- 메인 프롬프트에 들어가기 전의 검색된 RAG 컨텍스트 (Retrieved RAG context)
- 대화가 약 10회 이상 오갈 때의 대화 기록 (Conversation history)
- 문서 업로드 흐름에서의 긴 사용자 입력값
각각의 방법은 독립적으로 후속 호출 (downstream call)의 입력 토큰 비용을 15–30%씩 깎아줍니다. 이들을 함께 쌓으면, 모델 청구서가 머릿속으로 감당 가능한 수준인지 아니면 별도의 대시보드가 필요한 수준인지의 차이를 만들어냅니다.
가능한 곳에는 배치 (Batch) 처리를 하되, 강요하지는 마세요
배치 처리 (Batch processing)는 제가 거의 손대지 않는 지렛대입니다. 그 이유는 다음과 같습니다. 배치는 비용을 위해 지연 시간 (latency)을 맞바꾸는 것인데, 사용자 대상 제품에서는 맞바꿀 수 있는 지연 시간이 없습니다. 20개의 요청을 묶어서 처리하느라 p99 지연 시간이 8초가 된다면, 95%의 비용 절감으로 얻는 감사 인사보다 1점짜리 리뷰를 더 빨리 받게 될 것입니다.
그렇다고 해서 배치 처리가 쓸모없는 것은 아닙니다. 비동기 작업(Asynchronous jobs) — 야간 보고서 생성, 대량 분류, ETL 강화, 사용자 비대면 인덱스를 위한 임베딩 생성 (embedding generation) — 이러한 것들은 순수한 배치 워크로드 (batch workloads)입니다. 이런 작업들은 저렴한 티어 (cheap tier)에서 실행하세요. 모델이 지원한다면 요청들을 하나의 호출로 결합하십시오. 10–20%를 절약할 수 있습니다.
def batch_classify(texts: list[str]) -> list[str]:
"""여러 분류 요청을 하나의 LLM 호출로 결합합니다."""
numbered = "\n".join(f"{i}. {t}" for i, t in enumerate(texts))
...
제가 팀원들에게 주는 경험 법칙(rule of thumb)은 다음과 같습니다: 사용자가 기다리고 있다면 배치(batching)를 하지 마세요. 사용자가 자고 있다면 모든 것을 배치 처리하세요.
관측 가능성(Observability)이 실제 비용 최적화입니다
이 부분은 아무도 블로그 포스트에 쓰지 않는 내용입니다. 보이지 않는 것은 최적화할 수 없습니다.
저는 첫날부터 저희 LLM 게이트웨이에 네 가지 지표를 추가했습니다:
- 티어별 요청당 비용 (Cost per request by tier). p99 지연 시간(latency)과 동일한 대시보드에 표시합니다. 만약 너무 자주 에스컬레이션(escalation)이 발생하여 지연 시간이 증가한다면, 저는 그 현상을 달러 금액 옆에서 바로 확인하고 싶습니다.
- 경로별 캐시 히트율 (Cache hit rate by route). 엔드포인트(endpoint)별로 세분화합니다. 평균 50%의 히트율은 가장 성능이 안 좋은 엔드포인트의 10% 히트율을 숨길 수 있습니다.
- 티어 1에서 티어 3으로의 에스컬레이션 비율 (Escalation rate from tier 1 → tier 3). 이것은 품질의 대리 지표(proxy)입니다. 만약 이 비율이 급증한다면, 프롬프트(prompt)나 입력 데이터 분포(input distribution)에 변화가 생겼음을 의미합니다.
- 고객당 지출액 (Spend per customer). B2B 제품의 경우, 이것이 재무팀이 관심을 갖는 유일한 숫자입니다.
이 지표들이 갖춰지면, 최적화는 분기별 비상 대응(fire drill)이 아니라 매주 수행하는 일상적인 작업이 됩니다. 월요일에 대시보드에서 성능 저하(regression)를 확인하고 수요일까지 수정 사항을 배포할 수 있습니다.
멀티 리전 배포(Multi-Region Deployment)는 생각보다 더 중요합니다
대부분의 AI 비용 관련 논의는 지리적 요소를 무시합니다. 그래서는 안 됩니다. 멀티 리전(multi-region)으로 운영하면 두 가지 현상이 발생합니다:
- 추론(inference)이 사용자에게 더 가까운 곳에서 수행되므로 지연 시간이 개선됩니다. p99가 눈에 띄게 감소합니다.
- 실제 사용 프로필에 따라 서로 다른 리전을 서로 다른 모델 티어로 라우팅(route)할 수 있습니다. 미국의 티어 1은 Qwen3-8B일 수 있지만, 워크로드 분포(workload distribution)가 다르다면 유럽의 티어 1은 완전히 다른 모델일 수도 있습니다.
저는 글로벌 Anycast 엔트리포인트 (entrypoint)를 사용하여 세 개의 리전 (region)에 걸쳐 글로벌 API 게이트웨이 (Global API gateway)를 운영하고 있습니다. 장애 조치 (Failover)는 자동으로 이루어집니다. 저의 SLO (Service Level Objective)는 99.9%의 가동 시간 (uptime)이며, 세 개의 리전에 걸쳐 운영하는 비용은 대략 하나의 리전에 백업을 두고 운영하는 비용과 비슷합니다. 왜냐하면 저렴한 모델들이 그만큼 저렴하기 때문입니다. 라우팅 (routing) 작업을 완료하고 나면 신뢰성 (reliability) 향상은 사실상 비용이 들지 않습니다.
현재 청구 비용의 모습
절감액을 구체적인 수치로 나타내면 다음과 같습니다. 모델의 적정 규모 산정 (model right-sizing)만으로도 90%를 절감할 수 있습니다. 여기에 계층적 라우팅 (tiered routing)을 추가하면
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기