실제로 중요한 CLAUDE.md 섹션과 컨텍스트를 낭비하는 섹션
요약
CLAUDE.md 파일의 효율적인 작성을 위한 가이드로, 불필요한 컨텍스트 낭비를 줄이고 핵심적인 정보만 남기는 방법을 제안합니다. 유능한 신입 사원에게 필요한 정보인지, 코드에서 추론 가능한지를 기준으로 섹션을 분류합니다.
핵심 포인트
- CLAUDE.md는 200줄 미만, 권장 60줄 미만으로 간결하게 유지해야 함
- 명확하지 않은 명령(Commands) 정보를 포함하여 오류 방지
- 디렉토리의 의도를 담은 아키텍처 지도(Layout) 작성
- 린터가 강제하지 않는 프로젝트만의 컨벤션 명시
저는 CLAUDE.md 파일 내의 지침(instructions) 개수를 세는 린터(linter)를 작성했습니다. 그리고 제 프로젝트들에 이를 실행해 보면서 불편한 사실 하나를 깨달았습니다. 문제는 제 파일들이 너무 짧다는 것이 아니었습니다. 모든 파일에는 충분한 내용이 담겨 있었습니다. 문제는 그 내용의 대부분이 아무런 역할도 하지 못하고 있었거나, 더 심하게는 중요한 10줄의 내용을 적극적으로 밀어내고 있었다는 점이었습니다.
"짧게 유지하라"는 것은 이제 누구나 반복하는 조언이며, 이는 옳습니다. Anthropic의 자체 best-practices doc에서도 간결하고 사람이 읽기 쉽게 유지할 것, 200줄 미만을 목표로 할 것을 권장하며, 파일이 길어지면 더 많은 컨텍스트(context)를 소비하고 준수율(adherence)을 떨어뜨린다고 경고합니다. 이 주제에 대해 훌륭한 글을 작성한 엔지니어링 블로그를 보유한 HumanLayer는 루트 CLAUDE.md를 60줄 미만으로 유지합니다.
하지만 "짧게"라는 것은 제약 조건일 뿐, 계획은 아닙니다. 진짜 질문은 이것입니다: 어떤 줄이 파일 내에 자리를 잡을 가치가 있으며, 어떤 줄이 감당할 수 없는 임대료를 내고 있는가?
이제 제가 모든 줄에 적용하는 테스트는 다음과 같습니다: 유능한 신입 사원이 첫날에 이 정보가 필요할 것인가? 그리고 그들이 코드로부터 이를 추론할 수 없는가? 만약 두 질문 중 어느 하나라도 '아니오'라면, 그 줄은 삭제됩니다.
이 테스트는 CLAUDE.md의 모든 것을 두 더미로 분류합니다.
자리를 차지할 가치가 있는 6가지 섹션
1. Commands — 정확하고, 복사해서 붙여넣을 수 있는 것
어떤 CLAUDE.md에서도 단일 항목 중 가장 가치가 높은 콘텐츠입니다. Claude는 당신의 테스트 러너(test runner)에 특정 플래그가 필요하다거나, npm test가 고장 나서 실제로 모두가 npm run test:fast를 실행한다는 사실을 추론할 수 없습니다.
## Commands
- Build: `pnpm build` (NOT npm — lockfile is pnpm)
- Test single file: `pnpm vitest run path/to/file.test.ts`
...
네 줄입니다. 각 줄이 명확하지 않은(non-obvious) 세부 사항을 담고 있다는 점에 주목하세요. pnpm build 자체는 락파일(lockfile)로부터 추론할 수 있지만, "NOT npm"은 실제 발생할 수 있는 오류 모드(failure mode)를 방지합니다.
2. 아키텍처 지도(Architecture map) — 요소들이 위치한 곳
"어디를 봐야 하는가?"에 답하는 3~6줄입니다. 디렉토리 목록(Claude는 ls를 실행할 수 있습니다)이 아니라, 의도(intent)를 담고 있는 부분들입니다:
레이아웃 (Layout)
src/core/— 순수 비즈니스 로직 (pure business logic), I/O 없음, 프레임워크 임포트 (framework imports) 없음src/adapters/— 모든 외부 호출 (DB, API)은 오직 여기에만 존재함
...
legacy/ 및 src/gen/ 라인은 경계 마커 (boundary markers)입니다. 제 경험상, 이 라인들은 파일 내의 그 어떤 스타일 규칙보다 더 많은 피해를 방지해 줍니다. 생성된 파일을 편집하는 에이전트(agent)는 다음 코드 생성 (codegen) 실행 시 조용히 되돌아가는 변경 사항을 만들어내는데, 이는 추적하기 정말 괴로운 버그입니다.
3. 린터 (linter)가 강제하지 않는 컨벤션 (Conventions)
이 부분이 대부분의 파일이 양방향으로 잘못되는 지점입니다. 공식 가이드의 경험칙은 옳습니다: 린터가 이미 강제하는 내용을 절대 중복해서 작성하지 마세요. ESLint나 Prettier가 잡아낼 수 있는 내용이라면, 그 라인은 순전한 낭비입니다. Claude Code는 린트 오류 (lint failure)를 확인하고 어차피 수정할 것이기 때문입니다.
여기에 포함되어야 할 내용은 자동화된 강제성이 없는 것들입니다:
## 컨벤션 (Conventions)
- 에러 (Errors): 코어 함수에서는 `Result<T, E>`를 반환할 것; `throw`는 어댑터 (adapter) 경계에서만 수행할 것
- 새로운 엔드포인트 (endpoints)는 `src/api/users.ts`의 패턴을 따를 것 — 이를 복사할 것
...
두 번째 라인에 주목하세요: 예시 파일 (exemplar file)을 지칭하는 것이 산문 (prose)으로 패턴을 설명하는 것보다 훨씬 저렴합니다. 한 줄의 포인터가 30줄의 설명을 대체하며, 예시 파일은 산문처럼 시간이 지나면서 내용이 어긋날(drift) 염려가 없습니다.
4. 검증 (Verification) — Claude가 자신의 작업을 증명하는 방법
Claude Code는 자신의 출력을 스스로 확인할 수 있을 때 훨씬 더 신뢰할 수 있습니다. 어떻게 해야 하는지 알려주세요:
## 변경 사항 검증 (Verifying changes)
- 작업을 마치기 전에 `pnpm tsc --noEmit && pnpm vitest run`이 반드시 통과해야 함
- UI 변경 사항: `pnpm dev`가 :3000에서 실행됨; 완료를 주장하기 전에 스크린샷을 찍을 것
이 섹션이 없으면, 에이전트는 무엇이 "완료 (done)"인지 스스로 결정합니다. 이 섹션이 있으면, 당신이 완료를 정의하게 됩니다.
5. 짧은 "절대 안 됨 (never)" 목록 — 이유와 함께
매우 짧게 유지되는 엄격한 경계들입니다. 그리고 제가 지침 예산 (instruction-budget) 포스트에서 설명한 일반화(generalization) 이유를 위해, 모든 규칙에는 "이유 (why)\
절대 금지 사항 (Never)
main브랜치에 직접 커밋하지 마세요 (어차피 브랜치 보호 설정으로 인해 푸시가 거부됩니다)*.generated.ts파일을 수정하지 마세요 (빌드 시 재생성되므로, 수정 사항이 조용히 사라집니다)
...
마지막 줄이 바로 복사해야 할 패턴입니다. 이유("현재 238개입니다")를 명시하면, 당신이 규칙을 작성하지 않은 사례에 대해서도 모델이 올바른 판단(judgment call)을 내릴 수 있게 합니다.
6. 더 깊은 문서로의 연결 — 점진적 공개 (progressive disclosure)
Anthropic과 HumanLayer 모두, 분류하기 어려운 모든 항목에 대해 동일한 메커니즘을 사용합니다. 세부 사항을 붙여넣지 말고, 해당 위치를 가리키기만 하세요. 그러면 Claude는 작업이 필요할 때만 해당 파일을 가져옵니다. 이 메커니즘은 instruction-budget 포스트에서 다루었으므로, 여기서는 그 형태만 보여드리겠습니다:
## 상세 정보 (관련이 있을 때만 읽으세요)
- 테스트 철학 및 피스처 (fixtures): `docs/testing.md`
- 릴리스 프로세스 (release process): `docs/release.md`
...
조용히 컨텍스트를 낭비하는 섹션들
아래의 모든 항목은 '첫날 채용 테스트 (day-one-hire test)'를 통과하지 못합니다. 저는 실제 환경에서 이 모든 사례를 보았으며, 제 파일들에서도 여러 개를 발견했습니다:
- 프로젝트 미션 선언문 (mission statement). 앱이 무엇을 하는지, 누구를 위한 것인지에 대한 세 문단 분량의 설명. Claude에게는 한 문장이면 충분하며, 대부분의 경우 아예 필요하지도 않습니다.
- 붙여넣은 API 문서. 사용 중인 프레임워크의 문서는 모델의 학습 데이터에 포함되어 있거나
WebFetch한 번으로 가져올 수 있습니다. Drizzle 문서 50줄을 붙여넣는 것은 순전한 세금(tax) 50줄을 내는 것과 같습니다. - 도구가 강제하는 스타일 규칙. "2칸 들여쓰기를 사용하세요." Prettier가 이미 수행하고 있습니다. 삭제하세요.
- 튜토리얼. 예시 파일(exemplar file)이 무료로 보여주고 있는 내용을 중복해서 설명하는 단계별 "기능 추가 방법" 가이드.
- 변경 이력 (changelog). "2025-11: App Router로 마이그레이션함." 이력은 git에 있어야 합니다.
- 일반적인 엔지니어링 지혜. "좋은 이름을 사용하여 깨끗하고 유지보수 가능한 코드를 작성하세요." 이는 아무런 지침도 주지 않습니다. 모든 모델은 이미 이를 시도하고 있으며, 이 문장은 정보량이 전혀 없는 상태로 예산(budget)만 소모합니다.
교묘한 점은 이 문장들 중 어느 것도 개별적으로는 해로워 보이지 않는다는 것입니다. 하지만 이 파일은 모든 세션에 로드되며, 저는 위에서 링크한 지침 예산(instruction-budget) 포스트에서 지침 수가 증가할수록 준수율이 저하된다는 점을 논증한 바 있습니다. 모델은 212번 규칙에서 오류를 내는 것이 아니라, 그저 조용히 일부 규칙을 따르지 않게 됩니다. 이러한 채우기용 문구(filler)는 단순히 토큰을 소모하는 데 그치지 않고, 모델의 주의력(attention)을 두고 실제 규칙들과 경쟁합니다.
실제 파일에서의 모습
오늘 제 프로젝트 파일 중 하나에 claude-md-lint를 실행하여 얻은 실제 결과물입니다 (진단 부분):
claude-md-lint CLAUDE.md
────────────────────────────────────────────────
Instruction budget score: 🟢 84/100
...
가운데 진단 결과를 보십시오. 파일이 예산(budget) 범위 내에 안정적으로 들어와 있음에도 불구하고, 56개의 규칙 중 46개가 이유가 첨부되지 않은 단순 명령문입니다. 이 파일의 문제는 길이가 아니라 정보 밀도(information density)였습니다. 이것이 바로 앞서 언급한 6가지 섹션이 방지하고자 하는 실패 모드(failure mode)입니다.
전/후 비교 (실제 파일들을 바탕으로 구성됨)
이전 — 이 파일들을 린트(lint)할 때 계속 발견되는 문장들로 구성된 "관례(conventions)" 섹션입니다. 제가 린트한 파일 중 이 정도로 심각한 파일은 없었지만, 아래의 모든 문장은 실제 파일(제 파일 중 일부 포함)에서 본 것들입니다:
## Code Style
우리는 코드 품질을 매우 중요하게 생각합니다. 항상 깨끗하고 읽기 쉬운 코드를 작성하세요.
모든 새 파일에는 TypeScript를 사용하세요. 의미 있는 변수 이름을 사용하세요.
...
이는 8개의 줄이 16개의 규칙을 담고 있는 형태입니다. '첫 출근 직원 테스트(day-one-hire test)'를 해보십시오. TypeScript는 추론 가능하며(모든 파일이 .ts임), 들여쓰기와 임포트 정렬(import sorting)은 Prettier/ESLint의 역할이며, 남은 것의 절반 이상은 일반적인 격언입니다. 살아남은 것은 다음과 같습니다:
## Conventions
- `noUncheckedIndexedAccess`가 켜져 있음 — 인덱스 접근 시 `T | undefined`를 반환하므로 이를 처리할 것
- `src/core/` 내의 내보내진(exported) 함수에는 JSDoc을 작성할 것 (문서 사이트가 이를 통해 생성함)
16개의 규칙이 2개로 줄어들었습니다. 그리고 살아남은 2개는 모델에게 말해주지 않으면 실제로 틀릴 법한 것들입니다. 이것이 매번 발생하는 트레이드오프(trade-off)입니다. 짧은 버전은 긴 버전의 요약이 아니라, 모델이 이미 알고 있거나 도구가 이미 강제하고 있는 모든 것을 제거하고 남은 잔여물입니다.
60초 감사 (60-second audit)
CLAUDE.md를 열고 각 라인에 점수를 매기세요:
- Claude가 코드나 락파일(lockfiles)로부터 이를 추론할 수 있는가? → 삭제
- 린터(linter)나 포매터(formatter)가 이미 이를 강제하고 있는가? → 삭제
- 프로젝트 특화된 내용이 없는 일반적인 조언인가? → 삭제
- 전체 작업의 20% 미만에서만 필요한 세부 사항인가? →
docs/파일로 이동하고, 참조(pointer)만 남길 것 - "반드시 일어나야 하는" 규칙인가? → 유지하되, 괄호 안에 이유를 추가할 것
- 명령(command), 경계(boundary), 또는 예시(exemplar)에 대한 지침인가? → 유지, 이것들이 바로 파일의 핵심입니다.
제가 이 작업을 수행한 대부분의 파일은 길이는 절반으로 줄어들었지만, 기능은 전혀 손실되지 않았습니다.
저는 전체 체크리스트와 더불어, 어떤 에이전트(agent)를 배포하기 전에 적용하는 신뢰성 규칙들을 무료 Claude Code Field Guide에 담아두었습니다: penloomstudio.com/field-guide.html
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기