Tips & Tricks (업데이트: 2026. 6. 1.)

Claude Code 보안 완전 가이드: API 키 관리, 권한 설정, 프로덕션 보호

Claude Code를 안전하게 사용하기 위한 실전 보안 가이드. API 키 관리부터 권한 설정, Hooks 기반 자동화, 프로덕션 환경 보호까지 — 바로 동작하는 코드 예제와 함께 설명합니다.

Claude Code 보안 완전 가이드: API 키 관리, 권한 설정, 프로덕션 보호

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: "PASTE_REAL_API_KEY_HERE" });

// ❌ CLAUDE.md나 설정 파일에 작성
// ANTHROPIC_API_KEY=PASTE_REAL_API_KEY_HERE

// ❌ claude -p 프롬프트 안에 작성
// QIITA_TOKEN=PASTE_REAL_TOKEN_HERE를 사용해서 Qiita에 게시해줘

올바른 관리 방법

# .env (git 관리 외, 로컬 머신에만 저장)
ANTHROPIC_API_KEY=<anthropic-api-key>
QIITA_TOKEN=<qiita-token>
SLACK_BOT_TOKEN=<slack-bot-token>
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: /\b(?:ANTHROPIC_API_KEY|CLAUDE_API_KEY)\s*[:=]\s*["']?[^"'\s]{20,}/i },
  { name: "OpenAI API 키 설정", re: /\bOPENAI_API_KEY\s*[:=]\s*["']?[^"'\s]{20,}/i },
  { name: "AWS 액세스 키", re: /\bAKIA[0-9A-Z]{16}\b/ },
  { name: "Slack 토큰", re: /\bxox[baprs]-[0-9A-Za-z-]{10,}\b/ },
  { name: "범용 시크릿", re: /\b(?:secret|token|api[_-]?key|password)\s*[:=]\s*["'][^"']{10,}["']/i },
];

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의 권한 설정

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "defaultMode": "default",
    "disableBypassPermissionsMode": "disable",
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "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*)"
    ]
  },
  "disableAutoMode": "disable"
}
설정의미
allow확인 없이 실행
deny일절 실행 불가 (거부)
ask매번 승인 필요

포인트: 파괴적 명령은 deny, 쓰기 계열은 ask, 읽기 계열은 allow가 기본 분류입니다.

프로덕션과 조직 정책은 local 또는 managed settings로 분리

공식 Docs의 설정 스코프는 managed, 명령줄 인수, local, project, user 순서로 적용됩니다. 비공식적인 커스텀 파일 전환에 기대기보다, 개인의 프로덕션 유지보수 단말에서는 .claude/settings.local.json, 조직에서는 managed settings를 사용하는 편이 공식 동작에 맞습니다.

.claude/settings.local.json은 로컬 전용 오버라이드로 사용하고 git에 커밋하지 않습니다.

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "defaultMode": "plan",
    "disableBypassPermissionsMode": "disable",
    "allow": ["Read(**)", "Glob(**)", "Grep(**)", "Bash(git log*)", "Bash(git diff*)"],
    "deny": ["Write(**)", "Edit(**)", "Bash(git push*)", "Bash(rm*)", "Bash(*deploy*)"],
    "ask": []
  },
  "disableAutoMode": "disable"
}

팀이나 회사 정책으로 강제하려면 managed settings에 둡니다. allowManagedPermissionRulesOnly를 켜면 사용자와 프로젝트 저장소가 자체 allow / ask / deny 규칙으로 조직 정책을 우회할 수 없습니다.

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl *)"
    ],
    "disableBypassPermissionsMode": "disable"
  },
  "disableAutoMode": "disable",
  "allowManagedPermissionRulesOnly": true
}

대책 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에서 헤드리스 실행 중에 sudovim 등 대화형 입력이 필요한 명령이 섞이면 프로세스가 멈춥니다. 비대화형 명령만 사용하세요.

4. 에러 메시지에 인증 정보 포함

// ❌ 위험: API 키가 로그에 출력됨
throw new Error(`인증 실패: token=${process.env.TOKEN}`);

// ✅ 안전: 값을 출력하지 않음
throw new Error(`인증 실패: TOKEN 환경 변수를 확인해주세요`);

5. 전 프로젝트에서 같은 권한 설정을 재사용 취미 프로젝트와 업무 프로젝트에서 같은 settings.json을 사용하면, 업무 측에서 필요한 제한이 취미 측의 느슨한 설정으로 덮어써집니다. 프로젝트마다 .claude/settings.json을 관리하세요.

실무에서 지킬 운영 규칙

비밀 정보를 Claude Code에 넘기지 않기

Claude Code에 “이 오류를 고쳐줘”라고 요청할 때 전체 로그나 .env 내용을 그대로 붙여넣으면 위험합니다. API 키, OAuth 토큰, cookie, DB 연결 문자열, 고객 이메일, 결제 ID, private key는 prompt, issue comment, 채팅 로그에 넣지 않는다는 규칙을 먼저 정하세요.

맥락이 필요하면 값은 ***REDACTED***로 바꾸고 구조만 남깁니다. 예를 들어 DATABASE_URL=***REDACTED***이면 Claude Code는 DB 연결 설정이 있다는 사실만 이해하면 됩니다. 실제 값은 대부분의 디버깅에 필요하지 않습니다.

전달해도 되는 정보전달하면 안 되는 정보
오류 종류, stack trace의 파일명, 재현 절차API 키, private key, session cookie, 실제 .env
.env.example, 설정 항목명, 권한 규칙, 실패한 명령프로덕션 DB URL, 고객 데이터, 내부 인증 정보
마스킹된 로그, 테스트 데이터, 로컬 샘플 값실제 토큰, 서비스 계정 JSON, 비밀 정보가 보이는 스크린샷

