새롭게 도입한 AI 기능 뒤에 숨어 있는, 조용하지만 치명적인 비용 폭탄에 대해 생각해 보신 적 있으십니까? 스카이넷 같은 SF 영화 이야기가 아닙니다. 훨씬 더 현실적인 문제, 바로 ‘청구서’ 말입니다. 제가 ‘함께 일했던’ 팀 — ‘이노센트 주식회사’라고 부르겠습니다 — 은 단 2주 만에 첫 LLM 기능을 출시했습니다. 2주 만에요! 그런데 6주 후, 쾅! 4만 7천 달러짜리 OpenAI 청구서가 날아왔습니다. 그것도 무료 티어 제품에 대한 것이었습니다. 으악. 아주 비싼 수업료를 내고 배운 셈이죠.
사후 분석은 전형적인 ‘절대 하지 말아야 할 것’들의 총집합이었습니다. 돌아가는 상황을 보니, 어떤 테넌트는 재시도 로직을 ‘오늘은 좀 느리네’ 정도의 힌트로 여겼고, 또 다른 테넌트는 ‘1만 토큰으로 응답해 줘’라고 모델에게 뻔뻔하게 요청했습니다 (최고를 향해 달려가는 건 좋은 일이니까요). 그리고 세 번째, 좀 더 ‘열정적인’ 사용자 — 이분은 API 키가 사실상 무제한이라는 사실을 알아채고, 자신의 전체 배치 처리 워크로드를 이 키를 통해 돌렸습니다. SDK 직접 호출이었죠. 속도 제한도, 테넌트별 예산도, 비용 상한선도, 감사 추적도… 아무것도 없었습니다. 오직 공유된 키 덕분에 순수하고 여과되지 않은 API 남용만이 존재했습니다.
만약 당신 팀도 LLM 기능을 이런 식으로 — 마치 1999년이고 대역폭이 공짜였던 시절처럼 — 개발하고 있다면, 이 글은 당신을 위한 것입니다. 왜냐하면 충격적인 청구서를 받기 전에, 당신에게는 ‘가드레일’이 필요하기 때문입니다. 이건 바퀴를 재발명하자는 것이 아닙니다. 클라이언트와 LLM 제공업체 사이에 위치할, 스프링 부트 기반의 기능적인 멀티 테넌트 게이트웨이를 구축하자는 것입니다. 당신의 AI 파티를 위한 ‘입장권 검사관’이라고 생각하면 쉽습니다.
이 게이트웨이는 API 키, 속도 제한, 토큰 예산, 캐싱, 감사 로깅을 강제합니다. 모두 생산 환경에 배포하기 전에 필요한, 지루하지만 중요한 ‘어른의 일’들입니다. CFO가 악몽에 시달리기 전에 말이죠.
문제점: 단일 실패 지점
애플리케이션 코드가 OpenAI에 직접 호출을 보낼 때, 제공업체 입장에서는 모든 요청이 동일하게 보입니다. 그들은 하나의 API 키, 하나의 소스, 하나의 청구서를 봅니다. 마치 붐비는 아파트 건물 모든 사람들이 같은 우편함을 사용하는 것과 같습니다. 혼돈 그 자체죠.
이것은 다음과 같은 것을 불가능하게 만듭니다:
- 테넌트별 키 범위 설정 불가. 단일 공유 키는 한 명의 악성 테넌트가 전체 제품을 망가뜨릴 수 있음을 의미합니다. 공동 배포 없이는 키 로테이션이 불가능합니다. 그걸 성공시키기란… 행운을 빌어야 할 겁니다.
- 테넌트별 지출 상한선 설정 불가. 게이트웨이 없이는, 청구서가 도착했을 때 월 예산을 초과했다는 사실을 알게 됩니다. 실시간으로 속도를 늦출 수 없죠. 깜짝 놀랄 일입니다!
- 폭주 응답 차단 불가. 1만 토큰을 요청하는 버그투성이 프롬프트가 아무 문제 없이 실행됩니다. 제공업체는 그것이 잘못되었다는 것을 알지 못하며, 당신은 사후에야 알게 됩니다. 엄청난 비용이 발생하죠.
- 결정론적 호출 캐싱 불가.
temperature=0인 동일한 요청이 매번 비용으로 청구됩니다. 공유 캐시 계층이 없다는 것은 아무것도 공유할 수 없다는 것을 의미합니다. - 어떤 것도 감사 불가. 고객이 “AI가 잘못된 정보를 줬어요”라고 불평할 때, 무엇을 보냈는지, 무엇이 돌아왔는지, 어떤 모델이 사용되었는지 재구성할 수 없습니다. 데이터는 OpenAI 로그에 있지만, 당신은 쿼리할 수 없습니다. 탐정 놀음을 하려 해도 쉽지 않죠.
게이트웨이는 일반적인 해결책입니다. 문제는 어떤 제어를 실제로 시행하느냐, 그리고 어떻게 시행하느냐입니다.
게이트웨이의 8단계 방어 시스템
이 게이트웨이는 단순한 통과 지점이 아닙니다. 8개의 단계를 거치는 정교한 파이프라인으로, 각 단계는 특정 문제를 강제합니다. 당신의 AI 요청을 위한 매우 조직적이고 엄격한 TSA 검문소라고 생각하면 됩니다.
클라이언트
POST /v1/chat/completions
Authorization: Bearer <tenant_api_key>
1단계: 인증 -> 해시된 키 조회, 테넌트 해석
2단계: 입력 정규화 -> 모델/파라미터 표준화, 바이트 수 계산
3단계: 정책 결정 -> 허용 / 저하 / 차단
4단계: 할당량 강제 -> 속도 제한 + 예산 확인 (Redis)
5단계: 캐시 조회 -> temperature=0이고 정책이 허용하는 경우에만
6단계: 제공업체 호출 -> 시간 초과 제한, 서킷 브레이커
7단계: 응답 필터링 -> 제공업체 메타데이터 제거, PII 비공개 처리
8단계: 감사 + 집계 -> PostgreSQL에 기록, 카운터 증가
클라이언트가 응답 수신
이 아키텍처 자체는 세 가지 저장 구성 요소에 의존합니다. 영구적인 데이터(테넌트, 키, 정책, 감사 로그)는 PostgreSQL에, 빠른 경로(속도 제한 카운터, 세마포어, 캐시 등)는 Redis에 저장됩니다. 그리고 상태 없는 게이트웨이 인스턴스 자체는 로드 밸런서 뒤에 위치합니다. 수평으로 확장하는 것은 매우 쉽습니다.
정책의 기술: 모든 차단이 똑같은 것은 아니다
게이트웨이의 성패를 좌우하는 설계 결정은 정책 시행 방식입니다. 대부분의 팀은 ‘한도를 초과하는 모든 것을 차단’하거나 ‘모든 것을 기록하되 절대 차단하지 않음’ 둘 중 하나를 기본으로 선택합니다. 둘 다… 틀렸습니다. 아주 틀렸죠.
이 게이트웨이는 테넌트별, 정책별로 구성 가능한 세 가지 모드를 지원합니다. 여기서 마법이 일어납니다.
HARD (강제) — 한도 도달 시 요청을 거부합니다. 사유 코드를 포함하여 429 (속도 제한) 또는 402 (예산 소진)를 반환합니다. 이는 초과 사용이 허용되지 않는 종량제 플랜 테넌트에게 적용됩니다. 예외도, 변명도 없습니다.
SOFT (완화) — 요청을 거부하는 대신 요청을 ‘저하’시킵니다. 게이트웨이가 요청을 수정합니다: 더 저렴한 모델로 전환하거나, max_tokens를 줄이거나, 파라미터를 더 엄격하게 조정합니다. 사용자는 응답을 받지만, 프리미엄 품질의 응답은 아닙니다. 1등석 대신 할인 항공권을 받는 것과 같습니다. 아무것도 없는 것보다는 낫죠.
OBSERVE (관찰) — 요청을 허용하되 감사 로그에 플래그를 지정합니다. 새로운 정책을 배포할 때 매우 중요합니다. 실제로 차단하거나 저하시켰을 테넌트들을 — 그들에게 영향을 주지 않으면서 — 정확히 확인할 수 있습니다. HARD 또는 SOFT로 전환하기 전에 실제 트래픽으로 정책을 검증하는 것입니다. 변경 사항을 롤아웃하는 유일하게 합리적인 방법입니다.
OBSERVE 모드는 실용적입니다. 정책 임계값을 처음부터 정확하게 설정하는 것은 불가능합니다. 임계값을 설정하고, 2주간 OBSERVE 모드로 실행하며, 차단되거나 저하되었을 트래픽을 검토한 후 HARD 또는 SOFT로 전환하는 것이 유일하게 안전한 롤아웃 경로입니다.
상태 관리: 데이터베이스 백본
영구적인 상태를 위해 필요한 테이블은 단 5개뿐입니다. 가볍고, 간결하며, 효과적입니다.
tenants
id, name, status (ACTIVE/SUSPENDED), created_at
api_keys — 키는 절대로 평문으로 저장되지 않습니다. 천만다행이죠.
id, tenant_id, key_hash, scopes, status,
created_at, last_used_at, rotated_at
policies — 테넌트당 한 행입니다. 규칙이 여기에 살고 있습니다.
tenant_id,
allowed_models (json),
max_prompt_tokens (integer),
max_completion_tokens (integer),
max_requests_per_minute (integer),
max_budget_usd (decimal),
// 기타 설정에 대한 내용은 계속됩니다
usage_rollups — 일일 총계용입니다. 큰 그림을 봐야 하니까요.
tenant_id, model, date, total_prompt_tokens, total_completion_tokens, total_cost_usd, total_requests
audit_logs — 디버깅 및 규정 준수를 위한 핵심입니다.
id, tenant_id, key_id, request_timestamp, request_body_hash, response_status, response_body_hash, model_used, prompt_tokens, completion_tokens, cost_usd, latency_ms
진짜 MVP: 관찰 가능성 (Observability)
고객이 AI 출력 오류에 대해 불만을 터뜨릴 때, 당신에게는 데이터가 필요합니다. 변명이 아니라요. 감사 로그는 포렌식 추적 기능을 제공합니다. 정확한 요청, 사용된 모델, 수신된 응답을 재구성할 수 있습니다. 이것은 디버깅뿐만 아니라 규정 준수 및 분쟁 해결에도 필수적입니다. 로그 없이는 4만 7천 달러짜리 청구서를 설명하려고 상상해 보세요. 좋지 않을 겁니다.
이 게이트웨이는 단순한 비용 통제 메커니즘이 아니라 운영상의 필수 요소입니다. LLM 통합을 무법천지의 난장판에서 구조화되고 관리 가능하며 — 감히 말하자면 — 수익성 있는 노력으로 바꿉니다. 지금 이걸 구축하는 것은 나중에 그 영혼을 갉아먹는 청구서 전화를 받는 사람이 되지 않겠다는 의미입니다. 당신의 CFO는 당신에게 감사할 것이고, 개발자들은 아마 밤에 잠을 좀 잘 수도 있을 겁니다.