이 시리즈 마지막 편을 찍으려고 Google AI 스튜디오를 열었다가, 화면 맨 위에서 이 문구를 봤습니다. «공개적으로 노출된 API 키가 감지되었습니다.» 결제가 연결된 Gemini 키 두 개였습니다. 구글이 인터넷 어딘가에 공개된 제 키를 찾아내 알려 준 것입니다. 두 키를 바로 삭제했고, 경고는 사라졌습니다. 이론 대신 방금 겪은 실제 사고로 시작합니다. 바이브 코딩에서 가장 비싼 실수가 이것이기 때문입니다 — 앱은 다시 만들면 되지만, 새어 나간 열쇠로 쓴 요금은 돌아오지 않습니다.
AI 스튜디오(aistudio.google.com) 왼쪽 메뉴 API 키를 누르면 내가 만든 열쇠 목록이 나옵니다. 이날 목록 맨 위에 노란 경고가, 열쇠 하나 옆엔 «경고» 딱지가 붙어 있었습니다.


| 확인한 것 | 내용 |
|---|---|
| 어떤 열쇠 | Gemini(구글 AI) 열쇠 두 개 — 각각 2025년 9월, 2026년 1월에 만든 것. 둘 다 결제 계정이 연결돼 있었습니다 |
| 어디서 샜나 | 지금 컴퓨터의 프로젝트 파일에는 남아 있지 않았습니다. 예전에 공개된 곳(지난 기록·웹페이지·캡처 등)에 한 번 올라갔던 것으로 보입니다 — 지금 지워도 이미 퍼진 건 회수할 수 없습니다 |
| 한 일 | 두 열쇠 삭제(= 그 열쇠로는 더 이상 아무것도 못 함). 실제로 쓰는 열쇠는 경고 대상이 아님을 끝자리로 확인 |
| 배운 것 | 쓰지 않는 열쇠는 그때그때 지우기 · 앱마다 열쇠 따로 · 화면 코드에 넣지 않기 — 아래에서 하나씩 |
구글·GitHub·OpenAI 같은 회사는 인터넷에 공개된 곳을 훑어 자기 회사 열쇠 모양을 찾으면 주인에게 알려 주거나 자동으로 막습니다. 하지만 항상 먼저 찾아 준다는 보장은 없습니다. 나쁜 사람들도 같은 방법으로, 더 빨리 훑습니다.

| 새는 곳 | 어떻게 새나 | 이렇게 막기 |
|---|---|---|
| ① 화면 코드 유리창 | AI가 «빨리 되게» 하려고 열쇠를 웹페이지 코드에 바로 넣음. 그 페이지를 연 누구나 브라우저의 «페이지 소스 보기»로 열쇠를 볼 수 있음 | 비싼 열쇠는 «주방»(서버)에만 — 막는 법 ② |
| ② 공개 GitHub 공책의 지난 페이지 | 공개 저장소에 올라간 순간 몇 분 안에 수집됨. 나중에 파일에서 지워도 지난 기록(커밋)엔 남아 있음 | 저장소는 비공개로, 열쇠는 보관함 파일에 — 막는 법 ① |
| ③ 캡처·단톡방·메일 | «이거 왜 안 돼요?» 하며 설정 화면을 통째로 캡처해 공유. 사진 속 글자도 읽힘 | 보내기 전에 열쇠 부분 가리기 |
| ④ 강의 슬라이드·영상 | 실습 화면을 녹화·발표하다 열쇠가 그대로 찍힘. 영상은 한 번 올라가면 내려도 퍼져 있음 | 시연용 열쇠는 따로 만들고, 강의 끝나면 삭제 |
헷갈리는 이유가 있습니다. 어떤 열쇠는 일부러 화면에 넣으라고 만든 것이기 때문입니다. 이름과 쓰임으로 구분합니다.
| 열쇠 | 화면 코드에 | 이유 |
|---|---|---|
| Supabase publishable / anon | 🟢 넣어도 됨 | 장부 규칙(RLS)이 지켜 주는 «공개용» — 단, RLS가 켜져 있을 때만(«바이브 03») |
| Firebase 웹 설정값 apiKey 라고 적혀 있어도 | 🟢 넣어도 됨 | 앱을 식별하는 «주소표»에 가까움. 보안은 Firebase 보안 규칙이 담당 |
| Supabase secret / service_role | 🔴 절대 안 됨 | 장부 규칙을 무시하는 관리자 열쇠 |
| Gemini · OpenAI · Claude 키 | 🔴 절대 안 됨 | 쓰는 만큼 내 카드로 요금이 나감. 오늘 사고가 바로 이 종류 |
| GitHub 토큰 · 결제(PG) 시크릿 | 🔴 절대 안 됨 | 내 저장소·매출에 손댈 수 있음 |

