정신 건강을 해치지 않고 안전한 AI API 프록시를 구축한 방법
요약
AI API를 프론트엔드에 직접 노출할 때 발생하는 보안 및 비용 문제를 해결하기 위한 안전한 백엔드 프록시 구축 방법을 다룹니다. 단순한 라우팅을 넘어 속도 제한, 캐싱, 토큰 추적을 포함한 미니멀리스트 프록시 설계의 중요성을 강조합니다.
핵심 포인트
- 클라이언트 측 API 키 노출 방지를 위한 백엔드 프록시 필수
- IP 기반 속도 제한(Rate Limiting)을 통한 비용 폭증 방지
- 동일 프롬프트에 대한 응답 캐싱으로 API 비용 절감
- 사용자 입력을 정제하여 프롬프트 인젝션 공격 방어
저는 몇 년 동안 사이드 프로젝트에 AI API를 통합해 왔습니다. 매번 똑같은 벽에 부딪히곤 했습니다. AI 기반 엔드포인트를 프론트엔드(frontend)에 노출하고 싶지만, 클라이언트(client)에 API 키를 절대 둘 수는 없었습니다. 명확한 답은 백엔드 프록시(backend proxy)입니다. 하지만 처음 몇 번 시도했을 때는 지저분하고, 보안에 취약하거나, 비용이 많이 드는 엉망진창인 결과로 끝났습니다.
많은 시행착오 끝에 실제로 효과가 있었던 방법은 다음과 같습니다.
문제점 (The Problem)
저는 사용자가 문서에 대해 질문할 수 있게 해주는 작은 도구를 만들고 있었습니다. 프론트엔드에서 AI API(OpenAI 또는 Claude와 같은)를 호출해야 했습니다. 간단해 보이죠? 그렇지 않습니다.
- 클라이언트의 API 키: 절대 안 됩니다. 누구나 네트워크 요청을 검사하여 키를 훔칠 수 있습니다.
- 속도 제한 (Rate limits): 무료 티어는 금방 한계에 도달하며, 저는 통제 불가능한 비용 청구를 원하지 않았습니다.
- 지연 시간 (Latency): 브라우저에서의 직접 호출은 때때로 CORS 오류나 예상치 못한 타임아웃(timeout)을 발생시킵니다.
- 프롬프트 인젝션 (Prompt injection): 사용자 입력을 정화(sanitize)하지 않으면, 사용자가 AI를 속여 시스템 프롬프트(system prompts)를 유출하거나 위험한 행동을 하게 만들 수 있습니다.
그래서 프록시가 필요했습니다. 그냥 아무 프록시가 아니라, 보안이 뛰어나고, 비용을 인지하며, 유지보수가 쉬운 프록시가 필요했습니다.
실패했던 시도들
1. 단순한 Express 라우트 (A Simple Express Route)
가장 게으른 방식으로 시작했습니다:
app.get('/api/ai', async (req, res) => {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
...
이 방식은 작동하지만, 팀의 모든 사람이 동일한 키에 접근할 수 있게 됩니다. 로깅(logging)도 없고, 속도 제한(rate limiting)도 없으며, 비용 추적도 불가능합니다. 프론트엔드의 단 하나의 버그가 백만 개의 요청을 보내 제 계좌의 잔액을 바닥낼 수 있습니다.
2. 서버리스 함수 사용 (Using a Serverless Function)
다음으로는 Vercel Edge Function을 시도했습니다. 콜드 스타트(cold starts) 때문에 예측 불가능해지고 디버깅(debugging)이 악몽 같다는 것을 깨닫기 전까지는 멋져 보였습니다. 게다가 사용량을 쉽게 로깅할 수도 없었습니다.
3. 사전 구축된 API 게이트웨이 (Pre‑built API Gateways)
Kong, Tyk, 심지어 클라우드 제공업체의 API Gateway도 살펴보았습니다. 오버헤드(overhead)가 너무 컸습니다. 저는 단지 하나의 AI 엔드포인트를 호출하고 싶었을 뿐이지, 완전한 엔터프라이즈 솔루션을 구축하고 싶었던 것이 아니었습니다.
결국 성공한 방법: 속도 제한(Rate Limiting), 캐싱(Caching), 토큰 추적(Token Tracking)을 갖춘 미니멀리스트 프록시
저는 세 가지 핵심 기능을 갖춘 아주 작은 Node.js express 서버를 구축했습니다:
- 요청 검증 (Request validation) – 사용자 프롬프트를 정제(sanitize)하고 최대 토큰 수를 제한합니다.
- IP당 속도 제한 (Rate limiting per IP) –
express-rate-limit을 사용합니다. - 응답 캐싱 (Response caching) – 비용 절감을 위해 동일한 프롬프트는 5분 동안 캐싱됩니다.
- 비용 로깅 (Cost logging) – 사용된 토큰 수와 예상 비용을 추적합니다.
핵심 구조는 다음과 같습니다:
const express = require('express');
const rateLimit = require('express-rate-limit');
const NodeCache = require('node-cache');
...
배운 점들
- 속도 제한(Rate limiting)은 타협할 수 없는 요소입니다. 사용자를 신뢰하더라도, 인터넷 자체는 신뢰할 수 없습니다. 무료 티어(Free tiers)는 악용되기 마련입니다.
- 공격적으로 캐싱하되, 영리하게 처리하세요. 서로 다른 사용자가 보낸 동일한 프롬프트가 API를 다시 호출하게 해서는 안 됩니다. 하지만 앱이 실시간(예: 채팅)이라면 캐싱이 신선도(freshness)를 해칠 수 있습니다. 이 경우 캐싱을 건너뛰거나 TTL(Time To Live)을 줄이세요.
- 모든 것을 로깅하세요 (단, 프롬프트가 민감하다면 원문을 저장하지 마세요). 저는 토큰 수와 응답 상태를 로깅하지만, 사용자 데이터를 저장하지 않기 위해 로깅 전 프롬프트를 해싱(hash)합니다.
- 요청을 단순히 전달만 하지 마세요. 검증하고 정제(sanitize)하세요. 사용자가 주입하려고 시도할 수 있는 모든 시스템 역할(system role) 오버라이드를 제거하세요.
트레이드오프(Trade-Offs) 및 이 방식을 사용하지 말아야 할 때
- 이 프록시는 싱글 노드(single-node) 방식입니다. 고가용성(high availability)이 필요하다면 로드 밸런서(load balancer)를 사용하거나, Cloudflare Workers의 서버리스 프록시(edge에서 캐싱도 가능)와 같이 더 확장 가능한 솔루션을 사용해야 합니다.
- 스트리밍(SSE)을 사용하는 경우 캐싱이 잘 작동하지 않습니다. 이 경우 다르게 처리해야 합니다.
- 비용 추정치는 대략적인 수치입니다. 정확한 과금을 위해서는 AI 제공업체의 대시보드를 사용하세요. 본인의 계산에만 의존하지 마세요.
다음에 한다면 다르게 할 점
- Express 대신 Cloudflare Worker로 시작하세요. 사용량이 적을 때는 무료이며, 내장된 캐싱 (Caching) 및 속도 제한 (Rate limiting) 기능을 갖추고 있고 전 세계적으로 실행됩니다. 코드는 유사하겠지만 Workers 런타임(Runtime)에서 작동하게 됩니다.
- 실시간이 아닌 요청에는 **큐 (Queue)**를 사용하세요. 배치 처리 (Batch processing)를 위해, 프롬프트를 큐(예: Bull 또는 AWS SQS)에 넣고 워커 (Worker)가 동시성 제한 (Concurrency limit)을 두고 이를 소비하도록 할 것입니다. 이렇게 하면 API에 과부하를 주는 것을 방지하고 비용을 예측 가능하게 만듭니다.
- **알림 (Alerts)**을 설정하세요. 오류율이 급증하거나 일일 토큰 사용량이 임계값을 초과할 경우 알림을 받을 수 있도록 웹훅 이메일 서비스(예: SendGrid)를 사용할 것입니다.
마치며
AI 프록시를 구축하는 것은 엄청나게 어려운 일은 아니지만, 세부 사항이 중요합니다. 위의 코드를 통해 저는 약 한 시간 만에 아무것도 없는 상태에서 사용 가능하고 안전한 엔드포인트 (Endpoint)를 만들 수 있었습니다. 그 이후로 저는 JWT 인증 (Authentication), 사용자별 속도 제한 (Rate limits), 그리고 비용 추적을 위한 간단한 대시보드와 같은 더 많은 미들웨어 (Middleware)를 추가하며 이를 개선해 왔습니다.
이제 여러분의 차례입니다. AI API를 안전하게 노출하기 위해 현재 어떤 설정을 사용하고 계신가요? 다른 스택을 시도해 보았거나 영리한 캐싱 트릭을 발견하셨나요? 여러분에게 효과적인 방법이 무엇인지 정말 듣고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기