토큰 누수 방지: 파일 탐색 및 읽기 제어 가이드 (Claude Code)
AI 코딩 어시스턴트 사용 시 토큰 비용이 예상보다 많이 나온다면? 범인은 내가 시킨 작업이 아니라, AI가 몰래 읽고 있는 거대한 파일들일 수 있다. 이 글에서는 '토큰 뱀파이어'를 식별하고, Claude Code의 파일 접근을 완벽하게 통제하는 기술적 방법을 소개한다.
1. 핵심 문제: '토큰 뱀파이어' (Token Vampires) 식별
AI가 코드를 읽을 때 가장 큰 비용이 발생하는 것은 "내가 시킨 파일"이 아니라 "AI가 스스로 탐색하다가 실수로 읽은 파일"이다. 이를 '토큰 뱀파이어'라고 부른다.
가장 위험한 경로들 (The Usual Suspects)
node_modules/(및vendor/,.venv/): 가장 치명적이다. 라이브러리 내부 코드를 읽기 시작하면 수만 토큰이 순식간에 증발한다. 한 사례에서는 전체 토큰 소모의 85%가node_modules스캔에서 발생하기도 했다.package-lock.json/yarn.lock: 이 파일들은 수만 줄에 달한다. 의존성을 확인하려다 이 파일을 통째로 읽으면 컨텍스트가 꽉 찬다.- 빌드 아티팩트 (
dist/,build/,.next/): 소스 코드가 아닌 컴파일된(난독화된) 코드를 읽는 것은 아무런 의미가 없으며 비용만 발생시킨다. - 로그 및 데이터 파일 (
*.log,*.csv,*.json): 테스트 로그나 대용량 데이터 덤프 파일을 읽지 않도록 해야 한다.
2. 토큰 누수의 기술적 원인: "Bash는 권한을 우회한다"
많은 사용자가 .gitignore에 파일을 추가하거나 settings.json에서 Read 권한을 막으면 안전하다고 생각한다. 하지만 여기에 치명적인 맹점이 있다.
원인: 도구 분리 (Read vs Bash)
Claude Code의 권한 시스템은 Read() 도구와 Bash() 도구가 분리되어 있다.
permissions.deny에Read(node_modules)를 설정하면, Claude Code가 직접 파일을 여는 것은 막을 수 있다.- 하지만! Claude Code가
grep -r "pattern" .혹은find . -name "..."같은 Bash 명령어를 실행하면, 이 명령어는 시스템 쉘에서 실행되므로Read권한 설정을 우회하여node_modules내부의 텍스트를 출력 결과로 가져온다.
결과: 사용자는 파일을 열지 못하게 막았다고 생각하지만, 실제로는 터미널 명령어의 출력값(Output) 형태로 수천 줄의 node_modules 내용이 컨텍스트로 쏟아져 들어온다.
3. 해결 솔루션 A: 강력한 설정 (settings.json)
프로젝트 루트의 .claude/settings.json 파일을 통해 명시적으로 접근을 차단해야 한다. (단순히 .claudeignore 파일을 만드는 것만으로는 완벽하지 않을 수 있다는 리포트가 많다.)
추천 settings.json 설정 (복사/붙여넣기용):
{
"permissions": {
"deny": [
"Read(**/node_modules/**)",
"Read(**/package-lock.json)",
"Read(**/yarn.lock)",
"Read(**/.git/**)",
"Read(**/dist/**)",
"Read(**/build/**)",
"Read(**/*.log)",
"Read(**/coverage/**)",
"Bash(cat *lock.json)",
"Bash(grep * node_modules)"
]
}
}
- 포인트:
glob패턴(**)을 사용하여 하위 디렉토리까지 확실하게 잡아야 한다.
4. 해결 솔루션 B: Bash Hook을 이용한 원천 봉쇄 (고급)
위에서 언급한 "Bash 명령어를 통한 우회"를 막기 위해, 명령어가 실행되기 전에 가로채서 검사하는 Hook을 설정하는 것이 가장 확실한 방법이다.
1단계: 검증 스크립트 작성 (.claude/scripts/validate-bash.sh)
#!/bin/bash
# 입력된 명령어 가져오기
COMMAND=$(cat | jq -r '.tool_input.command')
# 차단할 키워드 목록 (정규표현식)
BLOCKED="node_modules|\.env|__pycache__|\.git/|dist/|build/|package-lock\.json"
if echo "$COMMAND" | grep -qE "$BLOCKED"; then
echo "ERROR: Blocked directory pattern detected in command." >&2
exit 2 # Claude Code에게 실행 거부를 알림
fi
2단계: Hook 등록 (.claude/settings.json)
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/scripts/validate-bash.sh"
}
]
}
]
}
}
효과: Claude Code가 grep -r "auth" .를 실행하려고 할 때, 이 스크립트가 명령어를 검사하고 node_modules가 포함되어 있지 않더라도, grep이 내부적으로 제외 처리를 안 했다면 경고를 줄 수 있다.
5. 해결 솔루션 C: 'Grep' 대신 'Semantic Search' (RAG) 활용
단순 문자열 검색(grep)은 문맥을 모르기 때문에 불필요한 파일을 많이 열어보게 만든다. 이를 시맨틱 검색(의미 기반 검색)으로 대체하면 파일 탐색 비용을 획기적으로 줄일 수 있다.
- 문제 상황: "인증 관련 로직 찾아줘"라고 하면
grep "auth"를 실행 -> 수백 개의 파일이 나옴 -> 하나씩 읽어봄 -> 토큰 폭발. - 해결: 로컬 RAG 도구(예:
mcp-ragex,greb등)를 MCP로 연결.- 사용자가 "인증 관련 로직"이라고 물으면 벡터 DB에서 정확히 관련된 파일 2~3개만 찾아서 가져온다.
- 데이터: 벤치마크 결과, 일반
grep대비 입력 토큰을 97% 절감 (51k 토큰 -> 1.3k 토큰)하고, 비용을 27.5% 절감하는 효과가 입증되었다.
6. 실무자를 위한 행동 강령 (Best Practices)
-
명시적 파일 지정 (@ 멘션):
- ❌ "로그인 버그 고쳐줘" (전체 탐색 유발)
- ✅ "@src/auth/login.ts 파일의 토큰 검증 로직을 확인해줘" (파일 직접 지정)
- 파일 경로를 모른다면
ls src/auth등을 먼저 시켜서 경로를 확인한 후 지정하는 것이 훨씬 저렴하다.
-
모노레포(Monorepo) 격리:
- 거대한 프로젝트의 루트에서 Claude Code를 실행하지 마라.
cd packages/frontend처럼 작업할 하위 폴더로 이동한 뒤 실행하면,find나grep의 범위가 해당 폴더로 제한되어 토큰 낭비를 막을 수 있다.
-
Ripgrep(rg) 사용 유도:
- Claude Code는 기본적으로
grep을 쓰려 할 수 있다. 시스템 프롬프트(CLAUDE.md)에 "파일 검색 시grep대신rg를 사용하고, 반드시.gitignore를 준수하라"는 규칙을 넣자.rg는 기본적으로.gitignore에 등록된 파일(node_modules 등)을 검색하지 않는다.
- Claude Code는 기본적으로
📝 요약 테이블 (Copy & Paste용)
| 전략 | 실행 방법 | 예상 절감 효과 | 난이도 |
|---|---|---|---|
| 1. 접근 차단 | settings.json에 node_modules, lock 파일 deny 설정 | ★★★★☆ (매우 높음) | 하 |
| 2. Bash 방어 | PreToolUse Hook으로 위험한 Bash 명령어 필터링 | ★★★★★ (완벽 방어) | 상 |
| 3. 도구 교체 | grep 대신 ripgrep (rg) 사용 강제 | ★★★☆☆ (높음) | 중 |
| 4. 범위 제한 | 작업할 하위 폴더로 cd 후 실행 (Workspace Isolation) | ★★★☆☆ (상황에 따라) | 하 |
| 5. 정밀 호출 | 프롬프트에 @파일명 직접 명시 | ★★★★☆ (습관 의존) | 하 |
이 데이터들을 활용하시면, 단순히 "아껴 쓰세요"가 아니라 "시스템적으로 토큰이 새나갈 구멍을 막는" 전문가 수준의 가이드를 구축할 수 있다.