이 표를 CLAUDE.md에 넣어두면 세션마다 같은 기준으로 시작할 수 있습니다. 팀에서는 “비밀 정보를 노출하지 않는다”를 개인 판단이 아니라 운영 규칙으로 만들어야 합니다.

커밋 전 스캔은 중복해서 걸기

위의 PreToolUse Hook은 Claude Code가 git commit을 실행할 때 막아줍니다. 하지만 사람이 다른 터미널에서 커밋하거나 CI가 생성한 파일에 비밀 정보가 섞일 수 있습니다. 실무에서는 Claude Code Hook, 로컬 pre-commit, CI secret scan을 겹쳐 둡니다.

최소 구성은 로컬 Hook으로 한 번 막고, CI에서 다시 검사하며, secret pattern이 나오면 merge를 실패시키는 것입니다. gitleaks나 trufflehog 같은 전용 도구는 CI 규모의 감지에 적합하고, 이 글의 스크립트는 빠른 로컬 가드로 유용합니다.

구체적인 실패 예

실패 1: 조사 중 .env를 읽게 한 경우 개발자가 “환경 변수를 확인해줘”라고 요청했고 실제 값이 대화나 작업 로그에 남았습니다. 대책은 .env 읽기를 deny하고 .env.example만 제공하는 것입니다.

실패 2: Qiita 게시 토큰을 prompt에 붙인 경우 자동 게시 작업에서 QIITA_TOKEN을 prompt에 직접 넣어 subagent나 로그 파일에 남을 가능성이 생겼습니다. 더 안전한 흐름은 토큰을 .env에 두고 명령은 환경 변수명만 참조하게 하는 것입니다.

실패 3: 프로덕션과 스테이징 DB URL이 비슷한 경우 지시가 “DB를 정리해줘”뿐이고 연결 대상 확인을 생략했습니다. 프로덕션 URL이 활성화되어 있으면 삭제나 migration이 사고가 됩니다. 쓰기 작업 전에는 NODE_ENV, host, DB명을 출력하고 명시적 사용자 확인을 요구하세요.

사고 후 첫 대응

비밀 정보가 유출된 것 같다면 첫 단계는 히스토리 정리가 아니라 credential 비활성화입니다.

  1. 관련 API 키, 토큰, 비밀번호를 즉시 rotate 또는 revoke
  2. GitHub Actions, Cloudflare, AWS, GCP, SaaS audit log 확인
  3. 누가, 언제, 어떤 저장소에서, 어떤 채널로 무엇을 노출했는지 기록
  4. git history와 로그에서 secret을 삭제하고 force push 영향 공유
  5. deny 규칙, Hooks, CI scan, CLAUDE.md 금지사항을 강화

실제로 적용해 보면 credential을 먼저 멈추고 history를 나중에 정리하는 편이 실수를 줄입니다. 사고 대응 중에는 도움을 주려다 원본 로그를 다시 붙이기 쉬우므로, 마스킹 로그 템플릿을 미리 준비해 두세요.

교재와 상담으로 이어지는 흐름

Claude Code 보안은 하나의 settings 파일로 끝나지 않습니다. 저장소 구조, CI, 배포 권한, 팀 승인 플로우까지 함께 봐야 실제 구멍이 줄어듭니다.

ClaudeCodeLab의 개인 개발자용 학습 흐름은 .env 관리와 permission rules부터 시작합니다. 팀 도입 상담에서는 managed settings를 어디에서 강제할지, CI secret scan을 어디에서 merge block으로 둘지부터 확인합니다. 이미 업무에서 Claude Code를 쓰고 있다면, 권한을 손보기 전에 누가 어떤 비밀 정보에 접근할 수 있는지부터 정리하는 것이 현실적입니다.

보안 체크리스트

Claude Code 프로젝트 도입 시 확인 목록:

### 기본 설정
- [ ] .env 생성하고 .gitignore에 추가 완료
- [ ] .env.example 생성하고 팀 공유 완료
- [ ] git log로 기존 커밋에 비밀 정보 없는지 확인

### 권한 설정
- [ ] .claude/settings.json에 deny 리스트 설정
- [ ] 파괴적 명령 (rm -rf, DROP TABLE 등)을 deny에 추가
- [ ] 프로덕션 배포 명령을 ask에 설정

### 자동화
- [ ] 커밋 전 시크릿 스캔 Hook 설정
- [ ] CLAUDE.md에 보안 금지 사항 기재

### 운용
- [ ] API 키 로테이션 주기 결정 (권장: 90일)
- [ ] 프로덕션 작업은 .claude/settings.local.json 또는 managed settings로 제한
- [ ] 인시던트 발생 시 대처 플로우 문서화

정리

Claude Code의 보안은 “제한을 부과하는” 것이 아니라 “사고가 일어나지 않는 구조를 만드는” 것입니다.

위협대책
API 키 유출.env + .gitignore + 시크릿 스캔 Hook
의도하지 않은 삭제deny 리스트 + 삭제 전 Hook
프로덕션 오조작local/managed settings + CLAUDE.md 금지
커밋 오염PreToolUse Hook으로 커밋 전 스캔

설정은 한 번 넣으면 메인터넌스 프리입니다. 오늘 30분 투자하면 미래의 큰 사고를 막을 수 있습니다.

관련 글

참고 자료

#claude-code #security #api-key #permissions #devops #best-practices
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.