The Loading Architecture: How Claude Reads Your Files
로딩 아키텍처 — Claude는 파일들을 어떻게 읽는가
Claude가 세션 시작 시 어떤 순서로 어떤 파일들을 로드하는지 정확히 이해하면, 규칙의 범위와 우선순위를 의도대로 설계할 수 있다.
Overview
Claude Code가 실행되면 내부적으로 일련의 파일 로딩 시퀀스가 시작된다. 이 시퀀스의 순서와 우선순위를 이해하는 것은 단순한 호기심을 넘어 실용적인 설계 결정에 영향을 미친다. 중요한 규칙을 어디에 두어야 하는가? 팀 규칙과 개인 규칙을 어떻게 분리하는가? 특정 서브디렉토리에만 적용되는 규칙은 어디에 두는가?
이 챕터는 Claude Code의 파일 로딩 메커니즘을 정밀하게 분해한다. 문서에 명시된 것과 실제 동작 사이의 미묘한 차이, 특히 '지연 로딩'의 함의를 깊이 이해하면 더 신뢰할 수 있는 설정 아키텍처를 만들 수 있다.
- 글로벌, 프로젝트, 로컬, 서브디렉토리 CLAUDE.md의 차이와 우선순위를 설명한다
- 서브디렉토리 CLAUDE.md가 지연 로딩되는 이유와 그 함의를 이해한다
- settings.json 파일 5단계 우선순위를 정확히 안다
- 팀 공유 규칙과 개인 규칙을 어떻게 분리해야 하는지 설계할 수 있다
- CLAUDE_CODE_ADDITIONAL_DIRECTORIES 환경 변수의 동작을 이해한다
Sections
CLAUDE.md 4계층 로딩 순서
Claude Code는 세션 시작 시 다음 순서로 CLAUDE.md 파일들을 로드한다:
| 계층 | 위치 | 범위 | Git 커밋 |
|---|---|---|---|
| 글로벌 | ~/.claude/CLAUDE.md |
모든 프로젝트 | N/A (개인 기기) |
| 프로젝트 | .claude/CLAUDE.md 또는 루트 CLAUDE.md |
이 저장소 | 예 (팀 공유) |
| 로컬 | .claude/CLAUDE.md.local |
이 저장소 | 아니오 (gitignore) |
| 서브디렉토리 | any/sub/dir/CLAUDE.md |
해당 경로 접근 시 | 선택적 |
우선순위는 구체적인 것이 일반적인 것을 오버라이드한다. 같은 규칙이 글로벌과 프로젝트 CLAUDE.md에 충돌되게 있으면, 프로젝트 규칙이 이긴다.
또한 조상 경로도 탐색된다. ~/projects/myapp/src/api/ 디렉토리에서 작업 중이라면, Claude는 src/api/CLAUDE.md, src/CLAUDE.md, CLAUDE.md를 순서대로 찾는다. 이 ancestor walk가 모노레포에서 유용하다 — 패키지별 규칙과 저장소 전체 규칙을 자연스럽게 계층화할 수 있다.
서브디렉토리의 지연 로딩 — 핵심 함정
이 동작을 모르면 규칙이 작동하지 않는다고 착각할 수 있다.
서브디렉토리 CLAUDE.md는 세션 시작 시 로드되지 않는다. Claude의 도구(Read, Edit, Write, Bash)가 해당 경로의 파일에 실제로 접근할 때 비로소 로드된다.
즉:
src/api/CLAUDE.md에 있는 규칙은 세션 시작 시 없다- Claude가
src/api/아래의 파일을 읽거나 편집할 때 로드된다 - 그 이전에 일어난 대화나 결정에는 영향을 주지 않는다
이 함의는 중요하다: 세션 초반에 영향을 주어야 하는 규칙은 루트 레벨 CLAUDE.md에 두어야 한다. 예를 들어 '이 프로젝트에서 API 에러는 AppError 클래스를 써야 한다'는 규칙을 src/api/CLAUDE.md에만 두면, Claude가 API 파일을 처음 편집하기 전까지 그 규칙을 모른다.
InstructionsLoaded 훅은 이 지연 로딩 이벤트에 반응할 수 있다 — 새로운 CLAUDE.md가 로드될 때마다 특정 동작을 트리거할 수 있다.
settings.json 5단계 우선순위 체계
CLAUDE.md와 달리, settings.json은 훨씬 복잡한 우선순위 체계를 가진다:
| 우선순위 | 위치 | 설명 |
|---|---|---|
| 1 (최고) | Managed/IT policy | 기업 IT 정책, 사용자가 오버라이드 불가 |
| 2 | CLI arguments | claude --permission-mode plan 등 |
| 3 | ~/.claude/settings.json |
사용자 글로벌 설정 |
| 4 | .claude/settings.json |
프로젝트 설정 (git 커밋) |
| 5 (최저) | .claude/settings.local.json |
프로젝트 로컬 설정 (gitignore) |
실시간 리로드: Claude Code는 settings 파일들을 감시(watch)하고 세션 도중 변경이 감지되면 즉시 리로드한다. 재시작 없이 설정이 반영된다. ConfigChange 훅이 이 리로드 이벤트에 반응할 수 있다.
팀 설정의 모범 사례: 팀 전체에 적용되어야 하는 hooks와 permissions는 .claude/settings.json에 (git 커밋), 개인의 모델 선호나 개인 hooks는 ~/.claude/settings.json에, 이 프로젝트에 대한 개인 오버라이드는 .claude/settings.local.json에 (gitignore) 넣는다.
추가 디렉토리와 멀티 저장소 설계
단일 저장소를 넘어서는 경우 — 여러 저장소를 동시에 작업하거나, 공유 라이브러리를 참조하는 경우 — --add-dir 플래그를 사용해 추가 디렉토리를 Claude의 범위에 포함할 수 있다.
claude --add-dir ~/shared-utils/
중요한 gotcha: --add-dir로 추가된 디렉토리의 CLAUDE.md는 기본적으로 로드되지 않는다. 환경 변수 CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1을 설정해야 추가된 디렉토리의 CLAUDE.md도 로드된다.
모노레포 설계 패턴:
/monorepo/
├── CLAUDE.md ← 전체 저장소 공통 규칙
├── .claude/settings.json ← 팀 설정
├── packages/
│ ├── api/
│ │ └── CLAUDE.md ← API 패키지 특화 규칙
│ └── frontend/
│ └── CLAUDE.md ← 프론트엔드 특화 규칙
└── .claude/
└── CLAUDE.md.local ← 개인 설정 (gitignored)
이 구조에서 공통 규칙은 루트에, 패키지별 규칙은 패키지 안에. 루트 규칙이 항상 로드되고, 패키지 규칙은 해당 패키지 파일에 접근할 때 추가로 로드된다.
법률 시스템을 생각해보자. 헌법이 있고, 그 아래에 법률이 있고, 그 아래에 시행령이 있다. 충돌이 있으면 상위 법령이 우선한다. 하지만 시행령은 법률이 다루지 않는 구체적인 사항을 규정할 수 있다.
Claude Code의 설정 계층도 정확히 이와 같다. 글로벌 CLAUDE.md는 헌법이다 — 모든 프로젝트에 적용되는 기본 원칙. 프로젝트 CLAUDE.md는 법률 — 이 저장소에 특화된 규칙. 서브디렉토리 CLAUDE.md는 시행령 — 특정 모듈이나 컴포넌트에만 적용되는 세부 규정.
그리고 헌법보다도 높은 곳에 기업 IT 정책(managed settings)이 있다 — 어떤 사용자도 오버라이드할 수 없는 절대적 제약. 이 계층을 이해하면, 어떤 규칙을 어느 레벨에 두어야 하는지 직관적으로 알 수 있다.
실제 모노레포에서 CLAUDE.md 계층을 어떻게 설계하는지, 그리고 각 파일이 어느 시점에 로드되는지를 보여주는 예제다.
# 모노레포 구조 설계
# /workspace/myapp/
# 1. 루트 CLAUDE.md — 세션 시작 시 즉시 로드
cat > CLAUDE.md << 'EOF'
# MyApp 공통 규칙 (모든 패키지 적용)
## 절대 금지
- any 타입 사용 금지
- console.log 프로덕션 코드 금지
- 직접 push to main 금지 (PR 필수)
## 변경 후 반드시
1. pnpm typecheck
2. pnpm test
EOF
# 2. API 패키지 CLAUDE.md — api/ 파일 접근 시 지연 로드
cat > packages/api/CLAUDE.md << 'EOF'
# API 패키지 규칙 (루트 규칙에 추가됨)
## API 특화 규칙
- 모든 에러: AppError 클래스 사용 (src/errors.ts 참조)
- 인증이 필요한 엔드포인트: requireAuth 미들웨어 필수
- DB 쿼리: Prisma ORM만 사용, raw query 금지
EOF
# 3. 팀 공유 settings.json — git 커밋
cat > .claude/settings.json << 'EOF'
{
"permissions": {
"allow": ["Bash(pnpm *)", "Bash(git status)", "Bash(git diff *)"],
"deny": ["Bash(git push --force *)", "Bash(rm -rf *)"]
}
}
EOF
# 4. 개인 로컬 설정 — gitignore에 추가
echo '.claude/settings.local.json' >> .gitignore
cat > .claude/settings.local.json << 'EOF'
{
"model": "claude-opus-4-7",
"env": {
"ANTHROPIC_MODEL": "claude-opus-4-7"
}
}
EOF
echo 'CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1' >> .env.local 이 구조의 핵심은 각 파일이 로드되는 타이밍이다. 루트 CLAUDE.md는 항상 로드되므로 전체에 적용되어야 하는 금지 사항들이 들어간다. API 패키지 CLAUDE.md는 API 파일에 처음 접근할 때 로드되므로 API 특화 규칙이 들어간다. settings.json은 팀 공유 설정(git 커밋)이고, settings.local.json은 개인 취향(gitignore)이다.
✅ 시니어가 보는 것
- 팀 공유 settings.json과 개인 settings.local.json의 적절한 분리
- 서브디렉토리 CLAUDE.md의 지연 로딩을 고려한 규칙 배치
- 모노레포에서의 계층적 규칙 설계 경험
⚠️ 레드 플래그
- 중요한 규칙을 서브디렉토리 CLAUDE.md에만 두고 작동 안 한다고 혼란스러워하는 경우
- settings.json을 git에 커밋하지 않아 팀원마다 다른 권한이 설정된 경우
- 글로벌과 프로젝트 CLAUDE.md에 중복 규칙이 많은 경우
🎤 예상 인터뷰 질문
- 서브디렉토리 CLAUDE.md의 지연 로딩이 실제 문제를 일으킨 경험이 있나요?
- 팀 공유 설정과 개인 설정을 어떻게 구조화하시나요?
- 모노레포에서 패키지별로 다른 규칙이 필요할 때 어떻게 설계하시나요?
Key Takeaways
4계층 로딩 순서를 외워라
글로벌 → 프로젝트 → 로컬 → 서브디렉토리(지연). 더 구체적인 것이 더 일반적인 것을 오버라이드한다.
서브디렉토리는 지연 로딩이다
세션 초반에 영향을 줘야 하는 규칙은 반드시 루트 레벨에 두어야 한다.
settings.json 5단계 체계
Managed > CLI > 사용자 global > 프로젝트 > 로컬. 팀 공유는 프로젝트에, 개인 취향은 로컬에.
실시간 리로드를 활용하라
settings.json 변경은 재시작 없이 즉시 반영된다. ConfigChange 훅으로 리로드 이벤트에 반응할 수 있다.
모노레포는 계층을 활용하라
공통 규칙은 루트에, 패키지별 규칙은 패키지 안에. Ancestor walk가 두 계층을 자동으로 합성해준다.