LiteLLM으로 멀티 LLM 프록시 게이트웨이 구축하기
여러 팀이 하나의 AI 플랫폼 위에서 동시에 작업하는 조직에서는 모델 선택, API 키 관리, 비용 배분이 복잡하게 얽힙니다.
목차
- 개요
- LiteLLM 아키텍처와 동작 원리
- 프록시 게이트웨이 구축
- 로드밸런싱과 폴백 전략
- 비용 추적과 사용량 관리
- 운영 환경 적용 시 고려사항
- 맺음말
개요
여러 팀이 하나의 AI 플랫폼 위에서 동시에 작업하는 조직에서는 모델 선택, API 키 관리, 비용 배분이 복잡하게 얽힙니다. GPT-4o로 초안을 쓰고, Claude Sonnet으로 검토하고, Gemini Flash로 분류하는 파이프라인이 하나의 서비스 안에 공존할 때, 각 모델 제공자의 API를 개별적으로 호출하는 방식은 금방 한계를 드러냅니다. LiteLLM은 이 문제를 해결하기 위해 등장한 오픈소스 LLM 프록시 게이트웨이로, 단일 OpenAI 호환 엔드포인트 뒤에 100개 이상의 모델을 배치하고 로드밸런싱·폴백·비용 추적을 한꺼번에 처리합니다. 이 글에서는 LiteLLM 프록시를 직접 구성하고, 실제 운영 환경에서 마주치는 장애 허용성과 비용 가시성 문제를 어떻게 해결하는지 구체적으로 살펴봅니다.
문제 배경: 멀티 프로바이더 환경의 복잡성
단일 모델 제공자에 의존하는 구조는 처음에는 단순해 보이지만, 규모가 커질수록 두 가지 위험이 커집니다. 첫째는 벤더 락인입니다. OpenAI API 형식에 맞게 작성된 클라이언트 코드는 Anthropic이나 Google의 SDK로 전환하는 순간 대규모 리팩터링을 요구합니다. 둘째는 단일 장애점입니다. 특정 모델 제공자의 서비스 중단이나 레이트 리밋 초과가 전체 서비스 장애로 이어집니다. 실제로 OpenAI는 2024년 한 해에만 수 차례의 대규모 장애를 기록했으며, 이 시간 동안 대안 없이 OpenAI에만 의존하던 서비스들은 함께 다운됐습니다.
멀티 프로바이더 전략은 이 두 위험을 동시에 완화합니다. 그러나 직접 구현하려면 각 프로바이더 SDK를 통합하고, 요청 형식을 변환하고, 재시도 로직을 직접 작성해야 합니다. 팀 단위로 API 키를 관리하고 사용량을 집계하는 것도 별도 인프라가 됩니다. LiteLLM 프록시는 이 모든 작업을 인프라 레벨에서 처리해 애플리케이션 코드는 OpenAI SDK만 알면 되는 구조를 만들어 줍니다.
기존 방식의 한계
제공자별 SDK를 직접 통합하는 방식은 코드베이스에 추상화 레이어를 추가하는 부담이 있습니다. LangChain이나 자체 래퍼 클래스로 이를 해결하려는 시도도 있었지만, 폴백 로직과 재시도 정책을 애플리케이션 레이어에서 관리하는 한 각 서비스마다 동일한 로직이 중복됩니다. 비용 추적은 더 어렵습니다. 각 프로바이더 대시보드에서 별도로 확인해야 하고, 어떤 팀의 어떤 기능이 얼마를 썼는지 추적하기 위해서는 사용량 로깅 코드를 모든 호출 지점에 삽입해야 합니다. 프록시 게이트웨이는 이 책임을 네트워크 경계로 끌어올려 애플리케이션 코드의 변경 없이 정책을 중앙에서 관리하게 합니다.
LiteLLM 아키텍처와 동작 원리
LiteLLM은 파이썬 라이브러리와 독립 실행형 프록시 서버 두 가지 형태로 배포됩니다. 라이브러리는 litellm.completion() 하나로 100개 이상의 모델을 동일한 인터페이스로 호출하는 얇은 통합 레이어이고, 프록시는 이 라이브러리를 HTTP 서버로 감싸 모든 클라이언트가 네트워크를 통해 공유하는 형태입니다. 실제 조직 규모의 배포에서는 대부분 프록시 모드를 선택합니다.
핵심 컴포넌트 구조
프록시의 내부는 크게 세 레이어로 구성됩니다. 맨 앞에 라우터(Router) 가 있어 들어오는 모델 이름을 실제 프로바이더 엔드포인트로 매핑하고, 로드밸런싱 전략을 실행합니다. 그 뒤에 미들웨어 체인이 있어 인증, 레이트 리밋, 비용 계산을 순서대로 처리합니다. 마지막으로 콜백 시스템이 있어 각 요청의 결과를 Prometheus, Langfuse, Slack 등 다양한 수신처로 비동기 전송합니다.
라우터는 요청을 받으면 설정 파일의 model_list에서 논리 모델 이름에 해당하는 배포 목록을 조회합니다. 배포가 여러 개이면 설정된 전략(라운드로빈, 최소 레이턴시, 최소 비용 등)에 따라 하나를 선택하고, 그 배포의 프로바이더 형식으로 요청을 변환해 전달합니다. 요청 변환은 프로바이더마다 다른 매개변수 이름(max_tokens vs max_output_tokens), 시스템 메시지 위치, 스트리밍 형식 차이를 LiteLLM 내부에서 자동으로 처리하므로 클라이언트는 항상 OpenAI 형식만 사용하면 됩니다.
요청 처리 흐름
클라이언트로부터 요청이 들어오면 프록시는 미들웨어 체인을 순서대로 통과시킵니다. 먼저 Virtual Key 검증으로 요청자를 확인하고, 해당 키의 예산 한도와 레이트 리밋을 확인합니다. 이 단계에서 거부된 요청은 프로바이더까지 나가지 않으므로 불필요한 API 비용이 발생하지 않습니다. 검증을 통과한 요청은 라우터로 넘어가고, 라우터는 선택한 배포에 실제 API 호출을 보냅니다. 응답이 돌아오면 토큰 수를 바탕으로 비용을 계산하고, 콜백 핸들러에 비동기로 전달합니다.
미들웨어 체인을 통과한 뒤에야 실제 API 호출이 발생하는 구조 덕분에, 정책 변경이 애플리케이션 코드와 완전히 분리됩니다.
설정 기반 선언적 구성
LiteLLM 프록시의 핵심 특징은 모든 동작이 config.yaml 하나로 제어된다는 점입니다. 코드를 수정하지 않고 설정 파일만 교체하면 새 모델 추가, 폴백 순서 변경, 예산 재설정이 가능합니다. 이 선언적 구성 방식은 인프라팀이 모델 정책을 중앙에서 관리하면서 개발팀은 프록시 주소만 알면 되는 조직적 분리를 가능하게 합니다. 핫 리로드(litellm --config config.yaml --detailed_debug)도 지원되어 재시작 없이 설정을 반영할 수 있습니다.
프록시 게이트웨이 구축
프록시를 처음 배포할 때는 로컬에서 Docker 컨테이너로 시작하는 것이 가장 빠릅니다. 설정 파일을 마운트하면 컨테이너 이미지를 다시 빌드하지 않아도 모델 목록을 자유롭게 변경할 수 있습니다.
기본 설정과 모델 등록
아래는 OpenAI, Anthropic, Google 세 프로바이더를 등록하고 논리 모델 이름으로 외부에 노출하는 최소 설정입니다. litellm_settings 블록에서 폴백과 재시도 정책을 전역으로 지정하고, 각 배포에서 오버라이드할 수 있습니다.
# config.yaml
model_list:
- model_name: gpt-4o # 클라이언트가 사용하는 논리 이름
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
rpm: 500 # 분당 요청 상한 (레이트 리밋 사전 차단)
- model_name: gpt-4o # 동일 논리 이름에 두 번째 배포 → 로드밸런싱
litellm_params:
model: azure/gpt-4o-prod
api_base: os.environ/AZURE_API_BASE
api_key: os.environ/AZURE_API_KEY
rpm: 1000
- model_name: claude-sonnet
litellm_params:
model: anthropic/claude-sonnet-4-5
api_key: os.environ/ANTHROPIC_API_KEY
rpm: 200
- model_name: gemini-flash
litellm_params:
model: gemini/gemini-1.5-flash
api_key: os.environ/GEMINI_API_KEY
router_settings:
routing_strategy: least-busy # 옵션: simple-shuffle, latency-based, cost-based
num_retries: 3
timeout: 30
litellm_settings:
fallbacks:
- {"gpt-4o": ["claude-sonnet", "gemini-flash"]} # gpt-4o 실패 시 순서대로 폴백
success_callback: ["langfuse"]
failure_callback: ["langfuse", "slack"]
model_name이 동일한 배포가 여러 개이면 라우터가 자동으로 로드밸런싱합니다. 이 방식 덕분에 OpenAI Direct와 Azure OpenAI를 동일 논리 이름으로 묶으면 클라이언트 코드 변경 없이 두 엔드포인트를 함께 쓸 수 있습니다.
Docker 배포와 초기 검증
설정 파일이 준비되면 컨테이너 실행은 한 줄이면 충분합니다. 데이터베이스 없이 인메모리 상태만으로도 기본 프록시 기능은 모두 동작하며, PostgreSQL을 연결하면 Virtual Key 관리와 비용 집계 데이터가 영속됩니다.
# 컨테이너 실행 (인메모리 모드)
docker run -d \
-v $(pwd)/config.yaml:/app/config.yaml \
--env-file .env \
-p 4000:4000 \
ghcr.io/berriai/litellm:main-latest \
--config /app/config.yaml \
--port 4000 \
--detailed_debug
# 동작 확인 — OpenAI SDK를 그대로 사용
curl http://localhost:4000/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-1234" \
-d '{"model": "gpt-4o", "messages": [{"role":"user","content":"ping"}]}'
# 결과: OpenAI 호환 JSON 응답, x-litellm-model-id 헤더로 실제 사용 모델 확인 가능
x-litellm-model-id 응답 헤더에 실제 호출된 배포 이름이 담기므로 어떤 엔드포인트가 응답했는지 확인할 수 있습니다. PostgreSQL을 붙이면 /ui 경로의 관리 대시보드에서 Virtual Key 발급과 팀별 예산 설정이 가능합니다.
Virtual Key로 팀별 접근 제어
Virtual Key는 실제 프로바이더 API 키를 숨기고 조직 내 각 팀이나 서비스에 독립 키를 발급하는 메커니즘입니다. 각 키에 월 예산, 허용 모델 목록, 레이트 리밋을 개별 설정할 수 있어 한 팀의 과다 사용이 다른 팀에 영향을 주지 않습니다.
팀마다 독립 Virtual Key를 발급하면 실제 API 키 노출 없이 세밀한 접근 제어가 가능합니다.
로드밸런싱과 폴백 전략
LiteLLM 라우터가 제공하는 전략은 단순 라운드로빈에서 비용 기반 선택까지 다양합니다. 전략 선택은 서비스의 우선순위에 따라 달라지는데, 레이턴시가 중요한 실시간 서비스와 비용이 중요한 배치 처리는 서로 다른 전략이 적합합니다.
라우팅 전략 비교
| 전략 | 설명 | 적합한 상황 | 주의점 |
|---|---|---|---|
simple-shuffle |
균등 무작위 선택 | 배포가 동등한 경우 | 레이턴시 편차 무시 |
least-busy |
현재 진행 중 요청이 가장 적은 배포 선택 | 동시 요청이 많은 경우 | 단일 배포 과부하 방지 |
latency-based |
최근 P70 레이턴시 기반 가중 선택 | 실시간 챗 서비스 | 콜드스타트 초기 데이터 없음 |
cost-based |
토큰당 비용이 낮은 배포 우선 | 배치 처리, 대용량 | 레이턴시 보장 어려움 |
전략 선택은 단순하게 시작(least-busy)하고, 레이턴시 데이터가 쌓인 뒤 latency-based로 전환하는 점진적 접근이 안전합니다.
폴백 계층 설계
폴백은 두 레벨로 구성됩니다. 모델 수준 폴백은 특정 논리 모델 이름의 모든 배포가 실패했을 때 다른 논리 모델로 전환하고, 컨텐츠 필터 폴백은 프로바이더의 안전 필터에 걸렸을 때 다른 모델로 재시도합니다. 두 폴백을 모두 설정하면 기술적 장애와 정책적 거부 모두를 처리할 수 있습니다.
폴백 체인 설계 시 중요한 점은 비용과 레이턴시의 급격한 상승을 고려하는 것입니다. 저렴한 모델이 실패해 비싼 모델로 폴백되는 구성은 장애 상황에서 오히려 비용이 폭등할 수 있습니다. 일반적으로 동등한 비용대의 모델을 1차 폴백으로, 더 비싸지만 신뢰성이 높은 모델을 2차 폴백으로 두는 계층 설계가 권장됩니다. 폴백 발생 여부는 응답 헤더의 x-litellm-fallback-model로 확인할 수 있어 알럿 기준으로 활용할 수 있습니다.
폴백 순서는 비용 오름차순으로 설계하면 장애 상황의 예산 충격을 최소화할 수 있습니다.
레이트 리밋과 선제적 차단
LiteLLM의 rpm(분당 요청 수)과 tpm(분당 토큰 수) 설정은 실제 프로바이더 API를 호출하기 전에 요청을 차단합니다. 이 선제적 차단은 프로바이더의 429 오류를 받기 전에 처리하므로, 프로바이더 레이트 리밋 임박 신호로 폴백을 먼저 발동시킬 수 있습니다. allowed_fails 설정으로 특정 배포가 연속 실패한 횟수를 넘으면 일정 시간 동안 해당 배포를 비활성화하는 서킷 브레이커도 내장되어 있습니다.
rpm 임계값 기반 선제 폴백은 실제 레이트 리밋 오류를 클라이언트에 노출시키지 않아 사용자 경험을 보호합니다.
비용 추적과 사용량 관리
LLM 비용은 호출마다 다르고, 모델마다 인풋·아웃풋 토큰 단가가 다릅니다. 비용이 어디서 발생하는지 알 수 없으면 예산 초과 원인을 찾기 어렵고, 팀별 차지백도 불가능합니다. LiteLLM은 모든 응답에서 토큰 수를 추출해 내부 가격표와 곱하고, 이를 Virtual Key·팀·사용자 차원으로 집계합니다.
내장 비용 계산 메커니즘
LiteLLM은 공개 가격 데이터베이스를 내장하고 있어 모델 이름만 지정하면 자동으로 달러 비용을 계산합니다. 응답의 usage 필드에서 prompt_tokens와 completion_tokens를 읽어 가격표와 대조하고, 결과를 x-litellm-response-cost 헤더와 콜백으로 전달합니다. 가격표에 없는 사내 배포 모델이나 커스텀 엔드포인트는 config.yaml의 input_cost_per_token·output_cost_per_token으로 수동 지정할 수 있습니다.
| 집계 차원 | 확인 방법 | 활용 |
|---|---|---|
| Virtual Key별 | /key/info API, 관리 UI |
팀별 차지백 |
| 팀별 | /team/info API |
부서 예산 관리 |
| 모델별 | /model/info API |
고비용 모델 파악 |
| 날짜별 | /spend/logs API |
이상 패턴 탐지 |
| 사용자별 | user 필드 전달 시 |
개인별 사용량 |
Langfuse 연동으로 상세 추적
Langfuse는 LLM 관찰성(observability) 플랫폼으로, LiteLLM과 콜백 하나로 연동됩니다. 콜백이 활성화되면 모든 요청의 입력·출력·레이턴시·비용·모델 이름이 Langfuse 프로젝트에 자동 저장됩니다. 특히 metadata 필드를 요청에 포함하면 Langfuse에서 태그와 사용자 ID로 필터링할 수 있어 기능 단위의 비용 분석이 가능합니다.
from openai import OpenAI
client = OpenAI(
api_key="sk-team-search-key", # LiteLLM Virtual Key
base_url="http://localhost:4000" # 프록시 주소
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "검색 쿼리 분류해줘: 파이썬 비동기"}],
metadata={ # Langfuse 태그로 전달
"feature": "search-classify",
"user_id": "u-12345",
"session_id": "sess-abc"
}
)
# response.usage.prompt_tokens → 입력 토큰 수
# response.usage.completion_tokens → 출력 토큰 수
# 응답 헤더 x-litellm-response-cost: 0.000235 (달러)
print(f"비용: ${response.usage.total_tokens * 0.0000025:.6f}")
metadata 딕셔너리는 LiteLLM이 Langfuse에 전달할 때 tags와 user로 매핑됩니다. 이후 Langfuse 대시보드에서 feature:search-classify 태그로 필터링하면 해당 기능이 한 달에 얼마를 썼는지 즉시 확인할 수 있습니다.
예산 초과 알럿과 자동 차단
Virtual Key에 max_budget을 설정하면 LiteLLM이 해당 키의 누적 비용을 추적하고, 한도 초과 시 자동으로 요청을 차단합니다. 이 메커니즘은 오작동으로 무한 루프에 빠진 에이전트가 수백 달러를 소비하는 사고를 예방합니다. budget_duration으로 주기(일·주·월)를 설정하면 자동 리셋도 됩니다.
예산 80% 시점에 알럿을 보내고 초과 시 자동 차단하는 이중 안전망이 비용 사고를 효과적으로 방지합니다.
운영 환경 적용 시 고려사항
로컬 환경에서 잘 동작하던 프록시가 실제 트래픽 아래에서 다른 문제를 드러내는 경우가 많습니다. 상태 관리, 가용성, 비밀 관리 세 영역에서 흔히 마주치는 함정을 미리 파악해 두면 안정적인 운영이 가능합니다.
흔한 실수와 함정
가장 많이 겪는 문제는 Redis 없이 다중 인스턴스를 실행하는 경우입니다. LiteLLM 프록시를 수평 확장할 때 각 인스턴스가 인메모리로 레이트 리밋 카운터를 관리하면, 인스턴스 수만큼 실제 허용치가 늘어납니다. Redis를 router_settings.redis_host에 연결하면 카운터가 공유되어 일관성이 보장됩니다.
두 번째 함정은 폴백 루프입니다. A → B → A로 폴백이 순환하도록 설정하면 하나의 요청이 두 프로바이더를 반복 호출하다 최대 재시도 횟수에 도달합니다. 폴백 체인은 항상 비순환 방향(저비용 → 고비용)으로 설계해야 합니다.
세 번째는 타임아웃 미스매치입니다. 프록시의 timeout: 30이 클라이언트의 연결 타임아웃(예: 10초)보다 길면, 클라이언트는 이미 연결을 끊었는데 프록시는 여전히 프로바이더 응답을 기다립니다. 클라이언트 타임아웃보다 프록시 타임아웃을 짧게 설정해야 불필요한 프로바이더 호출을 막을 수 있습니다.
세 함정 모두 설정 단계에서 방지 가능하며, 운영 전 체크리스트로 만들어 두면 반복 실수를 예방할 수 있습니다.
모니터링과 디버깅
LiteLLM은 Prometheus 메트릭을 /metrics 엔드포인트로 제공합니다. 주목해야 할 지표는 세 가지입니다. litellm_requests_metric은 모델별 요청 수와 성공·실패 분류를 보여주고, litellm_llm_api_latency_metric은 P50·P90·P99 레이턴시를 프로바이더별로 제공합니다. litellm_spend_metric은 누적 비용으로 예산 알럿의 기준 지표입니다.
디버깅 시에는 --detailed_debug 플래그가 모든 요청의 변환 전후를 로그로 출력합니다. 특정 프로바이더로 잘못 라우팅되거나 요청 형식이 변환되지 않는 문제를 추적할 때 유용합니다. 프로덕션에서는 LITELLM_LOG=INFO 환경변수로 레벨을 낮추는 것이 권장됩니다.
| 지표 | 알럿 기준 | 대응 |
|---|---|---|
| P99 레이턴시 > 10초 | 특정 프로바이더 지연 | 해당 배포 비중 축소 |
| 폴백 발생률 > 5% | 1차 배포 불안정 | 용량 증설 또는 교체 |
| 예산 사용률 > 80% | 비정상 사용 가능성 | 호출 패턴 감사 |
| 서킷 브레이커 오픈 | 배포 완전 장애 | 폴백 체인 확인 |
확장과 마이그레이션
트래픽이 증가함에 따라 프록시 자체가 병목이 되지 않도록 주의해야 합니다. LiteLLM 프록시는 기본적으로 비동기 파이썬(FastAPI + uvicorn)으로 동작하며, workers 파라미터로 프로세스 수를 늘릴 수 있습니다. Kubernetes 환경에서는 HPA(Horizontal Pod Autoscaler)를 CPU 사용률 기준으로 설정하면 트래픽 급증에 자동 대응합니다.
기존 서비스를 마이그레이션할 때는 모델 이름 매핑을 점진적으로 적용하는 전략이 안전합니다. 먼저 프록시를 투명 모드(기존 모델 이름을 그대로 통과)로 배포하고, 트래픽 관찰 후 폴백과 로드밸런싱을 단계적으로 활성화합니다. 한꺼번에 모든 기능을 켜면 문제 발생 시 원인 파악이 어렵습니다.
각 단계에서 2주 이상 안정적으로 운영한 뒤 다음 단계로 전환하면 롤백 포인트가 명확합니다.
맺음말
핵심 요약
LiteLLM 프록시는 세 가지 문제를 동시에 해결합니다. 첫째, OpenAI 호환 단일 인터페이스로 모든 LLM 프로바이더를 통합해 클라이언트 코드 변경 없이 모델을 교체하고 확장할 수 있습니다. 둘째, 다중 배포 간 로드밸런싱과 계층형 폴백으로 단일 프로바이더 의존의 가용성 위험을 제거합니다. 셋째, Virtual Key 기반 예산 관리와 Langfuse 연동으로 팀·기능 단위의 비용 가시성을 확보합니다. 세 문제 모두 애플리케이션 코드 수정 없이 config.yaml 변경만으로 제어되는 점이 실제 조직 운영에서 가장 큰 가치입니다.
적용 판단 기준
LiteLLM 프록시 도입을 고려해야 하는 상황은 명확합니다. 두 개 이상의 LLM 프로바이더를 사용하거나 계획 중이고, 여러 팀이 공유 AI 인프라 위에서 개발 중이며, 프로바이더 레이트 리밋이나 장애로 서비스 영향을 받은 경험이 있다면 도입 효과가 높습니다. 반대로 단일 프로바이더를 사용하고 모델 전환 계획이 없으며 호출 규모가 작다면, 프록시 레이어는 불필요한 네트워크 홉과 운영 부담만 더할 수 있습니다. 핵심은 조직의 LLM 사용 복잡도가 단일 서비스의 관리 역량을 넘어서는 시점에 도입하는 것입니다. 그 시점이 되면 직접 만든 추상화 레이어보다 LiteLLM이 훨씬 빠르고 안정적인 출발점이 됩니다.