← 목록으로AI WORKFLOW

CLAUDE.md는 시스템 프롬프트가 아닙니다 — 그래서 규칙이 안 먹습니다 (복붙용 템플릿 3종)

CLAUDE.md는 시스템 프롬프트가 아닙니다 — 그래서 규칙이 안 먹습니다 (복붙용 템플릿 3종)

같은 지시를 세 번째 붙여넣고 있다면 그건 이미 파일이어야 합니다. “주석은 왜 쓰는지만”, “에러는 삼키지 말고 던져”, “테스트 먼저”. 매번 타이핑하는 대신 한 번 적어두면 되는 것들입니다.

그런데 파일로 옮겨놓고도 안 먹는 경우가 많은데, 대부분 분량 문제이거나 애초에 그 파일의 성격을 잘못 알고 있어서입니다.

CLAUDE.md는 시스템 프롬프트가 아닙니다

공식 문서가 직접 이렇게 적어뒀습니다.

CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself.

시스템 프롬프트 다음에 사용자 메시지로 들어갑니다. 같은 문서의 다음 문장은 더 분명합니다. “Claude reads it and tries to follow it, but there’s no guarantee of strict compliance.” 읽고 따르려 하지만 엄격한 준수는 보장되지 않는다는 말이고, 이게 왜 중요하냐면 기대치가 달라지기 때문입니다. CLAUDE.md는 설정 파일이 아니라 부탁입니다. 문서도 같은 표현을 씁니다. “context, not enforced configuration.” 그래서 반드시 실행돼야 하는 건 여기 적으면 안 됩니다.

원하는 것 써야 할 곳
커밋 전에 무조건 린트 PreToolUse hook
특정 경로 수정 차단 설정의 permissions.deny
진짜 시스템 프롬프트 레벨 --append-system-prompt
코딩 스타일, 컨벤션, 맥락 CLAUDE.md

“무조건”이 붙는 규칙을 CLAUDE.md에 적고 지켜지길 기대하는 게 첫 번째 실패 지점입니다.

추상적인 지시는 검증이 안 되니까 안 먹습니다

공식 문서가 나란히 붙여둔 대조 예시입니다.

"Use 2-space indentation"          ← "Format code properly"
"Run `npm test` before committing" ← "Test your changes"
"API handlers live in src/api/handlers/" ← "Keep files organized"

왼쪽은 지켰는지 안 지켰는지 눈으로 확인되지만 오른쪽은 확인이 안 되고, 확인이 안 되는 지시는 모델도 어떻게 하면 만족인지 모릅니다. 그래서 규칙을 쓸 때 걸어보는 기준은 이겁니다. 이걸 어겼는지 내가 diff만 보고 판정할 수 있는가. 못 하면 그 문장은 더 구체적으로 내려가야 합니다.

분량의 함정: 많이 쓸수록 잘 따르지 않습니다

규칙을 늘리면 늘린 만큼 따를 것 같지만 반대입니다. 2025년 7월에 나온 IFScale 벤치마크가 이걸 직접 쟀는데, 업무 보고서 작성 과제에 키워드 포함 지시를 10개에서 500개까지 늘려가며 20개 모델을 돌린 결과 최고 성능 모델도 500개 지점에서 68%에 그쳤습니다. 더 쓸모 있는 건 열화 패턴이 갈리는 방식입니다.

패턴 해당 모델 양상
임계 붕괴 Gemini 2.5 Pro, o3 150~250개까지 거의 완벽, 이후 급락
선형 열화 gpt-4.1, claude-sonnet-4 처음부터 꾸준히 하락
지수 열화 gpt-4o, llama-4-scout 초반부터 빠르게 붕괴

“150250개까지는 괜찮다“는 상위 추론 모델에만 해당합니다. 나머지는 임계점 같은 게 없어서 1번 지시부터 이미 깎이고, 소형 모델은 715%대 바닥에 눌러앉습니다. 그리고 논문이 짚은 것 중에 실무에서 제일 써먹을 만한 건 따로 있는데, 모델이 앞쪽 지시에 편향된다는 대목입니다. 뒤에 적은 규칙일수록 덜 지켜집니다. 그러니 규칙은 최소로 유지하고, 제일 중요한 걸 맨 위에 둡니다. 공식 문서의 권장치는 파일당 200줄 미만이고, HumanLayer는 300줄 미만을 권하면서 자사 루트 파일은 60줄 미만으로 유지한다고 밝혔습니다.

