Skip to content

Claude Code 조건부 규칙과 파일 참조

Published: at 05:27 PM

들어가며

21차시에서는 CLAUDE.md, 22차시에서는 Auto memory를 다뤘다. CLAUDE.md는 매 세션에 전체가 로드되고, Auto memory는 머신-로컬에 쌓인다.

그런데 프로젝트가 커질수록 CLAUDE.md 한 파일로는 부족해진다. TypeScript 작업할 때만 필요한 규칙, API 라우트 만질 때만 필요한 컨벤션, 테스트 파일에만 적용되는 패턴이 한 파일에 다 들어가면 — 매 세션마다 200줄, 300줄을 그대로 컨텍스트에 싣게 된다. 공식 문서가 200줄을 권장하는 이유다. 길수록 토큰을 더 먹고 준수율은 더 떨어진다.

이번 차시는 CLAUDE.md를 쪼개는 두 가지 메커니즘을 다룬다.

그리고 이 모든 걸 .claude/ 디렉토리째로 Git에 커밋하면 팀원이 클론만 해도 같은 규칙이 자동으로 적용된다.

CLAUDE.md만으로 부족해지는 순간

CLAUDE.md는 매 세션 시작 시 컨텍스트에 들어간다. 컨텍스트는 토큰이고 토큰은 비용이다. 그런데 길이만 문제가 아니라 준수율이 문제다.

공식 문서가 명시하는 권장 한도는 파일당 200줄이다. 그 이상이면 준수율이 떨어진다고 못박혀 있다. 또 CLAUDE.md는 시스템 프롬프트가 아니라 시스템 프롬프트 다음의 사용자 메시지로 주입된다. 강제 설정이 아니라 컨텍스트라는 뜻이다. 짧고 구체적일수록 따라온다.

길어지는 패턴은 대개 비슷하다.

이 모두가 한 CLAUDE.md에 쌓이면 어떻게 될까. 사용자가 README만 손보는 세션에서도 React 규칙과 테스트 규칙이 컨텍스트에 다 들어간다. 토큰 낭비도 낭비지만, Claude가 어떤 규칙을 적용할지 판단할 때 노이즈가 늘어나서 정작 중요한 지시를 흐리게 한다.

해결은 두 단계다.

  1. 토픽별로 파일을 쪼갠다.claude/rules/
  2. 특정 파일을 만질 때만 로드되게 한다paths: 프론트매터

.claude/rules/ 디렉토리

.claude/rules/는 CLAUDE.md를 토픽별로 쪼개기 위한 디렉토리다. 한 파일당 한 토픽, 파일명은 내용을 드러내게 짓는다.

your-project/
├── .claude/
│   ├── CLAUDE.md           # 핵심 지시
│   └── rules/
│       ├── code-style.md   # 코드 스타일
│       ├── testing.md      # 테스트 컨벤션
│       └── security.md     # 보안 규칙
└── src/

.md 파일은 재귀적으로 발견된다. 서브디렉토리를 만들어서 분야별로 묶어도 된다.

.claude/rules/
├── frontend/
│   ├── react.md
│   └── styling.md
├── backend/
│   ├── api.md
│   └── database.md
└── security.md

기본 동작은 단순하다. paths: 프론트매터가 없으면 매 세션 시작 시 무조건 로드된다. 우선순위는 .claude/CLAUDE.md와 같다. 즉 무조건 로드되는 rules 파일은 CLAUDE.md를 토픽별로 쪼갠 것에 지나지 않는다.

진짜 힘은 다음 절의 path-scoped rules에 있다.

path-scoped rules: 매칭 파일을 만질 때만 로드

paths: 프론트매터를 쓰면 특정 파일을 Claude가 읽을 때만 그 규칙이 로드된다. 매 세션 시작 시 로드되는 게 아니라, 매칭 파일을 읽는 순간 컨텍스트에 추가된다.

---
paths:
  - "src/api/**/*.ts"
---

# API 개발 규칙

- 모든 API 엔드포인트는 입력 검증 필수
- 에러 응답은 표준 포맷 사용
- OpenAPI 주석 포함

