Gemini API 키 제한 운영법: 무제한 키를 없애고 서비스별 피해 범위를 줄이는 방법
요약: Gemini API나 Vertex AI를 앱에 붙일 때 API key를 하나 만들어 모든 환경에서 돌리는 방식은 빠르지만 위험하다. Google Cloud 문서는 API key 제한, 저장 방식, query parameter 사용 금지, 키 분리, 주기적 rotation을 강조한다. AI 기능이 커질수록 키 하나의 노출이 곧 비용 사고와 데이터 접근 사고로 이어진다.
문제는 키가 아니라 ‘무제한 키’다
API key 자체는 흔한 인증 수단이다. Google Cloud 문서는 standard API key가 요청을 프로젝트와 연결해 billing과 quota 용도로 쓰이며, principal을 인증하지 않는다고 설명한다. 즉 표준 API key만으로는 IAM을 통해 호출 주체를 세밀하게 확인하기 어렵다. 그래서 제한 없이 노출된 키는 비용과 quota를 소모하는 진입점이 된다.
Gemini API처럼 사용량이 곧 비용으로 연결되는 서비스에서는 위험이 더 크다. 프론트엔드 코드에 키를 넣거나, URL query parameter로 전달하거나, GitHub 저장소에 실수로 커밋하면 스캐너에 잡힐 수 있다. Google의 best practices 문서도 공개 노출이 예상치 못한 비용이나 무단 접근으로 이어질 수 있다고 경고한다.
따라서 목표는 ‘API key를 쓰지 말자’가 아니라 ‘노출돼도 피해 범위가 작게 만들자’다. 서비스별 키 분리, API 제한, 애플리케이션 제한, 서버 프록시, 모니터링, rotation이 한 세트로 움직여야 한다.
첫 번째 원칙: 클라이언트에 직접 넣지 않는다
Google 문서는 API key를 client code나 code repository에 포함하지 말라고 권장한다. 클라이언트는 서버로 요청을 보내고, 서버가 credential을 붙여 Google API에 요청하는 구조가 안전하다. 웹앱이나 모바일앱 번들에 들어간 키는 난독화해도 결국 추출될 수 있다.
MVP에서는 클라이언트에서 Gemini API를 바로 호출하고 싶은 유혹이 크다. 그러나 AI 기능은 호출당 비용이 있고 abuse가 쉽다. 로그인 없는 공개 페이지에 키가 들어가면 누군가 대량 요청을 보내도 사용자의 브라우저와 구분하기 어렵다. 최소한 Cloud Run, Lambda, API Gateway 같은 얇은 proxy를 두고 rate limit과 사용자 인증을 붙이는 편이 낫다.
프록시 서버는 단순히 키를 숨기는 곳이 아니다. 입력 길이 제한, 모델 선택 제한, 일일 사용자 한도, abuse pattern 차단, 로그 redaction을 담당한다. 특히 프롬프트와 파일 업로드가 섞이면 서버에서 PII 마스킹이나 MIME type 검증을 먼저 해야 한다.
두 번째 원칙: 키마다 쓸 수 있는 API를 제한한다
Google은 API key restrictions를 추가해 키가 사용될 수 있는 방식을 제한하라고 안내한다. 한 키가 모든 Google API를 호출할 수 있으면 노출 시 피해가 커진다. Gemini API용 키는 generativelanguage.googleapis.com 또는 필요한 API로만 제한하고, 지도·스토리지·기타 API와 공유하지 않는 것이 기본이다.
애플리케이션 제한도 필요하다. 서버에서만 쓰는 키는 서버 환경에 맞는 제한을 걸고, 브라우저에서 불가피하게 쓰는 키는 HTTP referrer 제한을 둔다. 모바일은 패키지명과 서명 인증서 제한을 검토한다. 제한 방식은 서비스별로 다르므로 ‘키 하나에 모든 환경’이 아니라 ‘환경 하나에 키 하나’가 운영하기 쉽다.
키 이름도 중요하다. prod-gemini-summary-server, staging-gemini-eval-worker처럼 용도와 환경이 보이게 만든다. 나중에 이상 사용량이 생겼을 때 어떤 키를 꺼야 하는지 바로 알아야 한다. 이름이 API key 7이면 사고 대응 시간이 길어진다.
세 번째 원칙: URL query parameter를 피한다
Google 문서는 API key를 query parameter로 전달하면 URL에 키가 포함되어 URL scan을 통한 탈취 위험이 커진다고 설명한다. REST 호출에서는 x-goog-api-key HTTP header나 client library 사용을 권장한다. 이 차이는 사소해 보이지만 로그에서 크게 갈린다.
URL은 브라우저 히스토리, proxy log, analytics, error reporting, referrer header에 남기 쉽다. 반면 header도 완전히 안전한 것은 아니지만, 적어도 일반 URL 로그에 섞이는 위험은 줄인다. 서버에서는 access log에 header를 남기지 않도록 설정하고, 에러 리포트에서도 credential field를 마스킹해야 한다.
실무 체크는 간단하다. 코드베이스에서 ?key=, api_key=, GOOGLE_API_KEY 문자열을 검색한다. 프론트엔드 번들, .env.example, README, CI 로그까지 확인한다. 한 번이라도 공개 저장소에 올라간 키는 rotation 대상으로 보는 것이 안전하다.
네 번째 원칙: 모니터링과 회전은 자동화한다
Google은 strong monitoring and logging을 권장한다. AI API에서는 호출 수만 보면 부족하다. 모델별 호출 수, 사용자별 호출 수, 실패율, 입력 길이, 출력 길이, 지역, referrer, 서버 endpoint를 함께 봐야 한다. 갑자기 짧은 시간에 같은 키로 비정상적인 요청이 늘면 자동 알림이 필요하다.
Rotation은 ‘언젠가’ 하면 실패한다. 새 키 생성, secret manager 업데이트, 배포, 이전 키 비활성화, 모니터링 확인까지 runbook으로 만들어야 한다. 무중단 rotation을 하려면 서버가 여러 키를 읽을 수 있게 하거나, secret version을 지원하는 구조가 좋다.
불필요한 키 삭제도 중요하다. Google best practices는 사용하지 않는 API key를 삭제해 공격 표면을 줄이라고 말한다. PoC 때 만든 키가 prod 프로젝트에 남아 있으면 나중에 누가 쓰는지 모른다. 매월 키 inventory를 뽑고 owner 없는 키는 삭제 후보로 올려야 한다.
Authorization key를 production에서 조심해야 하는 이유
Google 문서는 authorization key가 service account에 bound된 API key라고 설명한다. Vertex AI와 Gemini API 등 일부 API에서 지원될 수 있지만, best practices는 production 환경에서 authorization key 사용을 권장하지 않는다. 이유는 bearer credential 성격, audit log에서 end user identity 추적 어려움, 노출 시 service account 권한 남용 가능성 때문이다.
생산 환경에서는 IAM, short-lived service account credentials, workload identity 같은 방식을 우선 검토해야 한다. API key는 개발 초기 경험을 빠르게 만들 수 있지만, 권한이 커질수록 장기 credential의 위험도 커진다. 특히 서버 간 호출, 배치 작업, 관리자 기능은 API key보다 IAM 기반 인증이 낫다.
결론은 단순하다. Gemini API 키는 제품 기능의 일부가 아니라 보안 자산이다. 코드 리뷰에서 프롬프트 품질만 보지 말고 credential 경로를 같이 봐야 한다.
실행 체크리스트
-
API key를 프론트엔드 코드와 공개 저장소에서 제거한다.
-
Gemini API용 키는 필요한 API와 환경으로만 제한한다.
-
REST 호출에서 query parameter 대신
x-goog-api-keyheader 또는 client library를 쓴다. -
키별 owner, 용도, 환경, 마지막 사용일을 inventory로 관리한다.
-
월 1회 미사용 키 삭제와 정기 rotation runbook을 실행한다.