Claude Code 보안 완전 가이드: API 키 관리, 권한 설정, 프로덕션 보호
Claude Code를 안전하게 사용하기 위한 실전 보안 가이드. API 키 관리부터 권한 설정, Hooks 기반 자동화, 프로덕션 환경 보호까지 — 바로 동작하는 코드 예제와 함께 설명합니다.
Claude Code는 강력한 파일 조작 및 명령 실행 능력을 갖추고 있지만, 잘못된 설정은 되돌릴 수 없는 사고로 이어질 수 있습니다. .env 파일 커밋, 프로덕션 DB 실수 삭제, API 키 로그 출력 — 이것들은 모두 Claude Code를 무방비 상태로 사용한 결과로 발생한 실제 사례입니다.
이 글에서는 Claude Code를 안전하게 사용하기 위한 보안 대책을 구현 수준에서 설명합니다. 개념 설명보다는 바로 복사해서 사용할 수 있는 설정과 예방 코드를 중심으로 정리했습니다.
Claude Code에 보안 대책이 필요한 이유
일반 텍스트 에디터와 달리, Claude Code는 다음과 같은 권한을 가집니다.
- 임의 파일 읽기·쓰기·삭제 (
Read/Write/Edit/Bash(rm)) - 셸 명령 실행 (
Bash) - 네트워크 액세스 (
WebFetch/ API 호출) - 외부 서비스 게시 (GitHub, Slack 등)
이것들은 모두 사용자가 승인만 하면 실행됩니다. 문제는 “승인을 기계적으로 계속 OK하면 의도하지 않은 조작이 통과된다”는 것입니다. 보안 대책이란 “실수가 끼어들 여지를 구조적으로 없애는” 작업입니다.
대책 1: API 키 관리 — .env + .gitignore가 기본
해서는 안 되는 예시
// ❌ 소스 코드에 직접 작성
const client = new Anthropic({ apiKey: "sk-ant-api03-..." });
// ❌ CLAUDE.md나 설정 파일에 작성
// ANTHROPIC_API_KEY=sk-ant-api03-...
// ❌ claude -p 프롬프트 안에 작성
// QIITA_TOKEN=abc123을 사용해서 Qiita에 게시해줘
올바른 관리 방법
# .env (git 관리 외, 로컬 머신에만 저장)
ANTHROPIC_API_KEY=sk-ant-api03-...
QIITA_TOKEN=06b4441b...
SLACK_BOT_TOKEN=xoxb-...
DATABASE_URL=postgresql://...
# .gitignore에 반드시 추가
.env
.env.*
.env.local
!.env.example # ← 샘플만은 OK
*.pem
*.key
credentials.json
*-service-account.json
# .env.example (git 관리 OK, 값은 비워둠)
ANTHROPIC_API_KEY=
QIITA_TOKEN=
SLACK_BOT_TOKEN=
DATABASE_URL=
코드에서의 읽기
// ✅ 환경 변수에서 읽기
import { config } from "dotenv";
config();
const token = process.env.QIITA_TOKEN;
if (!token) throw new Error("QIITA_TOKEN이 설정되어 있지 않습니다. .env를 확인해주세요.");
CLAUDE.md에 금지 사항으로 명시
## 보안 금지 사항
- API 키·토큰을 프롬프트에 포함하지 않음
- .env 파일을 읽어서 내용을 출력하지 않음
- 환경 변수 값을 로그나 주석에 작성하지 않음
- process.env의 내용을 console.log 하지 않음
대책 2: 커밋 전 비밀 정보 스캔
.env를 gitignore해도, 다른 파일에 잘못 기재하거나 복사·붙여넣기 누락은 방지할 수 없습니다. 커밋 전 자동 스캔 체계를 도입합시다.
Hooks로 커밋 전 체크
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit*)",
"hooks": [
{
"type": "command",
"command": "node scripts/secret-scan.mjs"
}
]
}
]
}
}
scripts/secret-scan.mjs:
import { execSync } from "child_process";
// 스테이징된 변경 사항 가져오기
const diff = execSync("git diff --cached").toString();
const PATTERNS = [
{ name: "Anthropic API 키", re: /sk-ant-api\d+-[A-Za-z0-9_-]{80,}/ },
{ name: "OpenAI API 키", re: /sk-[A-Za-z0-9]{48}/ },
{ name: "AWS 액세스 키", re: /AKIA[0-9A-Z]{16}/ },
{ name: "Slack 토큰", re: /xox[baprs]-[0-9A-Za-z-]{10,}/ },
{ name: "Generic 시크릿", re: /[Ss]ecret[_-]?[Kk]ey\s*[:=]\s*['"][^'"]{10,}['"]/ },
];
const found = PATTERNS.filter(({ re }) => re.test(diff));
if (found.length > 0) {
console.error("🚨 시크릿 감지! 커밋을 중단합니다:");
found.forEach(({ name }) => console.error(` - ${name}`));
console.error("\n대처법: git reset HEAD <file>로 unstage 해주세요");
process.exit(1); // 종료 코드 1 → Hook이 명령을 블록
}
console.log("✓ 시크릿 스캔: 문제 없음");
process.exit(0);
이로써 git commit을 Claude Code가 실행하려는 순간 자동 스캔이 작동하고, 유출이 감지된 경우 블록됩니다.
대책 3: 권한 모드 설정
Claude Code의 허용·거부는 파일 수준에서 세밀하게 제어할 수 있습니다.
.claude/settings.json의 권한 설정
{
"permissions": {
"allow": [
"Read(**)",
"Glob(**)",
"Grep(**)"
],
"deny": [
"Bash(rm -rf*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(DROP TABLE*)",
"Bash(truncate*)",
"Bash(curl * | bash)",
"Bash(wget * | sh)"
],
"ask": [
"Write(**)",
"Edit(**)",
"Bash(git commit*)",
"Bash(git push*)",
"Bash(npm publish*)",
"Bash(wrangler pages deploy*)"
]
}
}
| 설정 | 의미 |
|---|---|
allow | 확인 없이 실행 |
deny | 일절 실행 불가 (거부) |
ask | 매번 승인 필요 |
포인트: 파괴적 명령은 deny, 쓰기 계열은 ask, 읽기 계열은 allow가 기본 분류입니다.
프로덕션 환경 전용 설정 파일
프로덕션 환경에서는 읽기 전용으로 한정하는 것이 안전합니다.
// .claude/settings.production.json
{
"permissions": {
"allow": ["Read(**)", "Glob(**)", "Grep(**)", "Bash(git log*)", "Bash(git diff*)"],
"deny": ["Write(**)", "Edit(**)", "Bash(git push*)", "Bash(rm*)", "Bash(*deploy*)"],
"ask": []
}
}
# 프로덕션 작업 시 명시적으로 지정
CLAUDE_SETTINGS=.claude/settings.production.json claude
대책 4: 프로덕션 환경 보호
연결 대상을 명시적으로 분리
## CLAUDE.md — 프로덕션 환경 규칙
## 환경 판정
- DATABASE_URL에 'prod' 또는 'production'이 포함된 경우 **프로덕션 환경**
- 프로덕션 환경에서는 절대로 실행하지 않음:
- DROP / TRUNCATE / DELETE (WHERE 없이)
- 마이그레이션 (사전 확인 필수)
- 파일 일괄 삭제
## 확인 플로우
프로덕션 변경은 반드시:
1. 스테이징 환경에서 테스트
2. 사용자에게 확인 받기
3. 실행 후 결과 보고
환경 변수로 연결 대상 제어
// scripts/db-query.mjs
const env = process.env.NODE_ENV ?? "development";
const dbUrl = process.env.DATABASE_URL;
if (env === "production" && process.argv.includes("--write")) {
console.error("❌ 프로덕션 환경에 쓰기는 --force-production 플래그가 필요합니다");
process.exit(1);
}
대책 5: 파일 조작 안전 장치
삭제 전 백업 자동화
// .claude/settings.json의 Hooks
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(rm *)",
"hooks": [
{
"type": "command",
"command": "echo '⚠️ 삭제 명령이 실행되려 합니다. Ctrl+C로 중지할 수 있습니다.' && sleep 3"
}
]
}
]
}
}
중요 파일을 실수 편집으로부터 보호
## CLAUDE.md — 변경 금지 파일
다음 파일은 **절대로 편집하지 않음**:
- .env (환경 변수, 비밀 키 포함)
- wrangler.toml (Cloudflare 프로덕션 설정)
- scripts/deploy.sh (배포 스크립트)
- .github/workflows/*.yml (CI/CD 설정)
변경이 필요한 경우 사용자에게 확인 받을 것.
함정 5가지
1. .gitignore를 나중에 추가해도 이미 늦음
이미 커밋된 .env는 gitignore를 추가해도 git 히스토리에 남습니다.
# 히스토리에서 완전 삭제 (주의: force push 필요)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# 또는 BFG Repo Cleaner 사용
GitHub에 이미 푸시한 경우는 반드시 API 키를 로테이션한 후 대처하세요.
2. 서비스 계정 JSON을 저장소에 배치
Google Cloud나 AWS의 서비스 계정 키는 .json으로 배포되는 경우가 많지만, 저장소에 두는 것은 위험합니다. 환경 변수화하거나 Secret Manager (AWS Secrets Manager / GCP Secret Manager)로 이전하세요.
3. Bash 도구에서 대화형 명령 실행
claude -p에서 헤드리스 실행 중에 sudo나 vim 등 대화형 입력이 필요한 명령이 섞이면 프로세스가 멈춥니다. 비대화형 명령만 사용하세요.
4. 에러 메시지에 인증 정보 포함
// ❌ 위험: API 키가 로그에 출력됨
throw new Error(`인증 실패: token=${process.env.TOKEN}`);
// ✅ 안전: 값을 출력하지 않음
throw new Error(`인증 실패: TOKEN 환경 변수를 확인해주세요`);
5. 전 프로젝트에서 같은 권한 설정을 재사용
취미 프로젝트와 업무 프로젝트에서 같은 settings.json을 사용하면, 업무 측에서 필요한 제한이 취미 측의 느슨한 설정으로 덮어써집니다. 프로젝트마다 .claude/settings.json을 관리하세요.
보안 체크리스트
Claude Code 프로젝트 도입 시 확인 목록:
### 기본 설정
- [ ] .env 생성하고 .gitignore에 추가 완료
- [ ] .env.example 생성하고 팀 공유 완료
- [ ] git log로 기존 커밋에 비밀 정보 없는지 확인
### 권한 설정
- [ ] .claude/settings.json에 deny 리스트 설정
- [ ] 파괴적 명령 (rm -rf, DROP TABLE 등)을 deny에 추가
- [ ] 프로덕션 배포 명령을 ask에 설정
### 자동화
- [ ] 커밋 전 시크릿 스캔 Hook 설정
- [ ] CLAUDE.md에 보안 금지 사항 기재
### 운용
- [ ] API 키 로테이션 주기 결정 (권장: 90일)
- [ ] 프로덕션 환경은 전용 settings.production.json 사용
- [ ] 인시던트 발생 시 대처 플로우 문서화
정리
Claude Code의 보안은 “제한을 부과하는” 것이 아니라 “사고가 일어나지 않는 구조를 만드는” 것입니다.
| 위협 | 대책 |
|---|---|
| API 키 유출 | .env + .gitignore + 시크릿 스캔 Hook |
| 의도하지 않은 삭제 | deny 리스트 + 삭제 전 Hook |
| 프로덕션 오조작 | 프로덕션 전용 settings + CLAUDE.md 금지 |
| 커밋 오염 | PreToolUse Hook으로 커밋 전 스캔 |
설정은 한 번 넣으면 메인터넌스 프리입니다. 오늘 30분 투자하면 미래의 큰 사고를 막을 수 있습니다.
관련 글
참고 자료
Claude Code 워크플로우를 한 단계 업그레이드하세요
지금 바로 Claude Code에 복사해 쓸 수 있는 검증된 프롬프트 템플릿 50선.
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code 보안 실패 사례 7선 | 실제 발생한 사고와 방지책
Claude Code에서 실제로 발생한 보안 사고 7가지: .env 유출, 운영 DB 실수 삭제, 과금 폭발 등 — 각 사례별 원인과 재발 방지 코드를 상세히 해설합니다.
Claude Code 권한 설정 완벽 가이드 | settings.json·Hooks·allowlist 철저 해설
Claude Code 권한 설정 완벽 해설. allow/deny/ask 구분 사용법, Hooks를 활용한 자동화, 환경별 settings.json, 실전 패턴 모음까지 동작하는 코드로 소개합니다.
하네스 엔지니어링 완전 가이드 | Claude Code로 배우는 AI 에이전트 만들기
프롬프트만으로는 LLM을 제대로 다룰 수 없다. 도구·컨텍스트·제어 루프를 엮는 '하네스'를 실행 가능한 코드와 Claude Code의 설계로 차근차근 해부한다.