이 파일은 src/api/ 아래 .ts 파일을 Claude가 읽을 때만 로드된다. README만 손보는 세션에서는 컨텍스트에 들어가지 않는다. 트리거는 매 도구 호출이 아니라 매칭 파일을 읽는 시점이라는 점이 중요하다. Claude가 파일을 한 번 읽고 나면 그 세션 안에서는 규칙이 활성화된 상태로 유지된다.

글롭 패턴

paths:에는 글롭 패턴을 쓴다.

패턴매칭
**/*.ts모든 디렉토리의 TypeScript 파일
src/**/*src/ 아래 모든 파일
*.md프로젝트 루트의 마크다운
src/components/*.tsx특정 폴더의 React 컴포넌트

여러 패턴을 나열하거나 브레이스 확장으로 한 번에 묶을 수도 있다.

---
paths:
  - "src/**/*.{ts,tsx}"
  - "lib/**/*.ts"
  - "tests/**/*.test.ts"
---

무조건 로드 vs path-scoped 정리

종류프론트매터로드 시점우선순위
무조건paths: 없음매 세션 시작.claude/CLAUDE.md와 동등
path-scopedpaths: 있음매칭 파일을 읽을 때path-scoped 활성화 후에는 동등

경험칙: 매 세션에 필요한 핵심 규칙은 CLAUDE.md 또는 paths: 없는 rules에. 특정 영역을 만질 때만 필요한 규칙은 paths:가 있는 rules에.

실전 예시: TypeScript 규칙

---
paths:
  - "**/*.ts"
  - "**/*.tsx"
---

# TypeScript 규칙

- `any` 금지. 정말 모를 땐 `unknown`을 쓰고 좁혀라
- 모든 public 함수에 반환 타입 명시
- 제네릭 파라미터 이름은 의미 있게 (`T` 대신 `TData`)

## 예시

