Claude Code를 쓰면서 "왜 맨날 같은 얘기를 반복하지?"라고 느낀 적 있다면, CLAUDE.md를 안 쓰고 있거나 잘못 쓰고 있는 거다.
이 파일 하나가 Claude Code의 행동 품질을 결정한다. 잘 쓰면 프로젝트 컨벤션을 첫 메시지부터 따르는 팀원이 되고, 못 쓰면 매번 "아니 그거 말고..."를 반복하게 된다.
이 글은 CLAUDE.md를 제대로 작성하는 실전 가이드다. 어디에 두는지, 뭘 써야 하는지, 흔한 실수는 뭔지 전부 다룬다.
목차
- CLAUDE.md가 뭔가
- 왜 중요한가
- 필수 섹션 5가지
-
- 프로젝트 개요 (2-3줄)
-
- 코드 컨벤션
-
- Conventions
-
- 빌드/실행 명령어
-
- Commands
-
- 아키텍처 핵심 규칙
-
- Architecture
-
- 하지 말 것 (금지 목록)
-
- Do NOT
- 좋은 CLAUDE.md vs 나쁜 CLAUDE.md
- 고급 기법
- 계층 구조 활용
- Skills로 분리
- Workflows
- 동적 컨텍스트
- References
- 실전 템플릿
- Tech Stack
- Commands
- Architecture
- Conventions
- Do NOT
- References
- Workflows
- 흔한 실수 5가지
-
- 너무 길게 쓴다
-
- 너무 추상적으로 쓴다
-
- 코드에서 이미 알 수 있는 걸 반복한다
-
- 업데이트를 안 한다
-
- Skills를 안 쓴다
-
- 요약
CLAUDE.md가 뭔가
CLAUDE.md는 프로젝트 루트에 두는 마크다운 파일이다. Claude Code가 세션을 시작할 때 자동으로 읽어서 컨텍스트에 넣는다. 모든 대화에 항상 포함되는 "내가 제어하는 시스템 프롬프트"라고 생각하면 된다.
세 가지 레벨이 있다:
| 레벨 | 경로 | 용도 |
|---|---|---|
| 글로벌 | ~/.claude/CLAUDE.md |
모든 프로젝트 공통 설정 (개인 취향) |
| 프로젝트 루트 | ./CLAUDE.md |
프로젝트 전체 규칙 |
| 서브디렉토리 | ./frontend/.claude/CLAUDE.md |
모듈별 규칙 |
세 파일이 동시에 존재하면 전부 로드된다. 글로벌 → 프로젝트 → 서브디렉토리 순으로 합쳐진다.
중요한 점: CLAUDE.md는 매 메시지마다 컨텍스트에 포함된다. 길게 쓸수록 매번 토큰을 더 소비한다. 이건 뒤에서 자세히 다룬다.
왜 중요한가
CLAUDE.md 없이 Claude Code를 쓰면 이런 일이 벌어진다:
- "JPA 쓰지 말라고 했잖아" — 매번 말해줘야 한다
- "테스트 파일명은 Spec으로 끝나야 해" — 또 말해줘야 한다
- "API 응답은 항상 ApiResponse로 감싸" — 또또 말해줘야 한다
- "빌드 명령어가 그게 아니라..." — 또또또
CLAUDE.md가 없으면 Claude는 일반적인 관행(generic best practices)으로 코드를 짠다. 너의 프로젝트만의 컨벤션, 아키텍처 규칙, 금지 사항을 알 방법이 없다.
반대로 좋은 CLAUDE.md가 있으면:
- 첫 메시지부터 프로젝트 컨벤션을 따른다
- 빌드/테스트 명령어를 알고 있어서 스스로 검증한다
- 금지된 패턴을 피한다
- 온보딩 문서를 다 읽은 신규 팀원처럼 행동한다
요약하면 이거다: CLAUDE.md는 Claude Code에게 주는 온보딩 문서다. 신입한테 온보딩 안 시키고 "알아서 해"라고 하면 어떻게 되는지 다들 알지 않나.
필수 섹션 5가지
1. 프로젝트 개요 (2-3줄)
프로젝트가 뭔지, 무슨 스택인지. 딱 2-3줄이면 된다. 장문의 비전 선언문이 아니다.
# Project
E-commerce API built with Kotlin + Spring Boot 3 + Exposed ORM.
Multi-tenant SaaS with schema-per-tenant architecture.
PostgreSQL 16, Redis for caching.
이것만으로 Claude는 "아 Kotlin + Spring Boot + Exposed 조합이구나, JPA가 아니라 Exposed를 쓰는구나"를 파악한다. 이 3줄이 없으면 Claude는 높은 확률로 JPA를 제안한다. Spring Boot 프로젝트니까.
2. 코드 컨벤션
네이밍, 포맷팅, import 순서 등. 핵심은 "Claude가 혼자서는 추측할 수 없는 것"만 쓰는 거다. "변수명은 camelCase로" 같은 건 안 써도 된다. Kotlin이면 당연히 camelCase니까.
## Conventions
- Use `Exposed` DSL, not JPA annotations
- All API responses wrap in `ApiResponse<T>`
- Use `kotlinx.datetime`, not java.time
- Test files: `*Spec.kt` (Kotest), not `*Test.kt`
- DTO class names end with `Request`/`Response` (e.g., `CreateOrderRequest`)
- No wildcard imports
- Coroutine scope: always use `supervisorScope` for parallel calls
"Exposed DSL을 쓴다"는 한 줄이 없으면 Claude는 십중팔구 @Entity, @Table 같은 JPA 어노테이션을 붙인다. 이 한 줄이 수십 번의 수정을 방지한다.
3. 빌드/실행 명령어
Claude Code는 코드만 짜는 게 아니라 직접 실행해서 검증할 수 있다. 근데 빌드 명령어를 모르면 검증을 못 한다.
## Commands
- Build: `./gradlew build`
- Test all: `./gradlew test`
- Test single: `./gradlew test --tests "com.example.OrderServiceSpec"`
- Run: `./gradlew bootRun --args='--spring.profiles.active=local'`
- Lint: `./gradlew ktlintCheck`
- Lint fix: `./gradlew ktlintFormat`
- DB migration: `./gradlew flywayMigrate -Dflyway.env=local`
이 섹션이 있으면 Claude가 코드를 수정한 후 ./gradlew test를 돌려서 테스트 통과 여부를 스스로 확인한다. 없으면 "코드 수정했습니다"로 끝나고, 빌드가 깨진 걸 네가 직접 발견해야 한다.
4. 아키텍처 핵심 규칙
어떤 패턴을 따르는지, 레이어 구조는 뭔지. 핵심만 3-5줄.
## Architecture
- Controller → Service → Repository 3-layer only
- No business logic in controllers
- All DB access through Repository layer
- Use coroutines for external API calls, not WebClient.block()
- Events: publish via ApplicationEventPublisher, handle in @Async listener
이게 없으면 Claude가 Controller에 비즈니스 로직을 넣거나, Service에서 직접 DB 쿼리를 날리는 코드를 짤 수 있다. "우리 프로젝트에선 안 그래"를 매번 말하는 대신, 여기에 한 번 적어두면 된다.
5. 하지 말 것 (금지 목록)
솔직히 이 섹션이 제일 효과가 크다. "해라"보다 "하지 마라"가 더 강력하다. Claude가 기본 성향상 하려고 하는 것 중에서 너의 프로젝트에서는 안 되는 것을 명시한다.
## Do NOT
- Do not use JPA or Hibernate — we use Exposed exclusively
- Do not add comments unless logic is non-obvious
- Do not create utility classes for one-time operations
- Do not modify files in /generated/ directory
- Do not use @Autowired — use constructor injection only
- Do not add new dependencies without explicit approval
- Do not use var — prefer val always
왜 이게 제일 효과가 큰지 설명하면: Claude는 "가장 일반적인 패턴"을 기본으로 택한다. Spring Boot면 JPA, 의존성 주입이면 @Autowired, 변수면 var. 이런 기본 성향을 꺾으려면 명시적으로 "하지 마"라고 써야 한다.
좋은 CLAUDE.md vs 나쁜 CLAUDE.md
| 나쁜 예 | 좋은 예 | 이유 |
|---|---|---|
| "Use good coding practices" | "All functions must have explicit return types" | 구체적이어야 한다. 모호하면 Claude가 제멋대로 해석한다 |
| 500줄짜리 장문 | 150줄 이하 | 매 메시지마다 토큰을 먹는다. 길수록 비용 증가 |
| "We use React" | "React 18 + TypeScript 5.3 + Zustand for state" | 스택과 버전을 정확히 명시해야 엉뚱한 라이브러리를 안 쓴다 |
| ASCII 아키텍처 다이어그램 30줄 | "Controller → Service → Repository 3-layer" 한 줄 | Claude는 ASCII 그림에서 정보를 잘 추출 못 한다 |
| "Follow our coding standards" | "See conventions in docs/CONVENTIONS.md" | Claude가 필요할 때 직접 읽게 참조만 걸어둔다 |
| 프로젝트 히스토리 장황하게 | 현재 상태만 간결하게 | Claude한테 "왜 이 구조가 됐는지"는 필요 없다 |
핵심 원칙: 짧고, 구체적이고, 실행 가능해야 한다.
"Clean code를 작성해라"는 의미가 없다. Claude도 사람처럼 "Clean code"의 정의를 제각각 해석한다. "함수는 30줄 이하, 파라미터는 3개 이하, 중첩 depth는 2 이하"가 실행 가능한 지시다.
고급 기법
계층 구조 활용
세 레벨의 CLAUDE.md를 전략적으로 나누면 효과적이다.
글로벌 (~/.claude/CLAUDE.md): 개인 취향. 어떤 프로젝트든 적용.
- Respond in Korean for explanations, English for code
- Prefer functional style over imperative
- Always run tests after code changes
프로젝트 루트 (./CLAUDE.md): 프로젝트 전체 규칙. 팀 전원이 공유.
- Kotlin + Spring Boot 3 + Exposed
- 3-layer architecture
- Test with Kotest
서브디렉토리 (./frontend/.claude/CLAUDE.md): 모듈별 규칙. 프론트엔드와 백엔드가 다른 규칙을 쓸 때.
- React 18 + TypeScript + Zustand
- CSS Modules, not styled-components
- All components must have Storybook stories
이렇게 하면 백엔드 디렉토리에서 작업할 때는 백엔드 규칙만, 프론트엔드 디렉토리에서 작업할 때는 프론트엔드 규칙이 추가로 로드된다.
Skills로 분리
CLAUDE.md의 가장 큰 함정은 매 메시지마다 전부 로드된다는 거다. 200줄이면 매번 200줄 분량의 토큰을 소비한다.
해결책: 워크플로우별 지침은 Skills로 분리한다.
.claude/skills/
├── pr-review/SKILL.md # PR 리뷰할 때만 로드
├── db-migration/SKILL.md # DB 마이그레이션 시에만 로드
├── deploy/SKILL.md # 배포 시에만 로드
└── api-design/SKILL.md # API 설계 시에만 로드
Skills는 해당 스킬이 호출될 때만 컨텍스트에 들어간다. PR 리뷰 규칙이 50줄이라면, PR 리뷰할 때만 50줄이 추가되고 평소에는 0이다.
CLAUDE.md에는 항상 필요한 핵심 규칙만 남기고, 특정 상황에서만 필요한 상세 지침은 Skills로 빼라. 이것만으로도 토큰 비용을 상당히 줄일 수 있다.
CLAUDE.md에 이렇게 적어두면 된다:
## Workflows
- PR review: use /pr-review skill
- DB migration: use /db-migration skill
- Deployment: use /deploy skill
동적 컨텍스트
CLAUDE.md에 모든 걸 다 적을 필요 없다. 참조만 걸어두면 Claude가 필요할 때 직접 읽는다.
## References
- Architecture details: see `docs/ARCHITECTURE.md`
- API conventions: see `docs/API_CONVENTIONS.md`
- DB schema: see `docs/schema/README.md`
이렇게 하면 CLAUDE.md 자체는 짧게 유지하면서도, Claude가 필요한 정보에 접근할 수 있다. CLAUDE.md에 100줄짜리 아키텍처 설명을 넣는 대신, 별도 파일에 두고 참조를 걸면 필요할 때만 토큰을 소비한다.
실전 템플릿
바로 복사해서 쓸 수 있는 템플릿이다. Kotlin/Spring Boot 프로젝트 기준이지만, 구조는 어떤 프로젝트에도 적용 가능하다.
# Project
Order management API — Kotlin + Spring Boot 3.2 + Exposed ORM.
Multi-tenant SaaS, schema-per-tenant. PostgreSQL 16, Redis 7.
Deployed on AWS ECS Fargate.
## Tech Stack
- Language: Kotlin 1.9, Java 21
- Framework: Spring Boot 3.2
- ORM: Exposed (DSL style, not DAO)
- Test: Kotest 5 + MockK
- Build: Gradle (Kotlin DSL)
## Commands
- Build: `./gradlew build`
- Test: `./gradlew test`
- Test single: `./gradlew test --tests "*.OrderServiceSpec"`
- Run: `./gradlew bootRun --args='--spring.profiles.active=local'`
- Lint: `./gradlew ktlintCheck`
- DB migrate: `./gradlew flywayMigrate -Dflyway.env=local`
## Architecture
- Controller → Service → Repository (3-layer only)
- No business logic in controllers — delegate to service
- All DB access via Repository layer using Exposed DSL
- External API calls: use coroutines (suspend fun), not block()
- Events: ApplicationEventPublisher → @Async @EventListener
## Conventions
- API responses: always wrap in `ApiResponse<T>`
- DTOs: `*Request`, `*Response` suffix
- Test files: `*Spec.kt` (Kotest style)
- Use `kotlinx.datetime`, not java.time
- Use `val`, avoid `var`
- Constructor injection only (no @Autowired)
- No wildcard imports
## Do NOT
- Do not use JPA/Hibernate — Exposed only
- Do not add comments unless logic is non-obvious
- Do not create utility classes for one-off logic
- Do not modify /generated/ directory
- Do not add dependencies without approval
- Do not use runBlocking in production code
- Do not put SQL in service layer
## References
- Architecture details: `docs/ARCHITECTURE.md`
- API design guide: `docs/API_GUIDE.md`
- DB schema: `docs/schema/README.md`
## Workflows
- PR review: use /pr-review skill
- DB migration: use /db-migration skill
약 60줄이다. 이 정도면 프로젝트의 핵심을 빠짐없이 전달하면서도 토큰 부담이 크지 않다.
흔한 실수 5가지
1. 너무 길게 쓴다
CLAUDE.md는 매 메시지마다 컨텍스트에 포함된다. 500줄짜리 CLAUDE.md는 매번 500줄 분량의 토큰을 먹는다. 하루에 100번 메시지를 보내면 50,000줄 분량의 토큰이 CLAUDE.md에만 쓰인다.
200줄을 넘기면 적신호다. Skills로 분리하고, 참조로 빼고, 정말 매번 필요한 것만 남겨라.
2. 너무 추상적으로 쓴다
# 나쁜 예
- Write clean, maintainable code
- Follow best practices
- Use proper error handling
이건 아무 의미가 없다. Claude도 사람도 "clean code"의 정의가 다르다.
# 좋은 예
- Functions: max 30 lines, max 3 parameters
- Error handling: use Result<T> for expected failures, throw for bugs
- All public functions must have KDoc
구체적인 숫자, 구체적인 패턴, 구체적인 도구명. 이게 실행 가능한 지시다.
3. 코드에서 이미 알 수 있는 걸 반복한다
# 불필요
- Project uses Gradle for building (build.gradle.kts가 있으면 당연히 안다)
- Source code is in src/main/kotlin (표준 구조면 안다)
- We use Spring Security (SecurityConfig.kt가 있으면 안다)
Claude는 코드를 직접 읽는다. build.gradle.kts를 보면 Gradle인 걸 안다. package.json을 보면 어떤 라이브러리를 쓰는지 안다. 코드만으로 알 수 없는 것만 써야 한다. "Exposed를 쓴다"는 코드를 봐도 알지만 "JPA를 쓰지 마라"는 코드만 봐서는 모른다 — 이런 게 써야 할 내용이다.
4. 업데이트를 안 한다
프로젝트는 진화한다. 6개월 전에 쓴 CLAUDE.md가 지금도 맞을까? 라이브러리 버전이 올라가고, 아키텍처 패턴이 바뀌고, 새 컨벤션이 추가된다.
CLAUDE.md도 코드다. 코드 리뷰할 때 CLAUDE.md도 같이 봐야 한다. 스프린트가 끝날 때마다 한 번씩 훑어보는 습관을 들여라.
팁: Claude Code한테 "현재 프로젝트 상태를 보고 CLAUDE.md가 최신인지 확인해줘"라고 시키는 것도 방법이다.
5. Skills를 안 쓴다
모든 지침을 CLAUDE.md 하나에 넣으려고 한다. PR 리뷰 규칙 30줄, DB 마이그레이션 가이드 20줄, 배포 절차 25줄, API 설계 규칙 30줄... 합치면 300줄이 넘는다.
이 중 항상 필요한 건 20%도 안 된다. 나머지 80%는 특정 작업을 할 때만 필요하다. Skills로 빼면 CLAUDE.md는 60줄로 줄이고, 필요한 순간에만 상세 지침을 로드할 수 있다.
요약
- CLAUDE.md는 Claude Code에게 주는 온보딩 문서다. 없으면 매번 같은 걸 반복 설명해야 한다.
- 세 레벨(글로벌/프로젝트/서브디렉토리)을 전략적으로 활용하라.
- 필수 5섹션: 프로젝트 개요, 코드 컨벤션, 빌드 명령어, 아키텍처 규칙, 금지 목록.
- 금지 목록이 가장 효과적이다. Claude의 기본 성향을 꺾는 건 "하지 마"뿐이다.
- 200줄 이하로 유지하라. 매 메시지마다 토큰을 먹는다는 걸 잊지 마라.
- 구체적으로 써라. "clean code" 대신 "함수 30줄 이하, 파라미터 3개 이하".
- Skills로 분리하라. 항상 필요한 핵심만 CLAUDE.md에, 나머지는 Skills로.
- 정기적으로 갱신하라. CLAUDE.md도 코드처럼 유지보수 대상이다.
파일 하나로 Claude Code의 품질이 달라진다. 10분 투자해서 CLAUDE.md를 제대로 쓰면, 그 이후 수백 번의 대화에서 시간을 아낀다.
관련글:
- Claude Code 토큰 비용 실전 절약법: 공식 문서 기반 7가지 전략 — CLAUDE.md 길이가 비용에 미치는 영향
- Claude Code 해부학 Part 12: 메모리 시스템 분석 — CLAUDE.md가 로드되는 내부 구조
'AI 코딩 에이전트' 카테고리의 다른 글
| Claude Code 숨겨진 키보드 단축키 & 치트시트: 속도가 2배 되는 조합들 (0) | 2026.04.11 |
|---|---|
| Claude Code Hooks 실전 활용법: 커밋 전 자동 검사부터 Slack 알림까지 (0) | 2026.04.11 |
| Claude Code 토큰 비용 실전 절약법: 공식 문서 기반 7가지 전략 (0) | 2026.04.10 |
| GitHub Agent HQ: Copilot 안에서 Claude와 Codex를 동시에 돌리는 구조 (0) | 2026.04.10 |
| Claude Code Agent Teams: AI 여러 마리를 동시에 굴리는 법 (0) | 2026.04.10 |
