LLM 라우팅 계층 — LiteLLM, OpenRouter, Portkey
공급자 종속(Provider lock-in)은 비용이 큽니다. 서로 다른 도구 호출(tool-calling) 워크로드에는 서로 다른 모델이 어울립니다. 라우팅 게이트웨이(Routing Gateway)는 하나의 API 표면, 재시도, 장애 조치(failover), 비용 추적, 가드레일(guardrail)을 제공합니다. 2026년에는 세 가지 원형(archetype)이 시장을 지배합니다. LiteLLM(오픈 소스 자체 호스팅), OpenRouter(관리형 SaaS), Portkey(프로덕션 등급, 2026년 3월에 오픈 소스로 공개)입니다. 이 강의는 의사결정 기준을 정리하고 표준 라이브러리(stdlib)만 사용한 라우팅 게이트웨이를 단계별로 살펴봅니다.
유형: Learn
언어: Python (표준 라이브러리, 라우팅 + 장애 조치 + 비용 추적기)
선수 학습: Phase 13 · 02 (function calling), Phase 13 · 17 (게이트웨이)
소요 시간: 약 45분
학습 목표
- 자체 호스팅(self-hosted), 관리형(managed), 프로덕션 등급(production-grade) 라우팅 옵션을 구분합니다.
- 공급자 장애가 발생하면 정의된 우선순위에 따라 재시도하는 대체 체인(fallback chain)을 구현합니다.
- 여러 공급자에 걸쳐 요청별 비용과 토큰 사용량(token usage)을 추적합니다.
- 주어진 프로덕션 제약 조건에 대해 LiteLLM, OpenRouter, Portkey 중 무엇을 선택할지 결정합니다.
문제
공급자 라우팅이 중요한 시나리오는 다음과 같습니다.
-
비용. Claude Sonnet은 Haiku보다 3배 비쌉니다. 분류(triage) 작업에는 Haiku로 충분하고, 종합(synthesis) 작업에는 Sonnet이 그만한 값어치를 합니다. 요청별로 라우팅합니다.
-
장애 조치(Failover). OpenAI가 한 시간 동안 장애를 겪습니다. 모든 요청이 실패합니다. 재배포 없이 Anthropic으로 자동 대체(fallback)되기를 원합니다.
-
지연 시간. 실시간 채팅 UI는 빠른 첫 토큰까지 시간(time-to-first-token)이 필요합니다. 배치 요약기는 그렇지 않습니다. 지연 시간 SLA에 맞춰 라우팅합니다.
-
컴플라이언스(Compliance). EU 사용자는 EU 지역(region) 안에 머물러야 합니다. 지역 기준으로 라우팅합니다.
-
실험. 같은 워크로드에서 두 모델을 A/B 테스트합니다. 테스트 버킷(bucket)을 기준으로 라우팅합니다.
이 모든 처리를 통합(integration)마다 손수 짜는 일은 반복적이고 지루합니다. 라우팅 게이트웨이는 하나의 OpenAI 호환(OpenAI-compatible) API를 제공하고 나머지를 알아서 처리합니다.
개념
OpenAI 호환 프록시 형태
모든 도구가 OpenAI 형식을 따릅니다. 라우팅 게이트웨이는 /v1/chat/completions 엔드포인트를 노출하고, OpenAI 스키마(schema)를 받아 내부적으로 Anthropic, Gemini, Cohere, Ollama 등 어떤 백엔드로든 프록시(proxy)합니다. 클라이언트는 그 차이를 신경 쓸 필요가 없습니다.
모델 별칭(Model alias)
코드에서는 claude-3-5-sonnet-20251022 대신 our_smart_model이라고 적습니다. 게이트웨이가 이 별칭을 실제 모델로 매핑합니다. Anthropic이 Claude 4를 출시하면 서버 쪽 별칭만 바꾸면 됩니다. 애플리케이션 코드는 손댈 필요가 없습니다.
대체 체인(Fallback chain)
primary: openai/gpt-4o
on 5xx: anthropic/claude-3-5-sonnet
on 5xx: google/gemini-1.5-pro
on 5xx: refuse
게이트웨이는 이 순서를 설정 파일(config)에 정의합니다. 대체 체인이 비용을 폭발시키지 않도록 재시도(retry)는 정해진 예산(budget) 안에서만 일어납니다.
의미 기반 캐싱(Semantic caching)
동일하거나 거의 동일한 프롬프트는 공급자 대신 캐시에 도달합니다. 반복되는 에이전트 루프(agent loop)에서는 30%에서 60%까지 비용을 절감할 수 있습니다. 키는 임베딩(embedding) 기반이므로, 거의 같은 프롬프트는 같은 캐시 슬롯(slot)을 공유합니다.
가드레일(Guardrails)
게이트웨이 수준에서 다음과 같은 기능을 제공합니다.
- 개인정보 마스킹(PII redaction). 프롬프트를 보내기 전에 정규식(regex) 또는 머신러닝 기반 검사를 통과시킵니다.
- 정책 위반(Policy violations). 금지된 내용이 포함된 프롬프트를 거부합니다.
- 출력 필터(Output filters). 모델이 생성한 결과(completion)에서 유출(leak)을 정리합니다.
Portkey와 Kong은 의견이 분명한(opinionated) 가드레일을 기본 제공합니다. LiteLLM은 가드레일을 선택 기능으로 둡니다.
키별 호출 한도(Per-key rate limits)
API 키 하나가 한 팀에 대응합니다. 키별 예산은 한 팀이 공유 할당량(quota)을 모두 소진하는 일을 막아줍니다. 대부분의 게이트웨이가 이 기능을 지원합니다.
자체 호스팅 vs 관리형 트레이드오프
| 항목 | LiteLLM (자체 호스팅) | OpenRouter (관리형) | Portkey (프로덕션) |
|---|
| 코드 | 오픈 소스, Python | 관리형 SaaS | 오픈 소스 (2026년 3월) + 관리형 |
| 설치 | 프록시 직접 배포 | 가입만 하면 됨 | 둘 다 가능 |
| 공급자 수 | 100개 이상 | 300개 이상 | 100개 이상 |
| 과금 | 자체 키 사용 | OpenRouter 크레딧 | 자체 키 사용 |
| 관측성(Observability) | OpenTelemetry | 대시보드 | 전체 OTel + PII redaction |
| 적합한 경우 | 완전한 제어를 원하는 팀 | 빠른 프로토타이핑 | 컴플라이언스가 필요한 프로덕션 |
데이터 주권을 지키고 싶고 SRE 팀이 있다면 LiteLLM이 유리합니다. 단일 구독만으로 인프라 부담을 없애고 싶다면 OpenRouter가 유리합니다. 가드레일과 컴플라이언스가 즉시 갖춰져야 한다면 Portkey가 유리합니다.
비용 추적
모든 요청은 provider, model, input_tokens, output_tokens를 함께 가집니다. 게이트웨이가 관리하는 가격표(pricing sheet)에서 모델별 토큰 단가를 가져와 곱합니다. 사용자별, 팀별, 프로젝트별로 집계합니다.
MCP와 라우팅
게이트웨이는 LLM 호출과 MCP 샘플링 요청(sampling request)을 모두 라우팅할 수 있습니다. 샘플링 요청의 modelPreferences가 특정 모델을 선호하면, 게이트웨이는 이를 올바른 백엔드로 변환합니다. 이 지점에서 Phase 13 · 17의 MCP 게이트웨이와 이 강의의 라우팅 게이트웨이가 하나의 서비스로 합쳐지기도 합니다.
라우팅 전략(Routing strategies)
- 정적 우선순위(Static priority). 목록의 첫 번째 항목을 사용하고 오류가 나면 다음으로 넘깁니다.
- 부하 분산(Load balancing). 라운드 로빈(round-robin) 또는 가중치 기반 분배입니다.
- 비용 인지(Cost-aware). 지연 시간과 품질 기준을 만족하는 모델 중 가장 저렴한 모델을 고릅니다.
- 지연 시간 인지(Latency-aware). 최근 N분 동안 가장 빠른 응답을 보인 모델을 고릅니다.
- 작업 인지(Task-aware). 프롬프트 분류기(prompt classifier)가 코딩 작업은 한 모델에, 요약 작업은 다른 모델에 라우팅합니다.
사용해 보기
code/main.py는 약 150줄의 라우팅 게이트웨이를 구현합니다. OpenAI 형태의 요청을 받아 공급자별 스텁(stub)으로 변환하고, 우선순위 대체 체인을 실행하며, 요청별 비용을 추적하고, 입력에 개인정보 마스킹(PII redaction)을 적용합니다. 세 가지 시나리오로 실행해 봅니다. 정상 요청, 1차 공급자 장애로 인한 대체, 마스킹으로 잡힌 개인정보 유출(PII leakage)입니다.
살펴볼 지점은 다음과 같습니다.
ROUTES 딕셔너리: 별칭에서 우선순위가 매겨진 실제 공급자 목록으로의 매핑입니다.
- 대체 루프는 5xx 응답에서 다음 공급자로 재시도합니다.
- 비용 추적기는 토큰 사용량에 모델별 요금을 곱합니다.
- 개인정보 마스킹기는 요청을 전달하기 전에 SSN 형태 패턴을 정리합니다.
산출물 만들기
이 강의는 outputs/skill-routing-config-designer.md를 결과물로 남깁니다. 지연 시간, 비용, 컴플라이언스를 포함한 워크로드 프로필(workload profile)이 주어지면, 이 스킬(skill)은 LiteLLM, OpenRouter, Portkey 중 하나를 고르고 그에 맞는 라우팅 설정을 만들어 줍니다.
연습문제
-
(쉬움) code/main.py를 실행합니다. 장애 시나리오를 발생시키고, 대체 동작이 두 번째 공급자에 도달하는지 그리고 비용이 올바르게 귀속되는지 확인합니다.
-
(중간) 의미 기반 캐싱을 추가합니다. 프롬프트의 SHA256 해시를 조회 키(lookup key)로 사용하고, 캐시 적중(cache hit) 시 즉시 응답을 반환하게 만듭니다. 반복 호출에서 절감된 비용을 측정합니다.
-
(중간) "code ..." 형태의 프롬프트는 지능(intelligence)을 우선하는 별칭으로, "summarize ..." 형태의 프롬프트는 속도를 우선하는 별칭으로 라우팅하는 프롬프트 분류기를 추가합니다.
-
(어려움) 팀별 예산을 설계합니다. 각 팀은 월간 지출 상한(spend cap)을 가지며, 상한에 도달하면 게이트웨이가 요청을 거부합니다. 강제 단위(요청별 또는 시간 창 기반)를 선택합니다.
-
(어려움) LiteLLM, OpenRouter, Portkey 문서를 나란히 읽습니다. 각 제품이 가지고 있고 다른 두 제품에는 없는 기능을 하나씩 짚어냅니다.
핵심 용어
| 용어 | 흔한 설명 | 실제 의미 |
|---|
| 라우팅 게이트웨이(Routing gateway) | "LLM 프록시(proxy)" | 여러 공급자 앞에 놓이는 단일 API 표면 계층 |
| OpenAI 호환(OpenAI-compatible) | "OpenAI 스키마를 따른다" | /v1/chat/completions 형태를 받아 어떤 백엔드로든 변환 |
| 모델 별칭(Model alias) | "our_smart_model" | 코드에서 사용하는 이름을 게이트웨이가 실제 모델로 매핑 |
| 대체 체인(Fallback chain) | "재시도 목록" | 실패 시 시도되는 공급자의 순서 있는 목록 |
| 의미 기반 캐싱(Semantic caching) | "프롬프트 임베딩 캐시" | 프롬프트 임베딩을 키로 사용해 거의 동일한 프롬프트가 캐시 적중을 공유 |
| 가드레일(Guardrails) | "입출력 필터" | 개인정보(PII)를 마스킹하고 정책 위반을 거부 |
| 키별 호출 한도(Per-key rate limit) | "팀 예산" | API 키 단위로 적용되는 할당량 |
| 비용 추적(Cost tracking) | "요청별 지출" | 토큰 사용량 × 모델별 가격의 집계 |
| LiteLLM | "오픈 프록시" | 자체 호스팅 가능한 오픈 소스 라우팅 게이트웨이 |
| OpenRouter | "관리형 SaaS" | 크레딧 기반 과금을 사용하는 호스팅형 게이트웨이 |
| Portkey | "프로덕션 옵션" | 가드레일이 기본 내장된 오픈 소스 + 관리형 옵션 |
더 읽을거리