템플릿 3종

그대로 쓰라고 드리는 게 아닙니다. 자기 것으로 고치는 출발점이니 각 항목마다 “이걸 어겼는지 diff로 판정되는가”를 걸어보고, 안 되면 지우거나 더 내려가세요.

1. 개인 스타일형 (~/.claude/CLAUDE.md)

전 프로젝트에 적용되는 개인 취향입니다. 스택 이야기는 넣지 않습니다.

# 개인 작업 규칙

## 코드
- 주석은 "무엇"이 아니라 "왜"만 적는다. 코드로 읽히는 건 주석 금지.
- 에러를 조용히 삼키지 않는다. `catch`에서 로그만 찍고 넘어가지 않는다.
- 이름은 줄이지 않는다. `usr`, `cfg`, `tmp2` 금지.
- 한 함수가 화면을 넘기면 자른다.

## 응답
- 결론 먼저, 근거는 그다음.
- 코드를 보여줄 때 변경된 부분만. 전체 재출력 금지.
- 확신이 없으면 "모르겠다"고 쓴다. 추측을 사실처럼 쓰지 않는다.

## 금지
- 요청하지 않은 리팩터링
- 요청하지 않은 의존성 추가
- 테스트를 통과시키려고 테스트를 고치는 것

2. 프로젝트 컨벤션형 (./CLAUDE.md)

팀과 공유되는 파일입니다. 개인 취향을 여기 넣으면 남이 불편해집니다.

# <프로젝트명>

<한 줄 설명. 무엇을 하는 서비스인가.>

## 스택
- <런타임/프레임워크와 버전>
- <DB와 접근 방식>
- <배포 대상>

## 명령
- 개발: `<command>`
- 테스트: `<command>`
- 빌드: `<command>`

## 구조
- `src/<dir>/` — <무엇이 사는 곳인가>
- `src/<dir>/` — <무엇이 사는 곳인가>

## 규칙
- 커밋 전 `<test command>` 통과 필수.
- `main`에 직접 커밋 금지. 브랜치 + PR.
- <프로젝트 고유의 함정 1~2개. 도구 기본값과 다른 것만.>

## 건드리지 말 것
- `<path>` — <이유>

## 규칙## 건드리지 말 것은 도구 기본값과 다른 것만 적으세요. 일반적인 모범 사례는 모델이 이미 아니까, 적을수록 남은 규칙의 지분이 올라갑니다.

3. 역할 지정형 (.claude/agents/<role>.md)

작업 유형마다 인격을 나누는 방식입니다. 리뷰어에게 구현을 시키지 않고, 구현자에게 자기 코드를 승인시키지 않습니다.

---
name: reviewer
description: 변경된 diff를 검토한다. 코드를 직접 수정하지 않는다.
model: opus
---

너는 이 저장소의 리뷰어다. 구현하지 않는다.

## 보는 것
1. 이 변경이 기존 호출부를 깨뜨리는가
2. 새로 생긴 분기 중 테스트가 없는 것
3. 이미 있는 유틸을 두고 다시 구현한 것
4. 경계(인증·결제·외부 입력)에서의 검증 누락

## 출력
- 발견마다: `파일:줄` — 무엇이 문제인가 — 어떤 입력에서 깨지는가
- 마지막 줄에 SHIP 또는 NO-SHIP

## 하지 않는 것
- 파일 수정
- 스타일 지적 (린터 담당)
- "좋아 보입니다" 같은 내용 없는 승인

역할 분리가 실제로 효과를 내는 이유는 하네스 엔지니어링 글에 따로 정리해뒀습니다. 요청 한 건을 잘 쓰는 쪽은 프롬프트 작성법입니다.

어디에 두고, 겹치면 뭐가 이기나

로드 순서는 넓은 범위에서 좁은 범위로 갑니다.

범위 위치
조직 정책 macOS /Library/Application Support/ClaudeCode/CLAUDE.md
개인 (전 프로젝트) ~/.claude/CLAUDE.md
프로젝트 (팀 공유) ./CLAUDE.md 또는 ./.claude/CLAUDE.md
프로젝트 (개인) ./CLAUDE.local.md — gitignore 대상

