Firebase browser key를 제한 없이 사용하다가 13시간 만에 €54,000 청구 폭탄 맞은 사례
€54k spike in 13h from unrestricted Firebase browser key accessing Gemini APIs
TL;DR Highlight
Firebase AI Logic(Gemini API)의 제한 없는 API 키가 자동화된 공격에 악용되어 13시간 만에 €54,000이 청구되었으며 Google은 환불을 거부했다.
Who Should Read
Firebase 또는 Google Cloud를 이용해 Gemini API 기반 기능을 개발하거나 출시하려는 프론트엔드/풀스택 개발자. 특히 API 키를 클라이언트 코드에 포함시키거나 예산 관리를 제대로 설정하지 않은 소규모 팀이나 개인 개발자.
Core Mechanics
- 1년 전에 Firebase Authentication 용도로만 만든 프로젝트에 최근 Gemini API 기반 AI 기능(텍스트 프롬프트로 웹 스니펫 생성)을 추가하면서 Firebase AI Logic을 활성화했는데, 활성화 직후부터 자동화된 트래픽이 폭발적으로 증가했다.
- Firebase 프로젝트의 브라우저용 API 키는 원래 'API 제한 없음' 상태로 생성되는데, 여기에 Gemini API가 추가되자 해당 키로 Gemini 요청이 무제한으로 들어오기 시작했다. 실제 사용자 트래픽과는 전혀 무관한 자동화된 봇 요청이었다.
- €80 예산 경고와 비용 이상 알림을 설정해뒀지만, 둘 다 몇 시간 지연 후에 발송됐다. 반응했을 때는 이미 약 €28,000이 청구된 상태였고, 지연된 비용 보고로 인해 최종 금액은 €54,000 이상으로 확정됐다.
- Google Cloud 지원팀에 로그와 분석 결과를 제출했지만, '해당 사용이 해당 프로젝트에서 발생했다'는 이유로 유효한 사용으로 분류되어 청구 금액 조정 요청이 거부됐다.
- Gemini 팀 책임자(Logan Kilpatrick)가 직접 댓글로 달려서 현재 대응책을 설명했다: Tier 1 사용자는 기본적으로 월 $250 소비 한도가 있고, 프로젝트별 소비 한도(project spend caps)도 설정 가능하다. 단, 두 기능 모두 최대 10분의 지연이 존재한다.
- Google은 앞으로 제한 없는 API 키(unrestricted API key)로 Gemini API를 사용하는 것을 막는 방향으로 이동 중이라고 밝혔다. 또한 신규 사용자에게는 기본적으로 더 안전한 Auth 키를 생성해주도록 변경했다고 한다.
- 선불 결제(prepaid billing) 방식도 도입 중이라고 발표됐다. 미국 신규 사용자부터 적용됐으며 전 세계로 확대 중인데, 이를 통해 개발자가 실제로 쓸 비용을 미리 파악하고 제어할 수 있게 된다.
- Google은 원래 10년 이상 'Google API 키는 비밀이 아니다(공개해도 된다)'는 기조를 유지해왔는데, Gemini API 출시 이후 이 원칙이 깨졌다. 하지만 많은 개발자들이 이 변화를 인지하지 못한 채 기존 방식대로 키를 사용하고 있다.
Evidence
- 댓글에서 GCP 예산 알림의 구조적 문제가 집중적으로 비판받았다. 청구 이벤트가 큐/로그를 거쳐 집계되기 때문에 알림 자체가 수 시간씩 지연될 수 있는데, 설령 하드 한도를 설정해도 마지막으로 알려진 집계값 기준으로 작동하기 때문에 순간적인 스파이크에는 속수무책이라는 지적이 있었다. '이 구조는 고객이 아니라 회사를 보호하는 설계'라는 비판이 많은 공감을 얻었다.
- 비슷한 피해를 입었다는 다른 개발자도 댓글에 등장했다. $26,000 피해를 입은 후 Google Cloud 지원팀에 환불을 요청했는데 처음에는 거부됐지만 현재 재검토 중이라며, '가능한 한 위로 에스컬레이션하라'고 조언했다. 또 다른 댓글에서는 Google 공개 라이브 트레이닝 세션 중 빠르게 생성한 API 키가 유출되어 약 $6,909가 청구됐다는 사례도 공유됐다.
- GitHub에 하드코딩된 Gemini API 키가 이미 매우 많다는 지적이 나왔다. GitHub에서 'gemini "AIza"'로 검색하면 수많은 결과가 나오는데, 기존 Google Maps/Firebase 등의 키는 공개해도 안전하다는 오랜 관행 탓에 개발자들이 Gemini 키도 같은 방식으로 다루고 있다는 분석이었다.
- GCP에서 청구를 즉시 차단하는 '비상 브레이크' 기능이 공식 문서에 있다는 정보가 공유됐다. billing 계정을 프로젝트에서 분리하면 즉시 API 사용이 멈추지만, 연결된 리소스가 삭제될 수 있는 위험이 있어 프로덕션 앱에는 적합하지 않다는 주의사항도 함께 전달됐다.
- Backblaze B2를 사용 중인 개발자가 '실제로 작동하는 소비 한도'의 사례로 언급했다. B2는 API 요청에 $0 한도를 설정하면 free tier 초과 시 즉시 요청이 차단된다는 경험을 공유하며, 클라우드 서비스의 청구 설계가 본질적으로 바뀌어야 한다는 점을 강조했다.
- 사기꾼들이 왜 AI API 키를 노리는지에 대한 질문도 나왔다. EC2 자격증명으로 비트코인 채굴하는 것처럼 명확한 금전적 이득이 뭔지 모르겠다는 의문에 대해, '다른 사람 계정으로 LLM 서비스를 무료로 사용하거나 재판매하기 위한 것일 수 있다'는 추측이 제기됐다.
How to Apply
- Firebase 프로젝트에 Gemini API를 연동할 예정이라면, API 키 설정에서 반드시 'HTTP referrer 제한'과 '허용 API 제한(generativelanguage.googleapis.com만 허용)'을 동시에 설정해야 한다. 이 두 가지 제한이 없으면 키가 노출됐을 때 모든 Google 서비스에 대한 호출이 가능해진다.
- Gemini API 관련 호출은 클라이언트 사이드(브라우저, 앱)가 아닌 서버 사이드에서만 이루어지도록 아키텍처를 설계해야 한다. 불가피하게 클라이언트에서 호출해야 한다면 Firebase App Check를 적용해 인증된 앱에서만 API를 호출할 수 있도록 제한하라.
- Google AI Studio 또는 GCP 콘솔에서 프로젝트 소비 한도(project spend caps)를 설정하고, Pub/Sub + Cloud Function 조합으로 한도 초과 시 billing 계정을 자동으로 분리하는 파이프라인을 구축해 두어야 한다. 단순 이메일 알림은 수 시간 지연이 있어 실질적인 방어가 되지 않는다.
- 기존에 Firebase Authentication 등 다른 용도로 만든 프로젝트에 나중에 Gemini API를 추가하는 경우, 해당 프로젝트의 기존 API 키들이 모두 Gemini 접근 권한을 갖게 된다. 반드시 기존 키 목록을 전수 점검하고 불필요한 API 권한을 제거해야 한다.
Code Example
# GCP billing 계정을 프로그래밍 방식으로 분리하는 비상 방법 (공식 문서 기반)
# 주의: 프로덕션 앱에는 사용 금지. 연결된 리소스가 삭제될 수 있음.
# gcloud CLI로 billing 계정 분리
gcloud billing projects unlink PROJECT_ID
# 또는 Pub/Sub + Cloud Function 조합으로 예산 초과 시 자동 분리
# 1. GCP 콘솔 > Billing > Budgets & alerts > Create budget
# 2. Alert threshold 설정 (예: 80%)
# 3. 'Connect a Pub/Sub topic' 선택
# 4. 아래와 같은 Cloud Function 배포
import base64
import json
from googleapiclient import discovery
def stop_billing(data, context):
pubsub_data = base64.b64decode(data['data']).decode('utf-8')
pubsub_json = json.loads(pubsub_data)
cost_amount = pubsub_json['costAmount']
budget_amount = pubsub_json['budgetAmount']
project_name = pubsub_json['budgetDisplayName'] # 프로젝트명을 예산 이름으로 사용
if cost_amount >= budget_amount:
billing = discovery.build('cloudbilling', 'v1')
# billing 계정 분리
billing.projects().updateBillingInfo(
name=f'projects/{PROJECT_ID}',
body={'billingAccountName': ''}
).execute()
print(f'Billing disabled for project {PROJECT_ID}')
# API 키 제한 설정 (Google Cloud Console > APIs & Services > Credentials)
# - Application restrictions: HTTP referrers (web sites) -> 자신의 도메인만 허용
# - API restrictions: Restrict key -> generativelanguage.googleapis.com 만 선택Terminology
관련 논문
Claude Code는 프롬프트 읽기 전에 33k 토큰을 전송한다; OpenCode는 7k
동일한 모델과 작업 환경에서 Claude Code와 OpenCode의 실제 토큰 사용량을 API 레벨에서 측정한 결과, Claude Code가 시스템 프롬프트 오버헤드만으로 OpenCode 대비 4.7배 더 많은 토큰을 소비한다는 것을 확인했다.
Mesh LLM: iroh 기반 분산 AI 컴퓨팅
사무실, 집, 클라우드에 흩어진 GPU들을 하나의 OpenAI 호환 API로 묶어주는 분산 LLM 실행 시스템으로, 비싼 API 비용 없이 큰 모델을 직접 운영할 수 있다.
Frugon – LLM API 호출 로그를 분석해서 더 싼 모델로 대체 가능한 구간을 찾아주는 로컬 도구
내 LLM API 비용이 어디서 새는지 로컬에서 분석해주는 오픈소스 CLI 도구로, 비싼 모델 대신 저렴한 모델로 전환 가능한 호출을 골라낸다.
로컬에서 SOTA LLM 실행하기 완전 가이드 (하드웨어부터 설정까지)
2천 달러짜리 RTX 3090 한 장부터 4만 달러짜리 RTX PRO 6000 4장 셋업까지, 로컬에서 최신 LLM을 직접 돌리는 방법을 하드웨어 선택·구성·실행 설정까지 통째로 정리한 실전 가이드다.
Manticore Search에서 ONNX 경로를 재설계해 임베딩 속도를 14배 높인 방법
Manticore Search가 기존 SentenceTransformers/Candle 백엔드를 ONNX Runtime으로 교체해 텍스트 임베딩 생성 속도를 평균 14배 향상시켰다. 별도 모델 서비스 없이 DB 내부에서 직접 임베딩을 처리하는 구조에서 INSERT 속도가 곧 임베딩 속도이기 때문에 이 개선은 실질적인 ingest 처리량 향상으로 직결된다.
Asymmetric Quantization: 97% 스토리지 절감으로 Late Interaction 검색 품질 유지하기
멀티벡터 검색 모델의 문서 벡터를 1비트 이진값으로 압축하고 쿼리 벡터만 int8로 유지하는 비대칭 양자화 기법으로, 스토리지를 97% 줄이면서 검색 품질 손실을 0.61점(NDCG@10 기준)에 그치게 만든 실제 프로덕션 적용 사례다.