Claude Code 완전 정복 가이드 Part 2: CLAUDE.md 최적화 - 비대해지는 것을 막아라
이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.
예상 소요 시간: 45분 난이도: ⭐⭐ 사전 요구사항: Part 1 완료, CLAUDE.md 사용 경험 Claude Code 버전: 2.1.x
1. 왜 CLAUDE.md는 간결해야 하는가?#
1.1 LLM의 Instruction-following 한계#
연구에 따르면 프론티어 LLM도 약 150-200개의 지시사항만 일관되게 따를 수 있습니다. Claude Code의 시스템 프롬프트 자체가 이미 ~50개의 지시를 포함하고 있어, CLAUDE.md에 사용할 수 있는 “지시 예산"은 제한적입니다.
┌─────────────────────────────────────────────────────────────────┐
│ LLM 지시 따르기 용량 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 총 용량: ~150-200개 지시 │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ Claude Code │ │ CLAUDE.md │ │ Skills/Rules │ │
│ │ 시스템 프롬프트 │ │ │ │ │ │
│ │ (~50개) │ │ (당신의 몫) │ │ (추가 지시) │ │
│ └──────────────────┘ └──────────────────┘ └────────────────┘ │
│ │
│ ⚠️ 초과 시 → 균일하게 모든 지시를 무시하기 시작 │
│ │
└─────────────────────────────────────────────────────────────────┘
1.2 토큰 비용과 Context Window#
CLAUDE.md는 모든 대화에서 항상 로드됩니다. 파일이 커질수록:
| 문제 | 결과 |
|---|---|
| 토큰 비용 증가 | 매 대화마다 불필요한 비용 발생 |
| 컨텍스트 낭비 | 실제 작업에 사용할 공간 감소 |
| 지시 희석 | 중요한 규칙이 묻힘 |
1.3 “지시를 무시하기 시작하면” 파일이 너무 긴 것#
Claude가 CLAUDE.md의 규칙을 무시하는 것 같다면, 이는 대부분 파일이 너무 길기 때문입니다.
┌─────────────────────────────────────────────────────────────────┐
│ 증상 체크리스트 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ □ Claude가 코딩 스타일 규칙을 자주 무시한다 │
│ □ 테스트 실행 명령어를 틀리게 사용한다 │
│ □ 금지한 패턴을 계속 사용한다 │
│ □ CLAUDE.md에 있는 질문을 다시 물어본다 │
│ │
│ ▶ 2개 이상 해당? → CLAUDE.md가 너무 길 가능성 높음 │
│ │
└─────────────────────────────────────────────────────────────────┘
2. CLAUDE.md 다이어트 전략#
2.1 린터가 할 수 있는 일은 린터에게#
나쁜 예: CLAUDE.md에 모든 코드 스타일 규칙 나열
# ❌ 이렇게 하지 마세요
## 코드 스타일 규칙
- 들여쓰기는 스페이스 4칸
- 세미콜론 필수
- 문자열은 작은따옴표 사용
- 최대 줄 길이 120자
- 함수 정의 후 빈 줄 1개
- import 순서: 표준 라이브러리 → 외부 패키지 → 내부 모듈
- trailing comma 사용
- 화살표 함수는 한 줄이면 중괄호 생략
- ... (50줄 더)
좋은 예: 린터에 위임하고 실행 방법만 알려주기
# ✅ 이렇게 하세요
## 코드 스타일
코드 스타일은 ESLint + Prettier로 관리됩니다.
- 린트 체크: `npm run lint`
- 자동 포맷팅: `npm run format`
작업 완료 후 반드시 `npm run lint`를 실행하세요.
2.2 포인터 vs 복사: 코드 스니펫 대신 파일 참조#
코드 스니펫을 CLAUDE.md에 직접 넣으면 빠르게 outdated 됩니다.
나쁜 예:
# ❌ 코드 스니펫 직접 포함
## API 응답 형식 예시
```java
public class ApiResponse<T> {
private boolean success;
private T data;
private ErrorInfo error;
// getter, setter...
// 50줄의 코드
}
```
좋은 예:
# ✅ 파일 참조 사용
## API 응답 형식
API 응답은 `ApiResponse<T>`를 사용합니다.
참고: `src/main/java/com/example/common/ApiResponse.java`
2.3 @path/to/file 문법으로 외부 파일 임포트#
CLAUDE.md는 @ 문법으로 다른 파일을 참조할 수 있습니다:
# CLAUDE.md
프로젝트 개요는 @README.md 참조
## 추가 가이드
- Git 워크플로우: @docs/git-workflow.md
- API 설계 규칙: @docs/api-guidelines.md
- 개인 설정: @~/.claude/my-preferences.md
이렇게 하면:
- CLAUDE.md는 간결하게 유지
- 상세 내용은 별도 파일로 관리
- 필요한 파일만 참조
3. 프로젝트별 vs 전역 설정 분리#
3.1 ~/.claude/CLAUDE.md: 개인 전역 설정#
모든 프로젝트에 적용할 개인적인 선호도를 여기에 작성합니다:
# ~/.claude/CLAUDE.md
## 커뮤니케이션 스타일
- 한국어로 응답
- 코드 변경 시 변경 이유를 간단히 설명
- 불확실한 부분은 먼저 질문
## 개인 개발 습관
- 커밋 전 항상 테스트 실행
- 브랜치명에 날짜 포함 선호: feature/20250123-description
## 선호하는 도구
- 테스트: JUnit 5 (TestNG 사용 금지)
- HTTP Client: OkHttp 선호
3.2 프로젝트 루트 CLAUDE.md: 팀 공유용#
Git에 커밋하여 팀 전체가 공유하는 규칙:
# ./CLAUDE.md (프로젝트 루트)
## 프로젝트 정보
Payment Gateway Service - 결제 처리 API
## 빌드 및 테스트
- 빌드: `./gradlew build`
- 테스트: `./gradlew test`
## 팀 규칙
- PR은 최소 1명 리뷰 필수
- main 브랜치 직접 푸시 금지
- 커밋 메시지는 Conventional Commits 형식
3.3 CLAUDE.local.md: 개인용 오버라이드#
팀 규칙 위에 개인 설정을 덮어쓸 때 사용 (.gitignore 대상):
# ./CLAUDE.local.md
## 로컬 환경 설정
- 로컬 DB: localhost:5432/mydb
- 테스트 시 `-Dspring.profiles.active=local` 추가
## 개인 작업 규칙
- 이 프로젝트에서는 TDD로 진행
- WIP 커밋 허용 (나중에 squash)
# .gitignore에 추가
echo "CLAUDE.local.md" >> .gitignore
3.4 설정 파일 선택 가이드#
┌─────────────────────────────────────────────────────────────────┐
│ 어디에 작성해야 할까? │
├─────────────────────────────────────────────────────────────────┤
│ │
│ "모든 프로젝트에 적용하고 싶다" │
│ └─▶ ~/.claude/CLAUDE.md (전역) │
│ │
│ "이 프로젝트의 모든 팀원이 사용해야 한다" │
│ └─▶ ./CLAUDE.md (프로젝트 루트, Git 커밋) │
│ │
│ "나만의 로컬 설정이 필요하다" │
│ └─▶ ./CLAUDE.local.md (프로젝트, .gitignore) │
│ │
│ "특정 모듈에서만 적용하고 싶다" │
│ └─▶ ./src/module/CLAUDE.md (하위 디렉토리) │
│ │
└─────────────────────────────────────────────────────────────────┘
4. Monorepo에서의 CLAUDE.md 전략#
4.1 루트와 서브 모듈별 구성#
monorepo/
├── CLAUDE.md # 전체 공통 규칙
├── apps/
│ ├── web/
│ │ └── CLAUDE.md # 웹 프론트엔드 규칙
│ └── api/
│ └── CLAUDE.md # API 서버 규칙
├── packages/
│ ├── ui/
│ │ └── CLAUDE.md # UI 컴포넌트 규칙
│ └── shared/
│ └── CLAUDE.md # 공유 유틸리티 규칙
└── infra/
└── CLAUDE.md # 인프라/DevOps 규칙
4.2 루트 CLAUDE.md 예시#
# Monorepo CLAUDE.md
## 전체 구조
- `apps/`: 애플리케이션 (web, api)
- `packages/`: 공유 패키지
- `infra/`: 인프라 설정
## 공통 명령어
- 전체 빌드: `pnpm build`
- 전체 테스트: `pnpm test`
- 특정 패키지: `pnpm --filter @repo/web build`
## 공통 규칙
- 패키지 간 import는 `@repo/` alias 사용
- 순환 의존성 금지
## 모듈별 상세 규칙
각 모듈의 CLAUDE.md를 참조하세요.
4.3 서브 모듈 CLAUDE.md 예시 (apps/api/)#
# API Server CLAUDE.md
## 이 모듈의 역할
NestJS 기반 REST API 서버
## 빌드 및 테스트
- 개발 서버: `pnpm dev`
- 테스트: `pnpm test`
- E2E 테스트: `pnpm test:e2e`
## 모듈 구조
src/ ├── modules/ # 기능별 모듈 (users, payments, …) ├── common/ # 공통 유틸리티 └── config/ # 설정
## API 규칙 (이 모듈 전용)
- 모든 엔드포인트는 `/api/v1/` 프리픽스
- DTO는 class-validator로 검증
- 에러 응답은 ProblemDetails (RFC 7807) 형식
4.4 동적 로딩 활용#
Claude Code는 작업 중인 파일의 위치에 따라 해당 디렉토리의 CLAUDE.md를 자동으로 로드합니다.
사용자가 apps/web/src/App.tsx 수정 요청
│
▼
Claude Code 자동 로드:
1. ~/. claude/CLAUDE.md (전역)
2. /monorepo/CLAUDE.md (루트)
3. /monorepo/apps/web/CLAUDE.md (해당 모듈) ← 동적 로드
이를 통해 모듈별로 다른 규칙을 적용하면서도 CLAUDE.md 파일 크기를 작게 유지할 수 있습니다.
5. 실습: 비대해진 CLAUDE.md 리팩토링#
5.1 Before: 비대해진 CLAUDE.md (300줄)#
# Project CLAUDE.md
## 프로젝트 정보
Spring Boot 기반 이커머스 플랫폼
## 빌드
./gradlew build
## 테스트
./gradlew test
## 코드 스타일 규칙 (100줄)
- 들여쓰기 4칸
- 최대 줄 길이 120자
- 클래스명 PascalCase
- 메서드명 camelCase
- 상수 UPPER_SNAKE_CASE
- ... (95줄 더)
## API 설계 규칙 (80줄)
- REST 원칙 준수
- URL은 명사 복수형
- HTTP 메서드 적절히 사용
- ... (77줄 더)
## 데이터베이스 규칙 (50줄)
- 테이블명 snake_case
- PK는 bigint auto_increment
- ... (48줄 더)
## Git 규칙 (30줄)
- 브랜치 전략
- 커밋 메시지 형식
- ... (28줄 더)
## 테스트 규칙 (40줄)
- 테스트 네이밍
- Mock 사용법
- ... (38줄 더)
5.2 After: 최적화된 CLAUDE.md (50줄)#
# E-Commerce Platform
Spring Boot 3.x 기반 이커머스 백엔드 서비스
## 빌드 및 테스트
- 빌드: `./gradlew build`
- 테스트: `./gradlew test`
- 단일 테스트: `./gradlew test --tests "ClassName"`
- 린트: `./gradlew ktlintCheck`
- 포맷: `./gradlew ktlintFormat`
IMPORTANT: 코드 변경 후 반드시 `./gradlew ktlintCheck test` 실행
## 프로젝트 구조
src/main/kotlin/com/shop/ ├── api/ # Controllers, DTOs ├── application/ # Use Cases ├── domain/ # Entities, Repositories └── infra/ # External integrations
## 핵심 규칙
1. 코드 스타일: ktlint가 관리, 수동 규칙 불필요
2. 테스트: Given-When-Then 구조, MockK 사용
3. 커밋: Conventional Commits (`feat:`, `fix:`, ...)
## 상세 가이드 (필요시 참조)
- API 설계: @docs/api-guidelines.md
- DB 규칙: @docs/database-conventions.md
- Git 워크플로우: @docs/git-workflow.md
5.3 분리된 파일들#
docs/api-guidelines.md:
# API 설계 가이드
## URL 설계
- 리소스는 명사 복수형: `/api/v1/users`
- 하위 리소스: `/api/v1/users/{id}/orders`
## HTTP 메서드
- GET: 조회
- POST: 생성
- PUT: 전체 수정
- PATCH: 부분 수정
- DELETE: 삭제
## 응답 형식
(상세 내용...)
docs/database-conventions.md:
# 데이터베이스 규칙
## 테이블 명명
- snake_case
- 복수형: `users`, `orders`
## 컬럼 명명
- snake_case
- boolean: `is_` 프리픽스
(상세 내용...)
5.4 리팩토링 체크리스트#
┌─────────────────────────────────────────────────────────────────┐
│ CLAUDE.md 다이어트 체크리스트 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ □ 린터로 검사할 수 있는 스타일 규칙을 제거했는가? │
│ □ 코드 스니펫 대신 파일 경로 참조로 변경했는가? │
│ □ 상세 가이드를 별도 파일로 분리했는가? │
│ □ 모든 규칙에 대해 "이게 없으면 Claude가 실수할까?" │
│ 질문을 던져보았는가? │
│ □ 핵심 규칙에 IMPORTANT 또는 대문자 강조를 추가했는가? │
│ □ 최종 파일이 100줄 이내인가? │
│ │
└─────────────────────────────────────────────────────────────────┘
6. 지시 강조 기법#
6.1 중요한 규칙 강조하기#
Claude는 특정 키워드에 더 주의를 기울입니다:
# 강조 기법 예시
## 일반 규칙
- PR 전에 테스트 실행
## 강조된 규칙 (더 잘 따름)
IMPORTANT: PR 전에 반드시 `./gradlew test` 실행
YOU MUST run tests before creating a PR.
NEVER commit directly to main branch.
ALWAYS use conventional commits format.
6.2 강조 키워드 목록#
| 키워드 | 용도 |
|---|---|
IMPORTANT: |
중요한 규칙 강조 |
NEVER |
절대 하지 말아야 할 것 |
ALWAYS |
항상 해야 할 것 |
YOU MUST |
필수 사항 |
DO NOT |
금지 사항 |
6.3 주의사항#
⚠️ 모든 규칙에 강조를 사용하면 효과가 없어집니다. 정말 중요한 2-3개 규칙에만 사용하세요.
# ❌ 과도한 강조 (효과 없음)
IMPORTANT: 들여쓰기는 4칸
IMPORTANT: 줄 끝 세미콜론
IMPORTANT: 변수명 camelCase
IMPORTANT: ... (모든 규칙에 강조)
# ✅ 선택적 강조 (효과적)
- 들여쓰기는 4칸
- 줄 끝 세미콜론
- 변수명 camelCase
IMPORTANT: main 브랜치 직접 푸시 금지. 반드시 PR 생성.
7. 정리#
이번 파트에서 배운 것#
- LLM의 한계: ~150-200개 지시만 일관되게 따를 수 있음
- 다이어트 전략:
- 린터에 위임
- 포인터(파일 참조) 사용
@path문법으로 외부 파일 임포트
- 계층적 구조: 전역 → 프로젝트 → 로컬 → 하위 디렉토리
- 강조 기법: 핵심 규칙에만 IMPORTANT, NEVER, ALWAYS 사용
핵심 질문#
모든 규칙에 대해 이 질문을 던지세요:
“이 줄을 삭제해도 Claude가 실수하지 않을까?”
대답이 “아니오"라면, 그 줄은 제거해도 됩니다.
다음 파트 예고#
CLAUDE.md를 간결하게 유지하는 것만으로는 부족합니다. 특정 작업에만 필요한 규칙들은 어떻게 관리할까요? Part 3에서는 Skills 시스템을 통해 필요할 때만 로드되는 전문 지식을 구성하는 방법을 배웁니다.
📚 참고 자료#
이전: Part 1: CLAUDE.md 기초 다음: Part 3: Skills 시스템 - 온디맨드 전문가 활용하기