AI 게이트웨이 벤치마킹: GoModel vs LiteLLM vs Portkey vs Bifrost
요약
AI 게이트웨이의 성능을 기능 중심이 아닌 핫 패스(hot path)에서의 효율성 관점에서 비교 분석합니다. LiteLLM, Portkey, Bifrost와 직접 개발한 GoModel을 대상으로 지연 시간, 처리량, 리소스 사용량 및 배포 환경 적합성을 벤치마킹합니다.
핵심 포인트
- AI 게이트웨이는 모든 요청 경로에 위치하므로 런타임 오버헤드가 매우 중요함
- 단순 기능 비교보다 지연 시간, CPU, 메모리, 콜드 스타트 등 리소스 효율성 측정 필요
- GoModel은 Go 언어로 작성되어 가볍고 빠른 성능을 목표로 하는 오픈 소스 게이트웨이임
- 배포 환경(서버리스, 사이드카 등)에 따른 이미지 크기와 메모리 점유율이 핵심 결정 요소임
2025년 10월, 나는 LiteLLM을 기반으로 스타트업을 구축하려고 시도했습니다.
처음에는 명백한 선택지처럼 보였습니다. 많은 제공업체(providers)를 지원하고, OpenAI 호환 API를 갖추고 있었으며, 이미 많은 사람들이 사용하고 있었기 때문입니다. 나는 AI 게이트웨이(AI gateway)를 직접 만들고 싶지 않았습니다. 그 뒤에 있는 제품을 만들고 싶었습니다.
그러다 이를 핫 패스(hot path)에서 실행하기 시작했습니다.
그 지점에서 내 의견이 바뀌었습니다.
게이트웨이는 가끔씩 호출하는 대시보드나 통합용 접착제가 아닙니다. 게이트웨이는 모든 요청(request), 모든 재시도(retry), 모든 스트림(stream), 모든 도구 호출(tool call), 모든 폴백(fallback), 모든 타임아웃(timeout) 위에 자리 잡고 있습니다.
무거운 게이트웨이는 영원히 임대료를 청구합니다.
대부분의 AI 게이트웨이 비교는 이 부분을 놓칩니다. 그들은 제공업체 수, 대시보드, 트레이싱(tracing), 그리고 "1,000개 이상의 모델 지원"에 대해 이야기합니다. 그런 것들도 중요하지만, 공짜는 아닙니다. 게이트웨이가 OpenAI, Anthropic, Gemini, vLLM 또는 다른 무엇인가를 호출하기 전에, 이미 당신의 CPU, 메모리, 콜드 스타트(cold-start) 시간, 그리고 운영 예산을 소모했습니다.
여기서 나는 제품의 전체적인 성숙도를 비교하는 것이 아닙니다. 나는 이 게이트웨이들이 핫 패스(hot path)에서 어떻게 동작하는지를 비교하고 있습니다.
그래서 나는 GoModel을 작성하기 시작했습니다. 이는 OpenAI 호환 API와 명시적인 제공업체 어댑터(provider adapters)를 갖춘, Go 언어로 작성된 작고 가벼운 오픈 소스 AI 게이트웨이이자 AI 컨트롤 플레인(control plane)입니다.
Hacker News에 GoModel을 출시했을 때, 나는 실제적이고 재현 가능한 벤치마크를 약속했습니다. 이 글은 그 후속 작업입니다.
벤치마크 질문은 간단합니다:
각 AI 게이트웨이가 요청 경로(request path)에 위치할 때 얼마나 가벼운가?
그 질문은 전체 벤치마크를 관통합니다: 랜딩 페이지나 기능 매트릭스 대신 지연 시간(latency), 처리량(throughput), 메모리, CPU, 콜드 스타트(cold start), 그리고 이미지 크기로 측정된 GoModel vs LiteLLM vs Portkey vs Bifrost의 비교입니다.
런타임 풋프린트(runtime footprint)가 중요하다
지연 시간(Latency)은 가장 논쟁하기 쉬운 주제입니다. 하지만 그것이 전체 이야기를 다 들려주는 경우는 드뭅니다.
대부분의 실제 LLM 호출은 추론 시간(inference time)이 지배적입니다. 모델이 답변하는 데 2000 ms가 걸린다면, 프록시 오버헤드(proxy overhead)가 5 ms인지 15 ms인지는 핵심적인 이야기가 아닙니다.
핵심적인 이야기는 배포 환경(deployment envelope)입니다:
- 부하가 걸린 상태에서 게이트웨이에 필요한 RAM은 얼마인가?
- 요청당 CPU를 얼마나 소모하는가?
- 코어당 얼마나 많은 요청을 처리할 수 있는가?
- 콜드 스타트(cold-start) 속도는 얼마나 빠른가?
- Docker 이미지 크기는 어느 정도인가?
- 사이드카(sidecar)로 실행할 수 있는가, 작은 VM, 서버리스(serverless), 또는 로컬 모델 근처에서 실행할 수 있는가?
- 핵심 게이트웨이가 실제로 오픈 소스(open-source)인가?
이러한 수치들이 게이트웨이를 원하는 곳에서 실행할 수 있는지 여부를 결정합니다.
압축된 이미지 크기가 372 MB(1.2 GB 압축 해제 시)이고, 유휴 상태에서 기가바이트 단위의 RAM을 사용하며 콜드 스타트에 25 s가 걸리는 것은, 이미지 크기가 16 MB이고 RAM 사용량이 최대 37 MB이며 실행 0.56 s 만에 트래픽을 처리하는 것과는 운영 측면에서 완전히 다른 이야기입니다.
따라서 저는 런타임 풋프린트(runtime footprint)에 주목합니다.
이 벤치마크가 증명하지 않는 것
이 벤치마크는 특정 게이트웨이가 모든 기업에 최선이라는 것을 증명하지 않습니다.
저는 다음 사항들을 측정하지 않습니다:
- 버그 수 또는 전반적인 정확성
- 시맨틱 캐시(semantic cache) 품질
- 트레이싱(tracing) UI 품질
- 가드레일(guardrail) 품질
- 관리자 대시보드
- 제공업체(provider)의 장기적인 유지보수
- 가능한 모든 제공업체별 특화 기능
- 전체 제공업체 수
이러한 요소들은 중요합니다. 그중 일부는 매우 중요합니다.
특히 LiteLLM은 현재 GoModel보다 더 많은 통합 제공업체와 더 많은 게이트웨이 기능을 보유하고 있습니다. 만약 현재 시점에서 최대의 제공업체 커버리지가 최우선 요구사항이라면, LiteLLM이 확실한 강점을 가집니다. 이 벤치마크가 그 사실을 부정하는 것은 아닙니다. 이 벤치마크는 각 게이트웨이를 요청 경로(request path)에 배치했을 때의 런타임 풋프린트를 측정합니다. 실제로 많은 소규모 또는 신규 제공업체들이 이미 OpenAI 호환 API를 노출하고 있으므로, 제공업체의 수가 항상 실질적인 라우팅 커버리지와 일치하는 것은 아닙니다.
이 벤치마크는 더 좁은 범위의 한 가지를 측정합니다: 요청 경로에서의 런타임 및 배포 오버헤드(runtime and deployment overhead).
게이트웨이는 핫 패스(hot path)에 위치하기 때문에 이는 여전히 중요합니다. 높은 요청 볼륨, 로컬 모델, 서버리스 워크로드, 에지(edge) 워크로드 또는 많은 수의 작은 모델 호출을 실행한다면, 오버헤드는 더 이상 이론적인 문제가 아닙니다.
AI 게이트웨이 벤치마크 설정
사람들이 실제로 비교하는 네 가지 AI 게이트웨이를 테스트했습니다:
- GoModel
- LiteLLM
- Portkey
- Bifrost
모든 게이트웨이는 의도적으로 **동일한 즉각적인 모의 백엔드 (instant mock backend)**와 통신하도록 설정했습니다. OpenAI, Anthropic, AWS 네트워킹 또는 무작위 인터넷 지터 (jitter)를 벤치마킹하고 싶지 않았기 때문입니다. 저는 게이트웨이 자체를 격리하여 테스트하고자 했습니다.
각 게이트웨이는 Docker 환경에서 2 vCPU와 4 GiB RAM을 갖춘 AWS c7i.large 인스턴스 위에서 한 번에 하나씩 실행되었으며, 최신 Amazon Linux 2023 AMI를 사용했습니다. 전체 과정은 Terraform으로 구성되어 단 하나의 명령어로 실행되며, 완료 후에는 자동으로 삭제됩니다.
처음에는 프리 티어(free-tier)인 t2.micro에서 이 테스트를 실행했습니다. 비용이 저렴하고 재현하기 쉬웠지만, 더 무거운 게이트웨이들에게는 불공평했습니다. 1 GiB 사양의 머신은 기가바이트 단위의 메모리를 요구하는 게이트웨이를 수용할 수 없어 스와핑 (swapping)이 시작됩니다. 그 시점부터는 게이트웨이가 아니라 호스트 사양이 너무 작다는 것을 벤치마킹하게 되는 셈입니다.
그래서 c7i.large로 옮겼습니다. 여전히 작은 사양이지만, 버스트 가능 (non-burstable)하지 않으며 스와핑이 발생하지 않을 만큼 충분히 큽니다. 또한 이는 LiteLLM 설정을 더 정직하게 만들어 줍니다. LiteLLM은 vCPU당 하나의 워커 (worker)를 권장하는데, 이 머신은 2개의 vCPU를 가지고 있으므로 LiteLLM은 2개의 워커를 할당받습니다. 이를 통해 아주 작은 박스에서 단일 워커에 고정되는 대신, 원래 가져야 할 멀티 코어 (multi-core) 접근 권한을 가질 수 있게 됩니다.
테스트는 다음 여섯 가지 워크로드 (workloads)를 대상으로 했습니다:
- 채팅 완성 (chat completions), 비스트리밍 (non-streaming)
- 채팅 완성 (chat completions), 스트리밍 (streaming)
- 응답 API (Responses API), 비스트리밍 (non-streaming)
- 응답 API (Responses API), 스트리밍 (streaming)
- Anthropic 메시지 (Anthropic messages), 비스트리밍 (non-streaming)
- Anthropic 메시지 (Anthropic messages), 스트리밍 (streaming)
각 워크로드는 동시성 (concurrency) 10에서 8,000개의 요청을 사용하였으며, **게이트웨이 순서를 무작위로 하여 두 번의 시행 (two trials)**을 거쳤습니다. 지연 시간 (latency)은 **시행 전체의 중앙값 (median)**이며, 하나의 노이즈가 섞인 구간이 전체 결과를 대변하지 않도록 p99 값과 함께 최소-최대 범위를 보고합니다.
이를 통계적으로 철저한 연구라고 부르지는 않겠습니다. 이것은 재현 가능한 엔지니어링 벤치마크이며, 테스트 프레임워크 (harness)가 공개되어 있으므로 사람들이 이를 다시 실행하거나, 머신을 변경하거나, 자신만의 워크로드를 추가할 수 있습니다.
수치를 재현하거나 비판하고자 한다면 몇 가지 세부 사항이 중요합니다:
- 처리량(Throughput)은 추론하는 것이 아니라 측정하는 것입니다. 지연 시간(Latency) 실행 결과는 고정된 동시성(Concurrency)에서의 완료된 초당 요청 수(completed-req/s)를 보고하지만, 실제 용량은 각 게이트웨이를 포화 상태(Saturation)까지 몰아붙이는 별도의 동시성 스윕(Concurrency sweep)을 통해 확인됩니다.
- 모든 방언(Dialect)은 측정 전에 웜업(Warmup)을 거칩니다. LiteLLM은 첫 사용 시 일부 방언별 번역 코드를 지연 임포트(Lazily import)합니다. 채팅 전용 웜업만 수행했을 경우 Responses 및 Messages 경로가 실제보다 좋지 않게 나타날 수 있습니다. 이를 방지하기 위해 모든 방언을 웜업했습니다.
- 모든 게이트웨이에서 재시도(Retries)는 비활성화되었습니다. 이번 벤치마크를 위해 GoModel의 서킷 브레이커(Circuit breaker)도 비활성화했습니다. 운영 환경(Production)에서는 업스트림(Upstream)에 문제가 발생한 후 트래픽을 거부하는 것이 올바른 동작입니다. 하지만 포화 상태 벤치마크에서는 처리량 수치를 불공정하게 낮게 만들 수 있습니다.
- LiteLLM은 권장되는 워커(Worker) 수로 실행됩니다. LiteLLM 워커는 사실상 싱글 스레드(Single-threaded)이며, 권장되는 운영 가이드는 vCPU당 워커 1개입니다. 이 장비에서는
2개의 워커를 의미합니다. - 스트리밍(Streaming)은 터미널 마커(Terminal-marker) 또는 유휴 간격(Idle-gap) 감지 방식을 사용합니다. 게이트웨이가 콘텐츠를 스트리밍하지만 터미널 이벤트(Terminal event)를 보내지 않는 경우, 테스트 프레임워크(Harness)는 무한정 대기하는 대신 마지막 바이트까지 측정합니다.
GoModel vs LiteLLM vs Portkey vs Bifrost
대표적인 지연 시간은 비스트리밍(Non-streaming) 채팅 완료(Chat completions) 기준입니다. 모든 리소스 수치는 동일한 장비에서 부하(Load)가 걸린 상태로 측정되었습니다.
| 지표 (Metric) | GoModel | Bifrost | Portkey | LiteLLM |
|---|---|---|---|---|
| 런타임 (Runtime) | Go | Go | Node.js | Python |
| ... |
눈에 띄는 점
GoModel은 가장 낮은 중앙값 지연 시간(Median latency)과 가장 좁은 꼬리 지연 시간(Tail latency)을 기록했습니다: p50 1.8 ms, p99 6.9 ms.
Bifrost는 중앙값 지연 시간에서 2.5 ms로 근소한 차이를 보였으며, 이는 좋은 결과입니다. 하지만 꼬리 지연 시간과 메모리에서 격차가 벌어졌습니다: p99 18.3 ms, 부하 시 피크 RAM(Peak RAM) 143 MB.
Portkey는 이 좁은 범위의 프록시 벤치마크(proxy benchmark) 치고는 예상보다 무거웠습니다. 부하 상황에서 950 req/s를 지속적으로 처리했으며, 피크 RAM(Peak RAM)은 112 MB를 사용했습니다. 이 설정에서는 Anthropic의 /v1/messages 방언(dialect)을 지원하지 않았기 때문에, 워크로드 커버리지(workload coverage)는 4/6로 측정되었습니다. 이는 설정상의 한계로 간주해야 하며, Portkey가 더 완전한 가상 키(virtual-key) 구성에서 Anthropic을 지원할 수 없다는 의미는 아닙니다.
LiteLLM은 이례적인 결과(outlier)를 보였습니다. 권장되는 워커(worker) 수를 사용할 때, 약 2.3 GB의 RAM을 사용했고, 콜드 스타트(cold-start)에 25.5 s가 소요되었으며, 324 req/s를 지속했습니다.
이는 Python이 도덕적으로 나쁘기 때문이 아닙니다. 언어는 배포 환경(deployment envelope)을 변화시킬 때만 중요합니다. 여기서는 변화를 일으킵니다: 메모리 하한선(memory floor), 이미지 크기, 콜드 스타트 시간, 의존성 그래프(dependency graph), 그리고 코어당 처리량(throughput per core)이 변합니다.
최근 발생한 LiteLLM 관련 공급망 사고(supply-chain incident around LiteLLM) 또한 GoModel의 설계 방향에 대한 제 확신을 더해주었습니다. 표준 라이브러리 비중이 높은 작은 Go 바이너리는, 거대한 Python 의존성 그래프에 비해 구조적으로 해당 유형의 문제에 노출될 가능성이 더 낮습니다.
AI 게이트웨이 벤치마크가 포착하지 못하는 것
JSON을 전달하는 것은 어려운 부분이 아닙니다.
어려운 부분은 제공자 드리프트(provider drift)입니다.
OpenAI, Anthropic, Gemini, AWS Bedrock, Azure OpenAI, Groq, xAI, Cerebras, vLLM, 그리고 로컬 서버들은 모두 미세한 방식으로 서로 다릅니다. 그리고 그 방식들은 계속 변합니다. 도구 호출(Tool calling)이 변합니다. 스트리밍(Streaming)이 변합니다. 추론 파라미터(Reasoning parameters)가 변합니다. 이미지 입력이 변합니다. 에러 형식(Error formats)이 변합니다. 속도 제한(Rate-limit) 의미론이 변합니다.
AI 게이트웨이 또는 AI 컨트롤 플레인(control plane)은 마법처럼 작동하려 하지 않으면서도 이러한 변화를 흡수해야 합니다.
GoModel의 베팅은 "인터넷상의 모든 모델 이름을 지원하겠다"가 아닙니다.
그 베팅은 다음과 같습니다:
- 사람들이 실제로 배포하는 제공자들을 지원한다
- 제공자 어댑터(provider adapters)를 명시적으로 유지한다
- OpenAI 호환 요청을 관대하게 수용한다
- 번역이 필요한 것만 번역한다
- 제공자별로 유지되어야 하는 것은 그대로 통과(pass through)시킨다
- 보수적인 OpenAI 호환 응답을 반환한다
같은 이유로, GoModel은 프록시(proxy)가 부착된 대시보드가 아니라, 작은 OpenAI 호환 게이트웨이(gateway)로 시작합니다.
로컬 모델과 vLLM에 이것이 중요한 이유
만약 모든 트래픽이 응답에 몇 초가 걸리는 클라우드 모델(cloud model)로 향한다면, 게이트웨이 오버헤드(overhead)는 학술적인 수준의 문제로 보일 수 있습니다.
로컬 모델(local models)은 계산 방식을 바꿉니다.
만약 AI 게이트웨이를 통해 vLLM, Ollama, LM Studio, llama.cpp, 또는 자체 네트워크상의 작은 특화 모델(specialized models)로 라우팅(routing)한다면, 모델 호출(model call)이 훨씬 더 빠를 수 있습니다. 이 경우 게이트웨이 오버헤드, 콜드 스타트(cold starts), 메모리, 그리고 사이드카(sidecar) 크기가 더 중요해집니다.
제가 GoModel이 작게 유지되기를 원하는 한 가지 이유는, 게이트웨이가 워크로드(workload) 근처에 배치될 수 있을 만큼 충분히 저렴해야 하기 때문입니다.
중립성과 오픈 소스에 관한 참고 사항
Bifrost는 LLM 평가(evaluation) 및 관측성(observability) 플랫폼인 Maxim AI에 의해 구축되었습니다. 이 플랫폼은 많은 모델 제공업체로 라우팅하지만, 게이트웨이는 Maxim의 평가 및 관측성 생태계와도 밀접하게 맞닿아 있습니다. 만약 자신만의 평가 플랫폼을 선택하고 싶거나, 특정 평가 플랫폼으로부터 독립성을 유지하고 싶다면, Bifrost가 귀하에게 적합한 선택인지 확인하십시오. 좋은 소프트웨어라도 여전히 특정 유인(incentives)이 결합되어 있을 수 있습니다. 여기서 "벤더 중립적(Vendor-neutral)"이라는 말에는 별표(*)가 필요합니다.
"오픈 소스(Open-source)" 또한 주의가 필요합니다.
Portkey는 관측성 저장소(observability storage), 대시보드, 멀티 팀 RBAC, 그리고 대규모 시맨틱 캐싱(semantic caching)을 폐쇄형 관리 티어(closed managed tier)에서 제공합니다. Bifrost의 핵심 게이트웨이는 Apache-2.0 라이선스이지만, 엔터프라이즈 에디션(Enterprise edition)에는 폐쇄형 또는 관리형 기능이 추가됩니다. LiteLLM의 프록시 코어(proxy core)는 MIT 라이선스이지만, SSO, 감사 로그(audit logs), 세밀한 액세스 제어(fine-grained access control)와 같은 엔터프라이즈 기능은 독점적인 상용 라이선스 뒤에 있습니다.
GoModel은 현재 오픈 소스입니다. 일부 엔터프라이즈급 AI 컨트롤 플레인(control plane) 기능은 비공개로 유지될 수 있습니다. 핵심 게이트웨이는 이러한 비공개 기능 없이도 유용하게 유지되도록 설계되었습니다.
직접 재현해보기
이 벤치마크는 스스로 검증할 수 있도록 구축되었습니다. AWS 인스턴스를 프로비저닝(provision)하고, 모든 게이트웨이를 동일한 백엔드(backend)에 대해 실행하며, 표를 출력한 뒤 인프라를 파괴(destroy)합니다.
./run.sh
한 가지 주의사항: 이 작업은 프리 티어(free tier)가 아닌 유료 AWS 인프라에서 실행됩니다. c7i.large 인스턴스는 시간당 약 $0.09이며, 실행 후 한두 시간 내에 스스로 파괴(self-destruct)되므로, 안전하게 실행당 $1 미만의 예산을 책정하세요.
만약 KEEP=1을 전달하거나 정리(teardown) 작업이 실패하면, 인스턴스를 파괴할 때까지 계속 비용이 발생하므로 정리 과정을 반드시 재확인하십시오.
결론
제가 GoModel을 시작한 이유는 세상에 또 다른 AI 게이트웨이를 만들고 싶어서가 아니었습니다.
제가 사용하고 싶었던 게이트웨이가 문제의 일부가 되었기 때문에 시작했습니다. 그 게이트웨이는 핫 패스(hot path)에 위치해 있었지만, 핫 패스 소프트웨어처럼 느껴지지 않았습니다. 너무 무겁고, 시작하는 데 너무 느리며, 유지하기에 너무 비싸고, 맡은 작업에 비해 너무 컸습니다.
이 벤치마크(benchmark)는 그러한 좌절감을 수치로 변환한 결과물입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기