10장 — 내 API 키를 지켜라: .gitignore와 보안 규칙
2026년 6월 30일 화요일 오전 7시 05분. 기말고사 마지막 날 아침이었습니다. 김진관 선생님이 와이셔츠를 입으며 출근 준비를 하던 중 핸드폰이 짧게 진동했습니다. 메일 한 통이 도착해 있었습니다. 발신자는 Anthropic. 제목은 이랬습니다. "Your API key has been exposed."
손가락이 멈췄습니다. 메일을 열어 본문을 읽어 내려갔습니다. 지난주 class-2b 학급 웹사이트에 학생 글쓰기 피드백 기능을 추가하면서, Claude로부터 API 키를 받아 자바스크립트 파일 맨 위에 그대로 써뒀습니다. 그 파일이 GitHub 공개 저장소에 고스란히 올라가 있었습니다. 자동화된 봇이 감지하기까지 걸린 시간은 수 분. 키는 이미 Anthropic이 자동 폐기한 상태였습니다. 손이 떨렸습니다. 다행히 비용 청구 전 조치였습니다. 이 챕터를 먼저 읽었더라면 일어나지 않았을 사고였습니다.
API 키가 GitHub에 올라가는 순간 전 세계가 그 키를 읽을 수 있습니다.
.gitignore파일 하나가 이 사고를 막습니다.
이 챕터를 마치면 다음 세 가지를 할 수 있습니다.
- 프로젝트 루트에
.gitignore파일을 만들어.env와 API 키 파일을 추적에서 제외할 수 있습니다. .env와.env.example패턴으로 키는 숨기고 구조만 공유하는 방식을 적용할 수 있습니다.- 이미 커밋된
.env파일을git rm --cached로 제거하고 키를 교체할 수 있습니다.
왜 이 챕터가 중요한가
바이브 코딩으로 앱을 만들 때 Claude는 종종 .env 파일에 API 키를 넣으라고 안내합니다. 거기까지는 정상입니다. 문제는 그 파일이 GitHub로 함께 올라가는 순간 발생합니다. 자동화된 봇이 공개 저장소를 쉬지 않고 스캔하며 sk-, AKIA, AIza로 시작하는 문자열을 찾아냅니다. 노출된 키는 매우 빠르게 감지될 수 있습니다. 악성 사용자의 손에 먼저 들어가면 하루 사이에 수백만 원 단위의 요금이 청구된 사례가 개발자 커뮤니티에 여러 건 공유되어 있습니다. 미리 알면 막을 수 있습니다.
(1) .gitignore는 "열지 마세요"라고 써 붙인 서랍입니다
사무실 서랍에 직원 급여 명세서를 넣어뒀는데 손님이 들어왔습니다. "이 서랍은 열지 마세요"라고 메모를 붙여두면 실수로 열어볼 일이 줄어듭니다. .gitignore 파일이 바로 이 메모입니다. Git에게 "이 파일들은 추적하지 말고, GitHub에도 올리지 마라"라고 알려주는 단순한 텍스트 파일입니다.
김진관 선생님은 사고가 난 그날 오전, 보충수업 쉬는 시간을 쪼개어 class-2b 프로젝트 폴더를 열었다. 순서는 이랬다.
(1) 프로젝트 루트(저장소의 가장 바깥 폴더) 안에서 VSCode를 엽니다. 좌측 파일 탐색기에서 빈 공간을 우클릭하고 "새 파일"을 선택합니다.
(2) 파일 이름을 .gitignore로 입력합니다. 점(.)으로 시작하는 것이 포인트입니다. 탐색기에서 직접 만들 때 "파일 이름을 바꿀 수 없습니다"라는 경고가 뜨면 VSCode 안에서 만들면 됩니다.
(3) 아래 내용을 그대로 복사해 붙여넣고 저장(Ctrl+S)합니다.
# 환경변수 파일 (API 키 포함)
.env
.env.local
.env.production
.env.development
# AI 도구 설정 폴더
.cursor/
.claude/
# OS 생성 파일
.DS_Store
Thumbs.db
# Node.js 의존성 폴더
node_modules/
저장이 끝나면 GitHub Desktop으로 돌아가 Changes 탭을 엽니다. 방금 추가한 .gitignore 한 줄만 목록에 올라 있고, 어제까지 보이던 .env는 목록에서 사라져 있습니다. 이것이 이 챕터의 Quick Win입니다. .env는 여전히 내 컴퓨터에 있습니다. 다만 Git이 더 이상 그 파일의 변경을 추적하지 않습니다.
잘 안 되면?
.gitignore를 추가했는데 Changes 탭에.env가 여전히 보인다면, 그.env는 이미 이전에 한 번 커밋된 적이 있다는 뜻입니다. 이 경우는 아래 개념 3에서 해결합니다. 지금은 당황하지 말고 계속 읽으면 됩니다.
(2) .env와 .env.example — 키는 숨기고 구조는 공유합니다
집 현관 열쇠 사진을 찍어 SNS에 올리는 교사는 없습니다. API 키를 GitHub에 올리는 것이 바로 그 행위와 같습니다. 누구든 그 키로 내 계정에 요청을 보낼 수 있고, 요금은 내 카드에서 빠져나갑니다.
.env 파일은 환경변수(Environment Variables)의 줄임말로, 코드와 분리해서 API 키·비밀번호·데이터베이스 주소를 저장하는 전용 파일입니다. 일반적인 형식은 다음과 같습니다.
ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxxxxxxxxxxxx
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxx
DATABASE_URL=postgresql://user:password@localhost/mydb
이 파일은 .gitignore에 등록되어 있으므로 GitHub에 올라가지 않습니다. 그런데 문제가 하나 생깁니다. 동료 교사 박혜원 선생님이 집 컴퓨터에서 class-2b 저장소를 clone 받았다고 해 봅시다. .env 파일은 따라오지 않습니다. 그러면 어떤 키가 필요한지 박 선생님은 어떻게 알 수 있을까요. 이때 쓰는 것이 .env.example 파일입니다.
ANTHROPIC_API_KEY=여기에_본인_키_입력
OPENAI_API_KEY=여기에_본인_키_입력
DATABASE_URL=여기에_DB_주소_입력
.env.example은 .gitignore에 등록하지 않습니다. 그래서 이 파일은 GitHub에 올라갑니다. 실제 키 값은 빠져 있고, "여기에 어떤 키가 들어가야 하는지"만 보여줍니다. 학생들에게 나눠 줄 구글 폼에 "이메일을 입력하세요"라고 안내만 써두고 실제 이메일 칸은 비워두는 것과 같은 원리입니다. 키는 숨기고, 구조만 공유합니다.
(3) 이미 올라간 키를 제거하는 순서 — 자물쇠 먼저, 열쇠 나중
현관 열쇠를 잃어버렸다고 가정해 봅시다. 새 열쇠를 만들기 전에 문을 아무리 단단히 잠가봤자 소용이 없습니다. 먼저 자물쇠 자체를 교체해야 합니다. 이미 GitHub에 올라간 API 키도 똑같습니다. 뒤늦게 .gitignore에 .env를 추가해봤자, 한 번 올라간 키는 커밋 히스토리에 영구 보존되어 있습니다. 순서가 중요합니다.
김진관 선생님이 사고 당일 실제로 밟은 순서는 이렇다.
(1) Anthropic 대시보드(console.anthropic.com)에 접속해 노출된 키를 즉시 폐기(Revoke) 버튼으로 무효화합니다. 이것이 가장 먼저입니다. 이 순서를 뒤집으면 안 됩니다.
(2) 같은 화면에서 "Create Key" 버튼을 눌러 새 키를 발급받습니다.
(3) 내 컴퓨터의 .env 파일을 열어 옛 키를 지우고 새 키로 교체합니다.
(4) .gitignore에 .env가 들어 있는지 확인합니다. 없으면 추가합니다.
(5) VSCode 터미널(Ctrl + `)을 열고 프로젝트 루트에서 아래 명령을 실행합니다.
git rm --cached .env
이 명령은 내 컴퓨터의 .env 파일은 그대로 두고, Git의 추적 목록에서만 제거합니다. --cached를 빼면 실제 파일까지 삭제되니 반드시 붙여야 합니다.
(6) GitHub Desktop으로 돌아가 "chore: remove .env from tracking"이라는 메시지로 커밋하고 Push origin을 누릅니다.
여기까지 마치면 앞으로의 커밋에서는 .env가 더 이상 따라 올라가지 않습니다. 다만 한 가지를 기억해야 합니다. 과거 히스토리에 남은 옛 키는 여전히 읽을 수 있으므로, (1)단계의 키 폐기가 최종 방어선입니다. 그래서 순서가 중요합니다.
잘 안 되면?
git rm --cached .env를 어디에 붙여넣어야 할지 모르겠다면 이렇게 하면 됩니다. VSCode에서 프로젝트 폴더를 엽니다. 상단 메뉴에서 "터미널 → 새 터미널"을 클릭합니다. 화면 아래쪽에 검은 창이 열리면 그 창의 첫 줄에 이미 프로젝트 루트 경로가 표시되어 있습니다. 거기에 명령을 그대로 붙여넣고 엔터만 누르면 됩니다.
핵심 3줄 요약
.gitignore는 Git에게 "이 파일은 추적하지 마라"를 알려주는 메모 파일입니다. 프로젝트 루트에 둡니다..env에 API 키를 넣고.env.example로 구조만 공유하면 키 노출을 원천 차단합니다.- 이미 올라간 키는 복구 불가. 즉시 폐기 → 새 키 발급 →
git rm --cached순서로 대응합니다.
완료 체크리스트
- 프로젝트 루트에
.gitignore파일을 만들었다. -
.env,.cursor/,.claude/,node_modules/항목을 등록했다. -
.env.example파일로 팀원에게 키 구조만 공유할 수 있다. - 이미 커밋된
.env를git rm --cached로 제거하는 순서를 설명할 수 있다.
다음은 에필로그입니다. 3월 3일의 빈 화면이 어떻게 7월의 한 줄 히스토리로 남았는지, 한 학기의 마지막 장면으로 이어집니다.