Claude Code에서 CLAUDE.md를 최적화해 컨텍스트 낭비를 줄인 방법
배경: SaaS 프로젝트(CHAPLO — 교회 홈페이지 빌더)를 Claude Code로 개발하던 중,
세션을 시작하자마자 컨텍스트가 22%나 소비된다는 사실을 발견했다.
원인을 파악하고 CLAUDE.md를 76% 줄인 과정을 기록한다.
문제 발견
Claude Code 세션을 열고 첫 메시지를 보내기도 전에 컨텍스트가 22%였다.
아무것도 하지 않았는데 컨텍스트 1/5이 사라진 것이다. 긴 개발 세션에서는 이 초기 낭비가 누적되어 중간에 컨텍스트 압축이 일어나거나, 후반부 작업 품질이 떨어지는 원인이 된다.
원인 분석
세션 시작 시 컨텍스트를 소비하는 요소들을 분류하면 다음과 같다.
| 원인 | 비중 | 제어 가능 여부 |
|---|---|---|
~/.claude/CLAUDE.md (OMC 글로벌 설정) |
~8% | ❌ 제어 불가 |
프로젝트 CLAUDE.md |
~5% | ✅ 개선 가능 |
<system-reminder> deferred tools 목록 |
~4% | ❌ 제어 불가 |
| MCP 서버 지시문 | ~2% | ❌ 제어 불가 |
/memory-start 메모리 파일 4개 |
~3% | ⚠️ 선택적 실행 |
OMC(oh-my-claudecode), deferred tools, MCP 지시문은 프레임워크 레벨이라 손댈 수 없다.
반면 프로젝트 CLAUDE.md는 직접 최적화할 수 있는 유일한 영역이었다.
CLAUDE.md가 뭐길래 문제인가
Claude Code는 프로젝트 루트의 CLAUDE.md를 시스템 프롬프트에 포함시켜서 매 메시지마다 자동으로 로드한다.
즉, 대화 한 번 할 때마다 이 파일 전체가 컨텍스트에 올라간다. 파일이 클수록 매 턴마다 그만큼의 토큰이 소비된다. 세션이 길어질수록 누적 낭비는 더 커진다.
기존 CLAUDE.md의 문제
당시 CLAUDE.md는 161줄이었고, 내용 구성은 다음과 같았다.
- 프로젝트 개요 6줄 ✅ 필요
- 현재 상태 (bold 목록) 12줄 ❌ handoff.md와 중복
- Figma 파일 ID 5줄 ⚠️ 쓸 때만 필요
- 기술 스택 표 13줄 ❌ architecture.md에 있음
- 주요 결정사항 25개 28줄 ❌ decisions.md와 100% 중복
- 플랜 구조 표 8줄 ❌ PRD에 있음
- MVP 기능 범위 18줄 ❌ PRD에 있음
- 제품 로드맵 5줄 ❌ PRD에 있음
- 다음 우선순위 8줄 ✅ 필요
- 메모리 시스템 안내 7줄 ✅ 필요문제의 핵심은 같은 정보가 여러 곳에 중복 저장되어 있다는 점이었다.
특히 "주요 결정사항 25개 항목"은 memory/decisions.md에 이미 전부 있는 내용이었다. CLAUDE.md에도 넣어두면 세션마다 decisions.md를 로드하지 않아도 된다는 편의를 위해서였겠지만, 결과적으로:
- CLAUDE.md 로드 → 결정사항 25개 로드됨
/memory-start실행 → decisions.md에서 동일한 결정사항이 다시 로드됨
같은 내용이 세션마다 두 번 올라가는 구조였다.
CLAUDE.md의 올바른 역할
핵심 원칙은 하나다.
CLAUDE.md는 "나침반"이어야 한다. 세부 지도는 필요할 때 펼친다.
Claude가 매 메시지마다 알아야 하는 것:
- 이 프로젝트가 무엇인가
- 지금 어디쯤 와 있는가
- 다음에 무엇을 해야 하는가
- 세부 정보는 어디에 있는가
Claude가 매 메시지마다 알 필요 없는 것:
- 전체 기술 스택 표 (architecture.md에 있음)
- 25개의 의사결정 목록 (decisions.md에 있음)
- MVP 기능 전체 목록 (PRD에 있음)
- 플랜별 가격 정책 (PRD에 있음)
개선 방법
1단계: 이동할 내용 파악
Figma 파일 ID 3개는 어느 파일에도 없었다. 이건 별도 참조 파일을 만들어 보관하기로 했다.
docs/figma-refs.md # 신규 생성
기술 스택, 결정사항, MVP 범위, 플랜 구조는 이미 각각의 문서에 있으므로 CLAUDE.md에서 제거하고 포인터(경로)만 남겼다.
2단계: CLAUDE.md 재작성
Before (161줄):
## 주요 결정사항
- 도메인 전략: Tier 1 서브도메인({slug}.platform.com) 전체 플랜 제공 / ...
- 서브도메인 자동 할당: 교회명 기반 slug 자동 생성 (한글 → 로마자 변환), ...
- 인증: /auth 단일 페이지에서 로그인·회원가입 통합 처리. 이메일 로그인 + ...
... (22개 항목 더)
## 기술 스택 (확정)
| 레이어 | 기술 |
| ---------- | ---------------------------------- |
| Frontend | Next.js 14 (App Router) |
| Backend/DB | Supabase (PostgreSQL + Auth + RLS) |
... (8줄 더)
## MVP 기능 범위
- 교회 생성 + 서브도메인 자동 할당
- 온보딩: /auth(로그인·회원가입 통합) + 공통 4단계 ...
... (12개 항목 더)
After (38줄):
# CHAPLO (Church Website Platform)
> **서비스명: CHAPLO** — 로고: 원형 앰버 체크 아이콘 + "CHAPLO" 텍스트
**Role: builder** — 기획 · 디자인 · 개발 전 과정 직접 수행
## 문서 위치
- PRD: `docs/prd/church-website-platform-prd-v0.7.md`
- 아키텍처·기술스택: `docs/tech/architecture.md`
- 개발 규칙: `docs/tech/dev-rules.md`
- Figma IDs: `docs/figma-refs.md`
## 현재 상태 (2026-04-30)
Next.js 14 셋업 완료. **다음: Supabase DB 마이그레이션.**
브랜드: `#1C1410` (웜 다크 브라운) + `#F0B429` (골드 앰버). 테마: Urban / Heritage / Cozy.
## 다음 우선순위
1. Supabase 프로젝트 생성 + DB 마이그레이션
2. Middleware 서브도메인 라우팅 구현
3. /auth 페이지 구현
4. 온보딩 4단계 + /complete 구현
5. Admin 대시보드 8개 탭 구현
## 메모리 시스템
- `memory/handoff.md` — 세션 인계
- `memory/patterns.md` — 코드 패턴
- `memory/decisions.md` — 기술 결정
- `memory/errors.md` — 에러 해결책
세션 시작: `/memory-start` | 세션 종료: `/session-end`
결과
| 항목 | Before | After |
|---|---|---|
| 줄 수 | 161줄 | 38줄 |
| 추정 토큰 | ~2,500 tok | ~700 tok |
| 세션당 절감 | — | ~1,800 tok (약 72%) |
| 초기 컨텍스트 기여 | ~5%p | ~1.5%p |
전체 세션 시작 컨텍스트: 22% → 18~19% 수준으로 감소.
극적인 변화는 아니지만, 이건 매 세션·매 메시지마다 누적되는 낭비를 줄인 것이기 때문에 긴 개발 세션일수록 체감 차이가 커진다.
기대했지만 변화 없는 것들
이 최적화를 진행하면서 중요한 사실을 확인했다.
"CLAUDE.md를 줄여도 /memory-start를 실행하면 결국 같은 정보가 올라오지 않나?"
반만 맞다.
/memory-start로 로드되는 메모리 파일 내용: 변화 없음- CLAUDE.md가 매 메시지마다 시스템 프롬프트에 붙는 분량: 72% 감소
핵심 차이는 로드 주기다. 메모리 파일은 세션 시작 시 한 번만 로드되어 대화 히스토리에 쌓인다. CLAUDE.md는 매 메시지마다 시스템 프롬프트에 새로 포함된다. 파일이 클수록 모든 메시지에서 그 비용을 치른다.
배운 점
1. CLAUDE.md는 "항상 필요한 것"만 담아야 한다
Claude가 코드를 작성하거나 계획을 세울 때 매번 참고해야 하는 정보만 넣어야 한다. "언젠가 필요할 수도 있는" 정보는 별도 파일로 분리하고 경로만 남긴다.
2. 중복이 가장 큰 적이다
같은 내용이 CLAUDE.md와 memory 파일에 동시에 존재하는 순간, 두 번 로드된다. 한쪽은 항상(시스템 프롬프트), 다른 쪽은 세션 시작 시(대화 히스토리). 정보는 한 곳에만 있어야 한다.
3. 컨텍스트 낭비는 대부분 "정리하지 않은 히스토리"에서 온다
프로젝트가 진행될수록 CLAUDE.md는 "지금까지 결정한 것들의 저장소"가 되는 경향이 있다. 하지만 결정사항은 decisions.md에, 진행 상황은 handoff.md에, 에러는 errors.md에 있어야 한다. CLAUDE.md는 그것들로 가는 입구여야 한다.
4. 줄일 수 없는 것들도 있다
OMC 글로벌 설정, deferred tools 목록, MCP 서버 지시문은 프레임워크 레벨이라 손댈 수 없다. 제어 가능한 영역에 집중하는 것이 현실적이다. 이번 경우 "프로젝트 CLAUDE.md"가 유일하게 직접 개선 가능한 부분이었다.
5. 문서는 읽히는 맥락에 맞게 설계해야 한다
CLAUDE.md: 항상, 자동, 비용 발생 → 최소한으로
architecture.md: 필요할 때, 수동, 비용 없음 → 상세하게
같은 내용이라도 어디에 두느냐에 따라 컨텍스트 비용이 달라진다. 문서를 설계할 때 "언제 읽히는가"를 먼저 생각해야 한다.
정리
Claude Code로 개발할 때 CLAUDE.md는 프로젝트의 "인사말" 역할을 한다. 인사말이 너무 길면 본론을 시작하기도 전에 지친다. 짧고 명확하게, 필요한 것만, 나머지는 링크로.
CLAUDE.md = 나침반. 지도가 아니다.