CLAUDE.md는 명령어가 아니라 계약서다.
CLAUDE.md에 규칙만 적으면 AI가 엇나간다. "왜"를 같이 적어야 AI가 명시 안 된 상황에서도 의도대로 움직인다.
CLAUDE.md에 분명히 적어뒀다. "커밋은 명시적으로 요청할 때만."
근데 AI가 알아서 커밋을 날린다.
반대로 규칙을 너무 많이 써놨더니, AI가 지키는 건지 마는 건지 모르겠는 상황도 생긴다. 사실 두 경우 모두 같은 이유다. CLAUDE.md를 명령 목록처럼 쓰고 있기 때문이다.
AI는 규칙을 기계적으로 실행하지 않는다. 맥락으로 읽고 판단한다. 그래서 "왜 이 규칙이 있는가"를 함께 적어야 명시 안 된 상황에서도 의도대로 행동한다.
Claude Code는 CLAUDE.md를 세 곳에서 읽는다.
~/.claude/CLAUDE.md ← 글로벌
{project}/CLAUDE.md ← 프로젝트 루트
{subdir}/CLAUDE.md ← 서브디렉토리
세 파일 모두 동시에 로드된다. 더 하위 경로 규칙이 우선하지만, 같은 주제가 두 곳에 있으면 AI가 어느 쪽을 따를지 모호해진다.
실제로 이런 일이 생긴다. CLAUDE.md가 점점 뚱뚱해져서 정리하다 보면, 루트에 이미 있던 또 다른 CLAUDE.md를 발견하는 경우다. 모르고 중복 작성된 규칙이 둘 다 로드되고, 충돌하면 AI가 자의적으로 해석한다.
예방법은 단순하다. 각 CLAUDE.md 상단에 "이 파일이 담당하는 범위"를 한 줄 적어둔다.
<!-- ~/.claude/CLAUDE.md -->
# 글로벌 설정
모든 프로젝트에 공통 적용되는 개인 작업 스타일만 담는다.
프로젝트별 규칙은 각 레포의 CLAUDE.md에.
나쁜 규칙과 좋은 규칙, 차이는 딱 하나다.
# ❌ 무엇만 있음
커밋은 명시적으로 요청할 때만 생성할 것
# ✅ 왜가 있음
커밋은 명시적으로 요청할 때만 생성할 것.
→ "수정", "고쳐줘", "변경"은 커밋 요청이 아니다.
→ 사용자가 변경 내용을 검토한 뒤 커밋 여부를 결정하는 게 원칙.
이유가 있으면 AI가 "수정해줘"와 "커밋해줘"를 정확히 구분한다. 없으면 비슷한 상황에서 자의적으로 해석한다.
보안 규칙도 마찬가지다.
# ❌
토큰을 URL 파라미터로 노출하지 말 것
# ✅
토큰을 URL 파라미터로 노출하지 말 것.
→ 브라우저 히스토리, 서버 로그, Referer 헤더에 노출된다.
→ 대안: Authorization 헤더 또는 HttpOnly 쿠키.
이유 없이 금지만 하면 AI가 다른 불안전한 방법을 선택할 수 있다. 이유가 있으면 AI도 같은 이유로 다른 대안을 거른다.
길어진 CLAUDE.md를 정리하다 보면 자연스럽게 일부를 스킬로, 일부를 memory 파일로 옮기게 된다. 이때 충돌이 생길 수 있다.
| 저장소 | 언제 로드되나 | 충돌 가능성 |
|---|---|---|
| CLAUDE.md | 세션 시작 시 항상 | 계층 간 중복 시 |
| memory 파일 | 대화 맥락으로 함께 | CLAUDE.md와 같은 주제 겹칠 때 |
| 스킬 | 명시적으로 호출할 때만 | 없음 |
CLAUDE.md와 memory에 같은 주제가 있으면 AI가 어느 쪽을 따를지 모호해진다. 기술적 충돌이라기보다 우선순위가 불명확해지는 문제다.
분리 기준은 하나의 질문으로 정리된다.
"6개월 뒤에도 팀 규칙으로 유효한가?" → CLAUDE.md
"대화를 거치며 쌓인 개인 선호인가?" → memory
"특정 작업에서만 쓰는 절차인가?" → 스킬
"CSS 계산 시 padding을 빼야 한다"는 팀 규칙이니 CLAUDE.md. "이 사람은 em dash를 싫어한다"는 대화에서 파악한 것이니 memory. "PR 생성 절차"는 스킬.