내 컴퓨터에서 열쇠를 둘 곳은 .env라는 보관함 파일입니다. 그리고 GitHub에 올라가지 않도록 .gitignore(올리지 않을 목록)에 그 파일 이름을 적어 둡니다. 둘 다 AI가 해 줍니다 — 확인만 하면 됩니다.


보관함을 잘 써도, 화면 코드가 직접 Gemini를 부르는 구조라면 열쇠는 결국 손님 브라우저로 전달됩니다. 해결책은 1편의 식당 비유 그대로 — 손님(화면)은 주문서만 넘기고, 열쇠는 주방(서버)에서만 씁니다.

| 위험한 구조 | 안전한 구조 | |
|---|---|---|
| 흐름 | 화면 → (열쇠 들고) → Gemini | 화면 → 내 서버(주방) → (열쇠는 여기서만) → Gemini |
| 열쇠 위치 | 웹페이지 코드 안 = 누구나 «소스 보기»로 확인 | Vercel 환경 변수 = 아무도 못 봄 |
| 덤으로 | — | «한 사람당 하루 몇 번까지» 같은 사용량 제한을 주방에서 걸 수 있음 |
| AI에게 | «Gemini 키가 화면 코드에 들어가지 않게, Vercel 서버 함수를 거쳐서 부르는 구조로 바꿔줘» | |
AI 스튜디오·캔버스 같은 곳에서 만든 앱을 «내 키로» 공개 공유하면, 앱을 쓰는 사람들의 사용료가 내 계정으로 청구될 수 있습니다. 공유 전에 누구의 열쇠로 돌아가는 앱인지 꼭 확인하세요.
열쇠가 샌 걸 알았을 때 가장 흔한 실수는 «어디서 샜는지»부터 찾는 것입니다. 그동안에도 누군가 쓰고 있을 수 있습니다. 순서가 중요합니다.

대부분의 AI 서비스는 «한 달 최대 얼마까지»를 정할 수 있습니다(AI 스튜디오 왼쪽 메뉴 «비용 제한» 등). 열쇠가 새도 피해가 그 금액에서 멈춥니다. 강의 실습용 계정이라면 꼭 걸어 두세요.
GitHub에 올리기 전에 이 앱의 보안을 점검해줘. 1) API 키·토큰·비밀번호가 코드나 화면 파일에 그대로 들어간 곳이 있는지 2) .env 같은 보관함 파일이 .gitignore에 들어 있는지 3) 지난 커밋 기록에도 열쇠가 올라간 적이 있는지 열쇠 값 자체는 화면에 보여주지 말고, 어느 파일 몇 번째 줄인지만 알려줘. 고칠 방법도 같이.
지금 이 앱은 화면 코드에서 Gemini를 직접 부르고 있어. 키가 브라우저에 노출되지 않게 Vercel 서버 함수를 거쳐서 부르는 구조로 바꿔줘. 키는 Vercel 환경 변수(Secret)에 넣고, 한 사람이 너무 많이 부르지 못하게 간단한 사용량 제한도 걸어줘. 내가 Vercel에서 할 일은 순서대로 알려줘.
이 앱이 쓰던 Gemini 키가 노출돼서 방금 삭제했어. 새 키를 발급했으니 코드 어디에서 그 키를 쓰는지 찾아서, 새 키는 .env와 Vercel 환경 변수에만 넣고 다시 배포해줘. 새 키 값은 내가 직접 붙여 넣을 테니 넣을 위치만 알려주고, 화면에 키를 출력하지 마.
| 편 | 한 줄 |
|---|---|
| 바이브 01 · 지도 | 작업실 → 창고(GitHub) → 가게(Vercel) → 간판(도메인), 그리고 장부와 열쇠 |
| 바이브 02 · 배포 | «올려줘» 한마디에 2분 — 처음 한 번 연결하는 법 |
| 바이브 03 · 장부 | «응답 0명»을 막는 한 권의 장부와 장부 규칙 |
| 바이브 04 · 열쇠 (지금 글) | 열쇠가 새는 네 곳, 막는 두 가지, 샜을 때 네 단계 |
2026년 10월 8일 제 Google AI 스튜디오·GitHub·Vercel·Supabase 계정에서 찍었습니다. AI 스튜디오의 경고는 실제로 받은 것이고, 해당 열쇠 두 개는 같은 날 삭제했습니다(키 끝자리와 프로젝트 이름은 가림). Vercel 열쇠 등록 창은 입력·저장하지 않고 열기만 했습니다. 서비스 화면 구성은 바뀔 수 있습니다.