\`\`\`typescript
// 좋은 예
function fetchData<TData>(url: string): Promise<TData> {
  return fetch(url).then(res => res.json());
}

// 나쁜 예
function fetchData(url: string): Promise<any> {
  return fetch(url).then(res => res.json());
}
\`\`\`

.ts.tsx를 Claude가 읽을 때만 이 규칙이 활성화된다. README, 마크다운 문서, 설정 JSON 작업에는 들어가지 않는다.

@ 멘션으로 외부 문서 import

CLAUDE.md와 rules 파일은 @path/to/file 문법으로 다른 파일을 import할 수 있다. import된 파일은 launch 시점에 펼쳐져서 컨텍스트에 같이 로드된다.

# CLAUDE.md

프로젝트 개요는 @README.md를 참조하고,
사용 가능한 npm 명령은 @package.json을 보라.

## 추가 지침
- git 워크플로 @docs/git-instructions.md
- 아키텍처 @docs/architecture.md

상대 경로(파일 기준)와 절대 경로 모두 허용된다. 상대 경로는 working directory 기준이 아니라 import한 파일 기준이라는 점에 주의한다.

재귀 import

import된 파일이 또 import할 수 있다. 최대 5단계까지 재귀가 허용된다.

CLAUDE.md
  → @docs/architecture.md
      → @docs/database-schema.md
          → @docs/migrations.md
              → @docs/migration-conventions.md
                  → @docs/legacy-notes.md  ← 여기까지 (5 hops)

첫 외부 import 시 승인 다이얼로그

처음 외부 파일을 import할 때 Claude Code는 승인 다이얼로그를 띄운다. 어떤 파일들이 로드되는지 보여준다. 거부하면 import는 비활성화되고 다이얼로그도 다시 안 나온다. 나중에 마음을 바꾸려면 별도로 처리해야 한다.

worktree 간 개인 설정 공유

Git worktree를 여러 개 쓰면 CLAUDE.local.md는 worktree마다 따로 존재한다(gitignore되어 있어서). 모든 worktree에서 같은 개인 설정을 쓰고 싶으면 홈 디렉토리에서 import하면 된다.

# 개인 선호
- @~/.claude/my-project-instructions.md

@~/.claude/...는 home-relative 절대 경로다. 어느 worktree에 있든 같은 파일이 펼쳐진다.

import vs path-scoped: 헷갈리지 말 것

@importlaunch 시점에 무조건 펼쳐진다. 컨텍스트에 항상 들어간다.

paths: rules는 매칭 파일을 읽을 때만 들어간다. 컨텍스트를 아낄 수 있다.

긴 파일을 import로 합치면 단순히 한 파일로 합친 것과 같다. 컨텍스트는 줄지 않는다. 컨텍스트를 줄이고 싶으면 path-scoped rules를 쓰는 게 맞다.

AGENTS.md 호환

다른 AI 코딩 에이전트(예: Codex, Cursor)는 AGENTS.md를 읽는다. Claude Code는 AGENTS.md를 직접 읽지 않는다. 한 저장소가 여러 도구를 같이 쓰고 있다면 둘 다 만족시키는 패턴이 있다.

<!-- CLAUDE.md -->
@AGENTS.md

## Claude Code 전용

`src/billing/` 아래 변경은 plan mode를 써라.

AGENTS.md를 import해서 공통 지침은 한 곳에 두고, Claude 전용 지침은 import 아래에 덧붙인다. 양쪽 도구가 같은 베이스를 보면서 도구별 추가 지침만 따로 두는 구조다.

사용자 전역 rules: ~/.claude/rules/

머신 전체에 적용되는 개인 rules는 ~/.claude/rules/에 둔다. 프로젝트와 무관한 본인 선호 — 코딩 스타일, 자주 쓰는 워크플로 — 같은 것들이다.

~/.claude/rules/
├── preferences.md    # 개인 코딩 선호
└── workflows.md      # 자주 쓰는 워크플로

여기서 우선순위 규칙을 알아두자. 공식 문서는 다음과 같이 명시한다.

User-level rules are loaded before project rules, giving project rules higher priority.

User rules가 먼저 로드되고 project rules가 나중에 로드된다. 충돌하는 지시가 있을 때 Claude는 나중에 본 것을 더 가까운 컨텍스트로 인식하기 쉽기 때문에, project rules가 사실상 더 높은 우선순위를 가진다. 팀 표준이 개인 선호를 덮어쓴다고 보면 된다.

같은 토픽에서 두 rules가 정반대 지시를 담고 있으면 Claude가 임의로 하나를 고를 수 있다. 충돌은 정기적으로 정리한다.

팀과 규칙 공유하기

.claude/ 디렉토리는 Git에 커밋해도 안전하다. CLAUDE.md, .claude/CLAUDE.md, .claude/rules/까지 묶어서 커밋하면 팀원이 클론한 순간 같은 규칙이 자동 적용된다.

git add .claude/
git commit -m "docs: 팀 코딩 규칙 추가"
git push

팀원이 한 일은 git pull이 전부다.

git pull
claude
# .claude/rules/ 자동 로드

다만 두 가지를 분리해서 생각한다.

.gitignoreCLAUDE.local.md.claude/settings.local.json을 미리 넣어둔다. /init로 CLAUDE.md를 생성할 때 이 작업을 자동으로 해준다.

심볼릭 링크로 여러 프로젝트에 규칙 공유

같은 회사의 여러 저장소에 동일한 보안 규칙, 회사 표준을 적용하고 싶을 때 매번 복사하는 건 유지보수가 힘들다. .claude/rules/는 심볼릭 링크를 지원한다.

# 회사 표준 디렉토리를 통째로 심볼릭 링크
ln -s ~/shared-claude-rules .claude/rules/shared

# 개별 파일만 링크
ln -s ~/company-standards/security.md .claude/rules/security.md

심볼릭 링크는 정상적으로 풀어서 로드된다. 순환 심볼릭 링크는 감지해서 처리한다. 한 곳에서 표준을 업데이트하면 모든 프로젝트가 자동으로 따라간다.

심볼릭 링크된 디렉토리/파일은 git에 커밋되면 링크 자체가 커밋된다. 팀원이 같은 경로(~/shared-claude-rules)를 가지고 있어야 동작한다. 팀이 이걸 자동화하고 싶으면 setup 스크립트를 PR에 포함하는 패턴이 흔하다.

추가 디렉토리에서 rules 로드하기

--add-dir 플래그로 working directory 외부 폴더를 같이 보여줄 수 있다(파일 접근 권한). 그런데 기본적으로는 추가 디렉토리의 CLAUDE.md와 rules는 로드되지 않는다. 별도 환경 변수로 켠다.

CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config

이렇게 하면 추가 디렉토리의 CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md, CLAUDE.local.md가 로드된다(--setting-sources에서 local을 빼면 CLAUDE.local.md는 제외).

여러 저장소가 공통 설정을 공유하는 모노레포-옆-공통-디렉토리 구조에서 유용하다.

모노레포에서 다른 팀 CLAUDE.md 제외하기

모노레포에서 여러 팀이 각자 CLAUDE.md를 두고 있을 때 — Claude Code가 디렉토리 트리를 위로 거슬러 올라가면서 발견하는 모든 CLAUDE.md를 합쳐 로드한다. 다른 팀의 지시가 내 작업에 노이즈로 들어온다.

이럴 땐 claudeMdExcludes 설정으로 특정 경로를 건너뛴다.

{
  "claudeMdExcludes": [
    "**/monorepo/CLAUDE.md",
    "/home/user/monorepo/other-team/.claude/rules/**"
  ]
}

패턴은 절대 경로에 글롭으로 매칭된다. user, project, local, managed policy 어느 레이어에서든 설정할 수 있고 여러 레이어의 배열은 합쳐진다. 이 설정은 머신-로컬에 두는 게 자연스러우니 보통 .claude/settings.local.json에 넣는다.

Managed policy CLAUDE.md(조직이 IT/DevOps로 배포하는)는 claudeMdExcludes로도 제외할 수 없다. 조직 단위 표준은 무조건 적용되도록 설계됐다.

/memory로 어떤 규칙이 로드됐는지 확인

22차시에서 /memory를 다뤘다. 다시 떠올려보면 /memory는 다음을 보여준다.

  1. 현재 세션에 로드된 모든 CLAUDE.md, CLAUDE.local.md, rules 파일 목록
  2. Auto memory 토글
  3. Auto memory 폴더 열기 링크
  4. 파일 선택 시 에디터로 열기

.claude/rules/를 도입한 직후에는 /memory로 의도한 파일이 실제로 로드되는지 확인한다. 보이지 않는 파일이 있다면 Claude가 못 보는 거다.

InstructionsLoaded 훅으로 디버깅

path-scoped rules는 매칭 파일을 읽는 시점에 동적으로 로드되기 때문에, “왜 이 규칙이 안 먹지?” 같은 의문이 생기기 쉽다. InstructionsLoaded이 이런 디버깅에 쓰는 도구다.

이 훅은 CLAUDE.md나 .claude/rules/*.md가 컨텍스트에 로드될 때마다 발화한다. 차단하거나 결정에 개입하지는 못하고 — 관찰 전용이다.

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "matcher": "session_start|path_glob_match",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Loaded: ${file_path}' >> ~/instruction-audit.log"
          }
        ]
      }
    ]
  }
}

매처 값은 다음과 같다.

매처의미
session_start세션 시작 시 로드된 파일
nested_traversal서브디렉토리 진입으로 lazy-load된 nested CLAUDE.md
path_glob_matchpaths: 패턴 매치로 lazy-load된 path-scoped rule
include@import로 끌려온 파일
compact/compact 후 재로드

훅에 전달되는 입력 필드에는 file_path, memory_type(User/Project/Local/Managed), load_reason, globs(path_glob_match일 때 패턴), trigger_file_path(어떤 파일을 읽다가 트리거됐는지)가 있다.

규칙이 안 먹는 것 같으면 이 훅으로 로그를 남기고, 어떤 파일을 어떤 이유로 어느 시점에 로드했는지 추적한다. 28~31차시에서 hooks를 다룰 때 이 패턴을 다시 본다.

트러블슈팅

규칙이 적용되지 않는 것 같다

순서대로 점검한다.

  1. /memory로 로드 여부 확인 — 목록에 파일이 보이는가
  2. paths: 패턴 확인 — 만지는 파일이 패턴에 정말 매치되는가. 패턴은 절대 경로가 아니라 working directory 기준 상대 경로로 매치된다
  3. paths: 매치 트리거 확인 — Claude가 매칭 파일을 한 번이라도 읽었는가. 패턴이 매치만 된다고 로드되지 않고, 실제 Read가 일어나야 활성화된다
  4. InstructionsLoaded 훅으로 audit log 남기기 — 위 단계로 안 풀리면 훅으로 정확히 어떤 파일이 언제 로드됐는지 본다
  5. 충돌 규칙 점검 — 다른 rules나 CLAUDE.md에서 정반대 지시를 하고 있지 않은지

무엇이 로드됐는지 모르겠다

/memory가 1차 도구다. 더 정밀하게 보고 싶으면 InstructionsLoaded 훅을 audit log로 쓴다.

CLAUDE.md가 너무 커졌다

200줄 넘기면 — 두 가지 처치다.

  1. path-scoped rules로 옮긴다 — 특정 영역에만 필요한 지시는 .claude/rules/로 빼고 paths:를 단다. 컨텍스트에서 영구적으로 빠진다
  2. @import로 분리한다 — 단순히 가독성 목적이면 import. 다만 import된 파일은 launch 시점에 펼쳐지므로 컨텍스트는 줄지 않는다. 토큰을 줄이려면 1번을 쓴다

모노레포에서 다른 팀의 CLAUDE.md가 들어온다

claudeMdExcludes로 경로를 제외한다. 머신-로컬이라 .claude/settings.local.json에 두는 게 자연스럽다.

path-scoped rule이 자꾸 활성화 안 된다

path-scoped rule의 트리거는 Claude가 매칭 파일을 Read하는 순간이다. Bash로 ls만 해서는 활성화 안 된다. 한 번 매치되면 세션 동안 유지된다. InstructionsLoaded 훅으로 path_glob_match 매처를 걸어두면 정확한 발화 시점을 본다.

정리

핵심 요점

  1. CLAUDE.md 200줄 한도: 길어지면 준수율 하락. 토픽별로 쪼개거나 path-scoped로 옮긴다

  2. .claude/rules/ 디렉토리: 토픽별 마크다운, 재귀 발견. 서브디렉토리(frontend/, backend/)도 가능

  3. 무조건 로드 vs path-scoped: paths: 없으면 매 세션 시작 시 무조건 로드(CLAUDE.md와 동등). 있으면 매칭 파일을 Read할 때 lazy-load

  4. 글롭 패턴: **/*.ts, src/**/*, 브레이스 확장(*.{ts,tsx}) 지원

  5. @import 문법: 상대(파일 기준) 또는 절대 경로. 최대 5단계 재귀. 첫 외부 import 시 승인 다이얼로그. import는 컨텍스트를 줄이지 않는다(launch 시점에 펼쳐짐)

  6. AGENTS.md 호환: CLAUDE.md에서 @AGENTS.md로 import 후 Claude 전용 지침 추가

  7. User vs Project rules: User rules(~/.claude/rules/)가 먼저, project rules(.claude/rules/)가 나중. 사실상 project가 우선

  8. 팀 공유: .claude/를 git에 커밋. CLAUDE.local.mdsettings.local.json은 .gitignore. 심볼릭 링크로 여러 프로젝트에 공통 규칙 적용

  9. 모노레포 제외: claudeMdExcludes로 다른 팀의 CLAUDE.md/rules 경로를 글롭으로 제외 (managed policy는 제외 불가)

  10. 추가 디렉토리에서 로드: CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ...

  11. 디버깅: /memory로 로드된 파일 목록 확인. InstructionsLoaded 훅으로 정확한 로드 시점/이유 audit log

확인해볼 링크

다음 단계

24차시부터는 섹션 5 — Custom Skills로 들어간다. 24차시에서는 Skills의 개념을 다룬다. CLAUDE.md와 rules가 “매 세션에 로드되는 컨텍스트”라면, Skills는 on-demand로 로드되는 워크플로/지식이다. /<name> 슬래시 명령으로 직접 호출하거나 Claude가 작업과 관련 있다고 판단했을 때만 본문이 들어온다. 매 세션 컨텍스트를 늘리지 않으면서 재사용 가능한 작업을 패키징하는 방법을 살펴본다.

참고 자료


Next Post
Claude Code 메모리 시스템 활용