아래쪽이 위쪽을 덮어쓴다고 착각하기 쉬운데, 실제로는 그냥 이어붙습니다. 문서 표현으로 “concatenated into context rather than overriding each other”입니다. 위에서부터 순서대로 쌓이고, 나중에 읽히는 쪽이 더 가깝습니다.

그래서 모순되는 규칙을 양쪽에 두면 어느 쪽도 이기지 않고 아무거나 골라집니다. 문서도 “Claude may pick one arbitrarily”라고 적어뒀습니다. 계층을 나눌 때 기준은 우선순위가 아니라 범위여야 하고, 전역에는 프로젝트와 무관한 것만, 프로젝트에는 그 저장소에서만 참인 것만 둡니다.

경로별로 더 쪼개고 싶으면 .claude/rules/paths: 프런트매터를 달면 되는데, 이러면 해당 파일을 읽을 때만 로드돼서 평소 컨텍스트를 안 먹습니다.

---
paths:
  - "src/api/**/*.ts"
---

- 모든 엔드포인트에 입력 검증을 넣는다.
- 에러 응답은 공통 포맷을 쓴다.

긴 문서는 본문에서 빼세요

빌드 절차나 배포 런북처럼 긴 레퍼런스를 CLAUDE.md에 넣으면 200줄이 금방 차니까, 필요할 때만 읽히게 분리하는 쪽이 낫습니다. @path import도 있지만 이건 분량 문제를 해결하지 못합니다. import된 파일은 시작 시점에 같이 로드되고, 문서도 “imported files still load and enter the context window at launch.“라고 명시합니다. 정리에는 도움이 되지만 컨텍스트는 그대로 듭니다. 중첩은 최대 4홉까지입니다.

진짜로 줄이려면 스킬이나 .claude/rules/의 경로 스코프를 쓰면 되고, 이쪽은 호출되거나 매칭될 때만 들어옵니다. /memory, /context 같은 명령으로 실제 로드 상태를 확인하는 방법은 슬래시 명령어 정리에 있습니다.

안 먹는 규칙은 지웁니다

규칙 파일은 쌓이기만 하고 줄지 않으니 주기적으로 걷어내야 합니다.

  • /context로 파일이 실제 로드됐는지 확인합니다. 목록에 없으면 모델은 애초에 못 봅니다.
  • 최근 작업에서 어긴 규칙을 찾습니다. 한 번 어겼으면 더 구체적으로 내리고, 두 번 어겼으면 그 규칙은 hook으로 옮길 후보입니다.
  • 모순을 찾습니다. 전역과 프로젝트가 다른 말을 하고 있으면 하나를 지웁니다.
  • 모델이 이미 아는 걸 지웁니다. 일반적인 모범 사례는 지분만 차지합니다.

제 계층을 재봤습니다

이 블로그 저장소 기준입니다.

~/.claude/CLAUDE.md          134 lines  (8,455 bytes)
./CLAUDE.md                    9 lines    (473 bytes)

합쳐서 143줄입니다. 200줄 기준 안쪽이고, 앞의 134줄이 전부 개인 규칙이라 프로젝트별로 다시 쓰지 않아도 됩니다. 프로젝트 파일 9줄에는 이 저장소에서만 참인 것만 남겼는데, 어떤 작업을 어떤 모델에 보낼지와 구현한 에이전트가 자기 diff를 승인하지 못한다는 규칙 정도입니다.

.claude/rules/는 안 씁니다. 대신 .claude/skills/로 긴 절차를 빼뒀습니다. 발행 파이프라인 같은 건 평소에 들고 있을 이유가 없으니까요.

정리

  • CLAUDE.md는 강제력이 없습니다. 무조건 실행돼야 하는 건 hook으로 옮깁니다.
  • diff로 판정 안 되는 문장은 규칙이 아닙니다.
  • 200줄 안쪽으로 유지하고, 위에서부터 중요한 순으로 적습니다. 아래로 갈수록 덜 지켜집니다.
  • 계층은 범위로 나눕니다. 모순은 승자를 만들지 않고 무작위를 만듭니다.
  • 긴 문서는 스킬이나 경로 스코프로 빼세요. @import는 컨텍스트를 줄여주지 않습니다.

템플릿을 그대로 복사하는 것보다, 지금 쓰고 있는 파일을 열어서 diff로 판정 안 되는 줄을 지우는 게 먼저입니다. 대개 절반쯤 줄어듭니다.

참고