AI 게이트웨이란 무엇인가? (그리고 우리가 그것이 절실히 필요하다는 것을 깨달은 한 주)
요약
AI 게이트웨이는 애플리케이션과 LLM 제공업체 사이에서 라우팅, 인증, 비용 추적, 가드레일 등을 중앙 집중식으로 관리하는 미들웨어 계층입니다. 본문은 비용 급증 및 보안 문제를 해결하기 위해 기존의 분산된 SDK 방식에서 게이트웨이 우선 설정으로 전환한 사례를 다룹니다.
핵심 포인트
- AI 게이트웨이는 LLM 트래픽 특화 미들웨어 역할을 수행함
- 라우팅, 인증, 속도 제한, 비용 추적 등을 중앙에서 관리 가능
- 비용 급증 및 보안 감사 문제를 방지하기 위한 필수 요소
- 토큰 기반 과금 및 스트리밍 응답 등 LLM 고유 특성 처리
요약 (TL;DR)
- AI 게이트웨이 (AI gateway)는 애플리케이션 코드와 LLM 제공업체 사이의 미들웨어 (middleware) 계층입니다. 라우팅 (routing), 인증 (auth), 속도 제한 (rate limiting), 비용 추적 (cost tracking) 및 가드레일 (guardrails)을 한곳에서 중앙 집중식으로 관리합니다.
- 통제 불능의 비용 급증, 모델 실패로 인한 무음 에러 (silent errors), 통과할 수 없는 보안 감사와 같이 특정한 문제가 발생하기 전까지는 아마 필요성을 느끼지 못할 것입니다.
- 우리는 약 3개월에 걸쳐 흩어져 있던 SDK와 공유된 API 키 방식에서 게이트웨이 우선 (gateway-first) 설정으로 전환했습니다. 이 포스트에서는 무엇이 변했는지, 그리고 우리가 무엇을 다르게 할 것인지에 대해 다룹니다.
6개월 전, 우리는 기능적으로 엉망인 상태였습니다. 우리는 세 가지 LLM 제공업체를 사용하고 있었습니다. 고객용 채팅을 위한 OpenAI, 내부 문서 요약을 위한 Anthropic, 그리고 배치 분류 (batch classification) 작업을 위한 자체 호스팅 Llama 모델이었습니다. 각 모델은 고유한 SDK를 가지고 있었습니다. 각 모델은 고유한 API 키를 가지고 있었으며, 해당 서비스를 마지막으로 실행한 사람의 컴퓨터에 있는 .env 파일에 저장되어 있었습니다. 각 모델은 약간의 변형이 있는 채로 서비스 간에 복사-붙여넣기 된 고유한 속도 제한 (rate limiting) 로직을 가지고 있었습니다.
아직 아무도 심각한 사고를 겪지 않았을 때 작동하는 방식 그대로, 일단 작동은 했습니다.
사고는 어느 화요일에 찾아왔습니다. 일주일에 한 번 실행되어야 할 백그라운드 작업 (background job)이 실수로 매분 실행되도록 예약되었습니다. 이 작업은 GPT-4o를 호출하고 있었습니다. 우리는 새벽 2시에 비정상적인 신용카드 결제에 대한 Slack 알림이 울렸을 때 이를 인지했습니다. 누군가 작업을 중단했을 때, 우리는 약 4시간 만에 340달러를 소진했습니다. API 키에는 지출 한도가 없었습니다. 토큰 사용량 (token usage)에 대한 알림도 없었습니다. 작업에는 속도 제한이 없었습니다. 이 세 가지 공백 모두 우리가 알고 있었지만 우선순위를 두지 않았던 것들이었습니다.
그 주에 우리는 AI 게이트웨이를 제대로 살펴보기 시작했습니다.
AI 게이트웨이란 실제로 무엇인가?
가장 간단한 정의는 다음과 같습니다: AI 게이트웨이(AI gateway)는 애플리케이션 코드와 LLM 제공업체(LLM providers) 사이에 위치하는 미들웨어 계층(middleware layer)입니다. 모든 LLM 요청은 이를 거쳐가며, 게이트웨이는 각 서비스마다 매번 다시 구현해야 했을 횡단 관심사(cross-cutting concerns)들을 처리합니다: 라우팅(routing), 인증(authentication), 속도 제한(rate limiting), 비용 추적(cost tracking), 캐싱(caching), 폴백(fallbacks), 가드레일(guardrails).
제가 이해하기 가장 쉬웠던 비유는 나머지 마이크로서비스 스택(microservices stack)을 위한 API 게이트웨이(API gateway)라는 점입니다. 만약 REST 서비스의 인증과 속도 제한을 처리하기 위해 Kong이나 AWS API Gateway를 설정해 본 적이 있다면, AI 게이트웨이는 동일한 역할을 수행하되 특히 LLM 트래픽에 특화되어 있습니다. LLM 트래픽은 일반적인 API 게이트웨이가 깔끔하게 처리하기 어려운 고유한 특성(토큰 기반 과금(token-based pricing), 스트리밍 응답(streaming responses), 가변적인 지연 시간(variable latency), 컨텍스트 윈도우(context windows))을 가지고 있기 때문입니다.
아키텍처(Architecturally) 측면에서, 이는 일반적으로 다음과 같은 요소들을 포함합니다:
- 정의된 규칙(지연 시간, 비용, 폴백 체인 등)에 따라 요청을 적절한 모델로 안내하는 라우팅 엔진(routing engine)
- 속도 제한, 지출 한도 및 액세스 제어를 위한 정책 계층(policy layer)
- 요청, 응답, 토큰 사용량 및 비용을 기록하는 관측성 스택(observability stack) — 이상적으로는 사용자 및 팀 단위의 세밀한 수준(granularity)까지 지원
- 동일하거나 의미론적으로 유사한 프롬프트(prompts)에 대해 불필요한 API 호출을 방지하는 캐싱 계층(caching layer)
중요한 점은 이 중 어떤 것도 애플리케이션 코드 내에 존재하지 않는다는 것입니다. 이는 자체적인 설정을 가진 별도의 계층이므로, 애플리케이션 코드를 수정하거나 배포(deployment)를 수행하지 않고도 라우팅 규칙을 변경하거나 새로운 지출 한도를 적용할 수 있음을 의미합니다.
이것이 실제로 해결하는 문제들
구체적인 기능들을 살펴보기 전에, 문제 상황을 명확히 하는 것이 도움이 됩니다. 우리가 직면했던 문제들은 다음과 같습니다:
1. 관리되지 않는 API 키(Unmanaged API keys)
네 개의 .env 파일에 네 개의 API 키가 있었습니다. 엔지니어가 팀을 떠날 때, 우리는 그들의 개인 키는 무효화했지만 공유 서비스 키는 무효화하지 못했습니다. 어떤 서비스가 해당 키를 사용하고 있는지 완전히 확신할 수 없었기 때문입니다. 게이트웨이 (Gateway)는 실제 제공자 키 (Provider keys)를 보유하는 유일한 주체가 됨으로써 이 문제를 해결합니다. 애플리케이션 서비스는 범위가 지정된 가상 키 (Scoped virtual keys)를 사용하여 게이트웨이에 인증합니다. 액세스 권한을 취소해야 하는 경우 가상 키를 취소하면 됩니다. 그러면 기반이 되는 제공자 키는 온전하게 유지되며 변경할 필요가 없습니다.
2. 비용 없는 가시성 (Zero cost visibility)
우리는 Anthropic과 OpenAI 대시보드를 통해 월간 지출액을 알고 있었습니다. 하지만 어떤 팀이나 서비스가 그 지출의 어느 부분을 차지하는지는 전혀 알지 못했습니다. 비용이 상승했을 때, 그 원인을 파악할 수 없었습니다. 팀별 및 서비스별 비용 추적 기능이 있는 게이트웨이를 도입하자 다음 달에는 다음과 같은 상세 내역을 확인할 수 있었습니다: 분류 작업 (42%), 고객 채팅 (31%), 내부 요약 (19%), 기타 (8%). 갑자기 우리는 어디를 최적화해야 할지 알게 되었습니다.
3. 지출 제한 없음 (No spending limits)
화요일의 사건. 더 말할 필요도 없습니다. 게이트웨이를 사용하면 API 키별, 팀별, 서비스별로 엄격한 토큰 또는 지출 제한을 설정할 수 있습니다. 제한에 도달하면 월말에 청구서가 날아오는 대신 요청에 속도 제한 (Rate-limit) 에러가 발생합니다.
4. 모델 장애 시의 조용한 실패 (Silent failures on model outages)
지난 3월 OpenAI에 부분적인 장애가 발생했을 때, 우리의 고객 채팅은 그냥... 조용히 실패했습니다. 요청은 에러를 반환했고, 프론트엔드에는 일반적인 메시지가 표시되었으며, 우리는 알림이 아닌 사용자 보고를 통해 이 사실을 알게 되었습니다. 폴백 라우팅 (Fallback routing) 기능이 있는 게이트웨이가 있었다면 자동으로 Anthropic이나 우리가 자체 호스팅하는 모델로 전환하여 서비스를 유지했을 것입니다. 우리는 폴백 로직 없이 단순히 직접적인 SDK 호출만 하고 있었습니다.
5. 보안 감사 (The security audit)
이것은 팀 외부에서 발생한 이슈였습니다. 보안 팀에서 검토를 진행한 후, 우리가 완전히 답변할 수 없었던 두 가지 질문을 던졌습니다. "지난 90일 동안 어떤 사용자가 어떤 모델 호출을 트리거했는지에 대한 감사 로그(audit log)를 보여줄 수 있습니까?" 그리고 "프로덕션 자격 증명(production credentials)이 개발자의 로컬 환경에서 접근할 수 없도록 어떻게 보장합니까?" 우리는 두 질문 모두 깔끔하게 답변하지 못했습니다. 요청 수준의 로깅(request-level logging)과 중앙 집중식 키 관리(centralised key management) 기능을 갖춘 게이트웨이는 이 두 가지 문제에 대한 인프라 차원의 해답입니다.
"라우팅 (routing)"이 실제로 의미하는 것
모호하게 들리지만 실제로 매우 유용하다는 것이 밝혀진 기능 중 하나는 바로 라우팅(routing)입니다.
단순히 "이 요청을 OpenAI로 보내라"는 수준이 아니라, 지능적인 라우팅을 의미합니다. 이해할 가치가 있는 몇 가지 모드가 있습니다.
지연 시간 기반 라우팅 (Latency-based routing): 게이트웨이는 설정된 제공업체(provider)들의 응답 시간을 지속적으로 모니터링합니다. 특정 제공업체의 지연 시간(latency)이 급증하면, 자동으로 가장 빠른 곳으로 라우팅합니다. 이는 여러 지역(region)에 걸쳐 동일한 모델의 여러 배포본을 사용할 때 특히 유용합니다.
가중치 기반 로드 밸런싱 (Weighted load balancing): 제공업체 간의 트래픽을 백분율로 나눌 수 있습니다. 우리는 새로운 모델을 테스트할 때 이 기능을 사용했습니다. 요청의 10%를 새 모델로 라우팅하여 지표를 관찰하고, 신뢰도가 높아짐에 따라 점진적으로 비율을 조정했습니다. 코드 변경 없이 설정(config) 업데이트만으로 가능했습니다.
폴백 체인 (Fallback chains): 우선순위 순서를 정의합니다. 기본 모델을 사용할 수 없거나 속도 제한(rate-limited)에 걸리면, 차선책을 시도하고, 그다음은 삼선책을 시도합니다. 애플리케이션 관점에서는 요청이 성공한 것으로 처리되므로, 폴백(fallback)이 발생했다는 사실을 전혀 알 수 없습니다.
비용 기반 라우팅 (Cost-based routing): 중요도가 낮은 작업에는 더 저렴한 모델로 라우팅합니다. 우리는 결국 분류(classification) 작업을 더 작고 저렴한 모델로 라우팅하고, 진정으로 필요한 작업에만 GPT-4o를 사용하게 되었습니다. 게이트웨이는 개별 엔지니어가 모든 서비스에서 비용을 의식하며 선택하도록 맡기는 대신, 중앙에서 이 정책을 강제합니다.
캐싱 (Caching): 우리가 과소평가했던 기능
우리는 캐싱을 정확히 일치하는 중복 제거(exact-match deduplication)에 사용할 것으로 예상했습니다. 즉, 두 사용자가 동일한 프롬프트를 보내면 캐시된 응답을 반환하는 방식입니다. 유용하지만 실제로는 그렇게 흔하지 않았습니다.
우리가 예상하지 못했던 것은 시맨틱 캐싱(semantic caching)이 얼마나 유용한가 하는 점이었습니다. 의미적으로 유사한 프롬프트 — 동일하지는 않지만, 약간 다르게 같은 것을 요청하는 경우 — 설정할 수 있는 임계값 이상의 유사성 점수가 나오면 캐시된 응답을 반환합니다. 요약 작업 부하(summarisation workload)의 경우, 상당 부분의 요청이 캐시 결과를 반환할 만큼 의미적으로 충분히 유사하다는 것을 발견했습니다. 이는 출력 품질에 아무런 변화 없이 실제 비용 절감 효과를 가져옵니다.
주요 설정 결정 사항은 캐시 만료(cache expiry, 캐시된 응답이 유효한 기간)와 유사성 임계값(similarity threshold, '충분히 유사하다'는 것은 어느 정도의 유사성을 의미하는가?)입니다. 이 두 가지는 튜닝할 가치가 있습니다. 기본 설정은 보수적이므로, 작업 부하를 이해하게 되면 보통 더 공격적으로 조정할 수 있습니다.
가드레일(Guardrails): 가장 많은 팀들이 필요할 때까지 건너뛰는 부분
가드레일은 AI 게이트웨이 설정의 일부로, 엔지니어링 문제라기보다는 '규정 준수 문제'처럼 느껴져서 미뤄지는 부분이기도 합니다. 하지만 사실 둘 다입니다.
가드레일은 요청이 모델로 전송되기 전에(입력 가드레일, input guardrails) 그리고 응답이 애플리케이션에 반환되기 전에(출력 가드레일, output guardrails) 실행되는 정책입니다. 일반적인 사용 사례는 다음과 같습니다:
- PII 감지: 개인 식별 정보(Personally Identifiable Information, PII)가 환경을 벗어나거나 응답에 나타나기 전에 제거하거나 마스킹합니다. 고객 데이터를 처리하는 경우 필수적입니다.
- 콘텐츠 모더레이션: 안전 정책을 위반하는 입력이나 출력을 필터링합니다.
- 프롬프트 인젝션 감지: 주입된 지침을 통해 모델의 동작을 조작하려는 시도로 보이는 요청을 플래그 지정하거나 차단합니다. 특히 사용자 생성 콘텐츠가 프롬프트에 포함되는 경우 매우 중요합니다.
TrueFoundry가 이를 처리하는 방식은 기본적인 기능에 대해 외부 자격 증명이 필요 없는 사전 구축된 통합(pre-built integrations)을 통한 것이며, 더 구체적인 요구 사항을 위해 Azure Content Safety, AWS Bedrock Guardrails, OpenAI Moderations 또는 Google Model Armor를 연결할 수 있는 옵션을 제공합니다. 가드레일(guardrails)을 검증(validate) 모드(검사, 플래그 지정, 선택적 차단) 또는 변형(mutate) 모드(검사 및 수정 — 거부하기보다 교체를 원하는 개인정보(PII) 삭제(scrubbing)에 유용함)로 실행할 수 있습니다.
이에 대한 제 생각을 바꾼 지점은 다음과 같습니다: 가드레일은 단순히 규정 준수(compliance)만을 위한 것이 아닙니다. 외부 콘텐츠를 검색하여 컨텍스트(context)에 넣는 에이전트(agents)를 구축하게 되면, 제3자 콘텐츠를 통한 프롬프트 인젝션(Prompt injection)은 실제적인 엔지니어링 리스크가 됩니다. 모델에 도달하기 전 검색된 콘텐츠에 대해 실행되는 가드레일이 올바른 아키텍처적 해답입니다. 애플리케이션 계층에서 입력을 정화(sanitise)하려고 시도하는 것이 아닙니다.
우리가 TrueFoundry를 선택하게 된 이유
우리는 몇 가지 옵션을 평가했습니다. LiteLLM이 우리가 가장 먼저 시도한 것이었습니다. 오픈 소스이고 MIT 라이선스이며, 오후 만에 여러 제공업체에 걸쳐 통합된 엔드포인트(unified endpoint)를 구축할 수 있기 때문에 명백한 시작점입니다. 우리는 이를 약 6주 동안 실행했습니다. 우리가 겪은 문제점은 다음과 같습니다: SSO 통합이 불가능했습니다(규정 준수를 위해 Okta가 필요했습니다). 또한 우리에게 필요했던 팀별 예산 집행(budget enforcement) 기능은 엔터프라이즈 라이선스에 포함되어 있었습니다. 모델과 라우팅 규칙(routing rules)이 추가됨에 따라 YAML 설정도 다루기 힘들어졌습니다.
결국 우리는 TrueFoundry의 AI Gateway를 선택했습니다. 우리의 평가에서 중요했던 몇 가지 세부 사항은 다음과 같습니다:
아키텍처(Architecture): 게이트웨이는 인증(auth), 속도 제한(rate limiting) 및 라우팅 결정을 위해 완전히 인메모리(in-memory)에서 실행되므로, 핫 패스(hot path)에서 외부 DB 조회(lookups)가 발생하지 않습니다. 설정은 NATS를 통해 컨트롤 플레인(control plane)으로부터 동기화됩니다. 이는 거버넌스(governance) 규칙을 추가하더라도 게이트웨이 지연 시간(latency)이 저하되지 않음을 의미합니다. 벤치마크 결과에 따르면 1 vCPU에서 풀 로드(full load) 시 추가 지연 시간이 10ms 미만인 350+ RPS를 보여주었으며, 이는 우리가 자체 테스트에서 확인한 결과와 일치했습니다.
키 관리 (Key management): 개발자는 게이트웨이에서 관리하는 제공업체 자격 증명(credentials)에 매핑되는 가상 키(virtual keys)를 받습니다. 실제 OpenAI 및 Anthropic 키는 시크릿 매니저(secrets manager)를 절대 벗어나지 않습니다. 새로운 개발자를 온보딩(onboarding)한다는 것은 새로운 가상 키를 발급하는 것을 의미하며, 오프보딩(offboarding)은 이를 취소하는 것을 의미합니다. 단 한 번의 동작으로 즉각적인 효과를 볼 수 있습니다.
팀별 예산 (Per-team budgets): 사후 지출 알림이 아니라 요청 경로(request path)에서 강제됩니다. 한도에 도달하면 요청은 속도 제한(rate-limit) 에러를 반환합니다. 덕분에 새벽 2시에 Slack 알림을 받는 일은 더 이상 발생하지 않았습니다.
자체 호스팅 모델 지원 (Self-hosted model support): 우리는 OpenAI 및 Anthropic 트래픽과 동일한 게이트웨이를 통해 온프레미스(on-prem) Llama 배포 환경으로 라우팅합니다. 동일한 관측성(observability), 동일한 비용 귀속(cost attribution), 동일한 속도 제한(rate limiting)을 적용할 수 있습니다. 이는 자체 호스팅 모델 인프라에 대한 가시성이 없는 Portkey와의 가장 큰 차이점이었습니다.
배포 (Deployment): 우리는 이를 VPC 내부에서 실행합니다. 전체 컨트롤 플레인(control plane)이 우리 인프라 내에 머물러 있으며, 이는 우리 보안 팀이 데이터 거주성(data residency) 문제를 깔끔하게 해결하는 데 필요했던 사항이었습니다.
솔직한 트레이드오프(tradeoff)로서 지적하고 싶은 점은 다음과 같습니다: TrueFoundry는 LiteLLM보다 설정할 것이 더 많습니다. Kubernetes 네이티브(Kubernetes-native) 방식이므로, K8s 환경이 없다면 초기 작업량이 더 많습니다. 또한 Portkey의 프롬프트 관리 UI는 설정 파일을 건드리지 않고 프롬프트를 반복 개선하려는 비엔지니어들에게 진정으로 더 낫습니다. 이들은 평가하기 전에 알아둘 만한 실제적인 차이점입니다.
모든 것을 바꾼 한 줄의 설정 변경
모든 것이 맞아떨어진 순간은 우리 서비스 설정에 다음 내용을 추가했을 때였습니다:
export ANTHROPIC_BASE_URL=https://<gateway-url>/api/inference/
export OPENAI_BASE_URL=https://<gateway-url>/api/inference/
그게 전부입니다. LangChain, OpenAI Python 클라이언트, 직접적인 요청(direct requests) 등 모든 기존 SDK 호출이 코드 변경 없이 게이트웨이를 통해 전달되기 시작했습니다. 갑자기 모든 서비스에 걸쳐 비용 귀속, 속도 제한, 요청 로깅이 가능해졌습니다. 애플리케이션 코드는 아무것도 변경되지 않았다는 사실을 전혀 알지 못했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기