여러 LLM 모델을 쓰고, 비용을 추적하고, Rate Limit을 관리하고, 팀별로 접근을 제어하려면 AI Gateway가 필요합니다. 또한 Agent를 구현할 때 LangChain, LangGraph, AutoGen 중 무엇을 선택할지 — 비용·복잡도·사용 목적에 따라 판단 기준이 있습니다.
서비스가 3개이고 모델이 3개라면, 각 서비스가 각 모델 SDK를 직접 쓰면 9개의 통합이 생깁니다.
Gateway가 중간에 있으면 서비스는 Gateway 하나와 통신하고, 모델 변경은 Gateway에서만 합니다.
핵심 기능:
① 통합 비용 추적: 팀/서비스별 토큰 사용량·비용 대시보드
② Rate Limit 통합 관리: 모델별 한도를 Gateway에서 집중 관리
③ Fallback: Claude가 503이면 자동으로 GPT-4o로 전환
④ 모델 A/B 테스트: 트래픽 10%를 새 모델로 흘려보내 품질 비교
| 항목 | LiteLLM | Portkey |
|---|---|---|
| 타입 | 오픈소스 (Self-hosted) | SaaS (Managed) |
| 인터페이스 | OpenAI 호환 API — SDK 교체 없이 모델 변경 | SDK + 웹 대시보드 |
| 비용 | 무료 (서버 운영비만) | 사용량 기반 과금 |
| 주요 기능 | 100+ 모델 지원, Fallback, 로드 밸런싱, 캐싱 | Guardrail, A/B 테스트, 팀 권한, 상세 분석 |
| 적합한 경우 | 인프라 통제권 필요, DevOps 여력 있는 팀 | 빠른 구축, 보안 요구사항 높음, 소규모 팀 |
| Framework | 언어 | 특징 | 선택 기준 |
|---|---|---|---|
| LangChain | Python / JS | RAG, 단순 체인, 풍부한 통합 (100+ 도구) | 단순 RAG 챗봇, 빠른 프로토타이핑 |
| LangGraph | Python / JS | 그래프 기반, 루프·분기·상태 관리 가능 | 복잡한 Multi-Agent, 조건 분기·재시도 필요 |
| AutoGen | Python | Agent 간 대화(채팅) 중심, Microsoft 개발 | Agent들이 서로 토론·협업하는 시나리오 |
| Spring AI | Java | Spring 생태계 통합, ChatClient, VectorStore 추상화 | Java 백엔드 서버에서 LLM 통합 시 |
| 직접 구현 | 모든 언어 | 의존성 없음, 완전한 통제권 | 단순한 단일 LLM 호출, 프레임워크 오버헤드 피하고 싶을 때 |
# config.yaml
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
- model_name: claude-sonnet
litellm_params:
model: anthropic/claude-sonnet-4-6
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: gpt-4o-mini
litellm_params:
model: openai/gpt-4o-mini
api_key: os.environ/OPENAI_API_KEY
# Fallback 설정
router_settings:
fallbacks:
- {"claude-sonnet": ["gpt-4o"]} # Claude 실패 시 GPT로
# 팀별 Rate Limit
team_settings:
- team_id: "backend-team"
max_budget: 100 # 월 $100
tpm_limit: 100000 # 분당 토큰 한도
// Spring AI: Java 백엔드 LLM 통합 표준
@Service
public class AiChatService {
private final ChatClient chatClient;
// 간단한 채팅
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
// RAG 통합
public String chatWithContext(
String question,
List<Document> context) {
String ctx = context.stream()
.map(Document::getContent)
.collect(joining("\n\n"));
return chatClient.prompt()
.system("다음 문서를 참고해서 답변하세요:\n" + ctx)
.user(question)
.call()
.content();
}
// Streaming
public Flux<String> stream(String prompt) {
return chatClient.prompt()
.user(prompt)
.stream()
.content();
}
}
세 레이어로 구성하겠습니다. Gateway 레이어: LiteLLM으로 Claude/GPT/Gemini를 통합 관리합니다. 팀별 예산 제한, 모델 Fallback, 비용 대시보드를 여기서 처리합니다. Service 레이어: 각 봇(CS봇, 검색봇)은 Spring AI로 Gateway와 통신합니다. Semantic Cache(Redis)와 Prompt Cache를 여기서 적용합니다. Observability 레이어: Langfuse로 토큰 사용량·레이턴시·Agent 스텝 수를 추적하고 Grafana에 시각화합니다.
두 가지 경우입니다. 첫째, 단순 RAG나 단일 LLM 호출입니다. LangChain은 추상화 레이어가 많아 디버깅이 어렵습니다. 단순한 경우 직접 HTTP 클라이언트로 API를 호출하는 것이 더 투명하고 유지보수가 쉽습니다. 둘째, Java 환경입니다. LangChain은 Python이 훨씬 성숙합니다. Java 백엔드에서는 Spring AI 또는 직접 Anthropic/OpenAI SDK를 쓰는 것이 현실적입니다. 프레임워크는 복잡성을 숨기는 것이지 없애는 것이 아닙니다 — 사용 전 반드시 어떤 추상화를 하는지 이해해야 합니다.
AI Gateway(LiteLLM)로 멀티 모델을 통합 관리하고, 단순 RAG는 LangChain, 복잡한 Multi-Agent는 LangGraph, Java 백엔드는 Spring AI. 프레임워크는 복잡성을 숨기는 것이지 없애는 게 아니다.