CLAUDE.md 하나 대신 Claude Code에 27개의 규칙 파일을 제공한 이유
요약
단일 CLAUDE.md 파일의 한계를 극복하기 위해 규칙을 27개의 개별 파일로 분해하여 관리하는 경험을 공유합니다. 규칙의 구조화 방법, '하지 말아야 할 것(don'ts)'의 중요성, 그리고 인벤토리 활용법을 다룹니다.
핵심 포인트
- 단일 파일 대신 주제별로 분리된 다수의 규칙 파일 사용
- 규칙 구성 요소: 규칙, 추론, 하지 말아야 할 것, 인벤토리, 상호 참조
- 구체적인 '하지 말아야 할 것(don'ts)'이 처방보다 효과적임
- 인벤토리를 통해 코드와 문서 간의 불일치(drift) 감지
- paths 스코핑을 통해 필요한 위치에만 규칙을 로드하여 효율성 증대
CLAUDE.md가 한계에 다다르는 순간이 있습니다. 그 순간은 달력에 표시되지 않으며 행동으로 나타납니다. 파일은 계속 길어지고, 그 안의 규칙들은 점점 덜 지켜지게 됩니다. 새로운 관습(convention)을 작성할 때마다 기존의 것들은 희석됩니다. 이것이 바로 이 글의 배경이 된 프로젝트의 상황이었으며, 해결책은 더 나은 CLAUDE.md를 만드는 것이 아니라, 이를 개별 규칙 파일로 분해하는 것이었습니다. 현재는 27개의 파일이 존재합니다.
이 글은 경험 보고서입니다. Claude Code 규칙이 수개월 동안 유지되려면 어떻게 구조화되어야 하는지, 단일 규칙 파일이 무엇을 담아야 하는지, 그리고 왜 가장 중요한 부분이 규칙 그 자체가 아닌지(그것은 '하지 말아야 할 것(don'ts)'과 '인벤토리(inventories)'입니다)를 다룹니다.
핵심 요약:
- 관습당 하나의 파일 — 하나의 CLAUDE.md 대신 27개의 규칙 파일을 사용하며, 각 파일은 단일 주제를 다룹니다.
- 유지되는 규칙의 해부학 — 규칙(rule), 추론(reasoning), 하지 말아야 할 것(don'ts), 인벤토리(inventory), 상호 참조(cross-references).
- 처방보다 '하지 말아야 할 것'이 효과적임 — 적어도 DI² 프로젝트에서는 그렇습니다. 부정적인 예시는 구체적이고 인식하기 쉬운 반면, 처방은 기존의 학습 내용과 충돌할 수 있습니다.
- 인벤토리는 드리프트 레이더(drift radar) 역할 — 코드의 실제 상태를 주장하는 규칙의 부분이며, 따라서 코드와 문서가 어긋날 때 가장 먼저 눈에 띄게 됩니다.
paths:스코핑(scoping) — 대규모 규칙이 적용되는 위치에만 로드되도록 합니다. 27개 파일 중 3개가 이를 사용합니다.- 솔직한 단점 — 유지보수 노력, 규칙 간의 충돌, 그리고 문서가 의도적으로 코드보다 앞서 나가게 되는 상태가 발생할 수 있습니다.
사전 요구 사항 (Prerequisites). Claude Code와 .claude/rules/ 디렉토리가 포함된 프로젝트. 이 패턴은 컨벤션 (convention) 파일들을 컨텍스트 (context)에 로드하는 모든 코딩 에이전트 (coding agent)로 전이될 수 있습니다. Cursor rules나 다른 도구의 유사한 메커니즘도 동일한 원리로 작동합니다. 무엇이 언제 컨텍스트에 로드되는지, 그리고 그 비용은 얼마인지에 대해서는 형제 기사인 Skills vs. Rules in Claude Code에서 다룹니다. 본 기사는 그보다 한 단계 앞선 단계, 즉 규칙 파일 자체가 어떤 모습이어야 하는가라는 질문에서 시작합니다.
시작점: 계속해서 커져만 가던 하나의 파일
이 수치들의 배경이 되는 프로젝트는 Next.js와 PostgreSQL 기반으로 구축된 ETL 생성기인 DI²이며, 그 코드는 거의 전적으로 Claude Code를 활용한 AI 보조 방식으로 작성되었습니다. 초기에는 모든 컨벤션 (convention)이 모든 Claude Code 프로젝트가 가장 먼저 수집하는 곳, 즉 CLAUDE.md에 존재했습니다. 파일이 짧을 때까지는 이 방식이 유효합니다. 하지만 파일이 데이터베이스 컨벤션 (database conventions), 컬러 토큰 (color tokens), 커밋 규칙 (commit rules)이 모두 나란히 놓이는 컨테이너가 되는 순간, 이 방식은 작동을 멈춥니다.
이러한 효과를 측정하기는 어렵지만, 느끼기는 쉽습니다. 이는 긴 컨텍스트 (long contexts)에 관한 연구 결과와도 일치합니다. 언어 모델 (language models)은 긴 입력값의 중간에 위치한 정보를 사용하는 능력이 눈에 띄게 저하됩니다 ("Lost in the Middle", Liu et al. 2023). 제 경험상, 긴 파일의 40번째 줄에 있는 규칙은 주제별로 이름이 붙여진 별도의 파일에 있는 동일한 규칙보다 준수될 확률이 낮습니다. 두 번째 효과는 모델보다는 인간과 관련이 있습니다. 400줄짜리 파일에서는 작성자조차 해당 규칙이 여전히 유효한지 확인하고 싶을 때 그 규칙을 다시 찾지 못할 수도 있습니다. 왜 단일 파일이 구조적으로 확장될 수 없는지, 그리고 그 이면에 어떤 로딩 메커니즘 (loading mechanics)이 있는지에 대해서는 skills-vs-rules 기사에서 다룹니다. 본 기사는 그 이후의 단계에 대해 다룹니다.
프로젝트에서의 결과는 다음과 같습니다: 하나의 관습(convention)당 하나의 규칙 파일을 담은 27개의 규칙 파일이 포함된 .claude/rules/ 디렉토리입니다 (2026년 7월 22일 기준). 이 규칙 구조의 공개 버전인 GitHub의 di2-starter-kit에서도 동일한 개수가 유지되고 있으며, 하위 폴더의 README를 제외하고 직접 확인하실 수 있습니다. 테이블 관습(table conventions)을 위한 파일 하나, 대화(dialogs)를 위한 파일 하나, 로딩 상태(loading states)를 위한 파일 하나, 보안 모델(security model)을 위한 파일 하나가 있습니다. 이 디렉토리는 프로젝트와 함께 계속 성장합니다. 이 글이 작성된 바로 이번 주에 뷰(views), 트리거(triggers), 데이터베이스 정책(database policies)을 위한 세 개의 새로운 파일이 추가되었습니다. 규칙 시스템은 프로젝트가 완료될 때 완료되는데, 이는 곧 결코 완료되지 않음을 의미합니다.
유지되는 규칙의 해부학 (Anatomy of a Rule That Holds)
이 시스템을 몇 달간 사용한 결과, 고정된 구조가 나타났습니다. 유지력이 있는 규칙 파일은 다음 다섯 가지 부분으로 구성됩니다:
# <관습> (<프로젝트>)
> 한 문장 요약: 이 규칙은 무엇을 강제하며, 어디에 적용되는가?
...
규칙 자체(The Rule 아래의 처음 두세 문장)는 가장 작은 부분이며, 이는 우연이 아닙니다. 규칙은 무엇이 적용되는지를 명령형으로 서술합니다. 그 외의 모든 것은 나머지 네 부분에 속합니다.
근거(reasoning)를 제시하는 것은 독자에 대한 예의가 아닙니다. 에이전트(agent)는 트레이드오프(trade-offs)를 저울질하며, DI² 프로젝트에서 관찰된 바와 같이, 근거가 없는 규칙은 구체적인 사례에서 제시되는 그럴듯한 반론에 대해 저울질 과정에서 더 쉽게 밀리게 됩니다. 근거가 있는 규칙은 구체적인 사례가 반박해야 할 기준점을 고정합니다. 이러한 차이는 모델이 예외가 정당하다고 판단하는 바로 그 중요한 순간에 명확히 드러납니다. 관습과 그 근거가 애초에 어떻게 형성되는지는 방법론 기사인 Deriving SQL Conventions with Claude Code에서 설명합니다.
나머지 세 부분은 이 글의 실제 핵심 내용입니다. '하지 말아야 할 것(Don'ts)'과 '인벤토리(Inventory)'는 각각 아래에 별도의 섹션으로 다루며, 상호 참조(cross-references)는 그 자체로 거의 설명이 필요 없을 정도입니다. 상호 참조는 인접한 규칙과의 경계를 설정하여 두 파일이 동일한 주제를 관장하는 일이 발생하지 않도록 합니다. 나중에 발생하는 모든 경계 위반 사항은 명시적인 참조로서 그곳에 기록됩니다.
왜 '하지 말아야 할 것(Don'ts)'이 '지침(Prescriptions)'보다 나은가
이것은 DI² 프로젝트에서 수개월 동안 규칙을 유지 관리하며 얻은 핵심적인 관찰 결과입니다. 이것이 다른 프로젝트에도 적용될지는 검증되지 않았습니다. 이는 연구가 아닌 프로젝트 경험입니다. 지침(Prescription)은 마땅히 어떠해야 하는지를 말합니다. 부정적인 예시(Negative example)는 무엇을 해서는 안 되는지를 구체적이고 식별 가능한 형태(spelling)로 보여줍니다. 언뜻 보기에는 그 차이가 작아 보일 수 있습니다. 하지만 실제로는 그렇지 않습니다.
<!-- 이전: 닻(anchor)이 없는 지침 -->
폰트 크기에는 프로젝트 토큰(project tokens)만 사용하세요.
...
"프로젝트 토큰만 사용하세요"라는 지침은 사실적으로 옳지만, 성과는 거의 없습니다. 매 생성(generation) 시마다 이 규칙은 모델의 사전 학습 데이터(training prior)와 경쟁하게 되는데, 해당 데이터에서는 text-sm이 작은 텍스트를 작성하는 통계적으로 가장 흔한 방식이기 때문입니다. "프로젝트 토큰만 사용"이라는 규칙은 먼저 구체적인 사례로 번역되어야 하며, 그 번역 과정에서 규칙은 유실됩니다.
부정적인 예시는 이 번역 과정을 건너뜁니다. text-[12px]는 모델이 막 작성하려는 바로 그 문자열이며, 규칙 내에 ❌ 표시와 이유와 함께 그대로 명시됩니다. '하지 말아야 할 것(Don't)'은 해석의 여지를 남기지 않습니다. 또한 대신 적용해야 할 철자(spelling), 즉 정확한 목표 지점(snap target)을 지정합니다. 사람이든 모델이든 이 'Don't'를 읽는 사람은 이후 두 가지를 모두 알게 됩니다. 무엇이 틀렸는지, 그리고 그 자리에 무엇이 와야 하는지를 말입니다. 이것은 'Don't'만의 특별한 마법이 아니라, 프롬프트 연구(prompt research)에서 알려진 익숙한 효과입니다. 구체적인 예시는 추상적인 지침보다 언어 모델(language models)이 실행하기에 더 쉽습니다. 부정적인 예시는 규칙 파일이 이러한 효과를 활용할 수 있는 단순한 형태일 뿐입니다.
가장 훌륭한 '하지 말아야 할 것(don'ts)'은 규칙 작성자의 상상력이 아니라 실제 발견 사례에서 나옵니다. 리뷰나 버그를 통해 새로운 우회 변형(bypass variant)이 나타날 때마다, 정확히 그 변형이 규칙 파일에 '하지 말아야 할 것'으로 추가됩니다. 이를 통해 규칙 시스템은 코드가 이미 한 번 저질렀던 실수를 동일하게 학습하게 됩니다. 재료는 부족하지 않았습니다. 형제 격인 기사 AI-Assisted Coding Gave Me 799 Hardcoded Font Sizes는 폰트 크기 관련 '하지 말아야 할 것'이 도출된 계기인 드리프트(drift) 발견 사례를 기록하고 있습니다.
드리프트 레이더로서의 인벤토리 (Inventories)
규칙은 목표 상태(target state)를 명시하며, 목표 상태는 불편한 특성을 하나 가지고 있습니다. 바로 '틀릴 수 없다'는 점입니다. "모든 대화 상자에는 선행 아이콘이 포함되어야 한다"라는 문장은 아이콘이 없는 대화 상자 6개가 코드에 오랫동안 방치되어 있더라도 문장 자체로는 여전히 올바른 상태를 유지합니다. 규칙은 이 상황을 전혀 인지하지 못합니다.
인벤토리(Inventory)는 이를 변화시킵니다. 인벤토리는 관례(convention)의 구체적인 사용 위치를 실제 상태와 함께 나열합니다:
## Inventory + Retrofit Backlog
현재 이 규칙은 문서화된 진실입니다. ...가 없는 기존 사이트들
...
표(table)는 규칙 파일의 부분 중 코드의 실제 상태와 일치하지 않을 수 있는 부분입니다. 추론(reasoning) 섹션이나 상호 참조(cross-reference) 또한 오래되어 쓸모없게(stale) 될 수 있지만, 오직 인벤토리만이 현재 코드가 어떤 모습인지에 대해 검증 가능한 주장(checkable claim)을 합니다. 만약 새로운 대화 상자가 추가되었는데 표에 누락되었다면, 인벤토리는 불완전한 것입니다. 만약 목록에 있는 대화 상자가 재구축되었음에도 상태가 업데이트되지 않았다면, 인벤토리는 오래된(stale) 상태입니다. 바로 이 취약점이 인벤토리를 가치 있게 만듭니다. 인벤토리가 없는 규칙은 코드와 동떨어진 채 수년간 눈에 띄지 않고 존재할 수 있지만, 인벤토리가 있는 규칙의 지연(lag)은 늦어도 다음 조정(reconciliation) 시점에는 가시화됩니다. 인벤토리는 규칙의 드리프트 레이더(drift radar)입니다.
프로젝트 내 27개의 규칙 파일 중 9개가 이러한 섹션을 포함하고 있습니다. 이는 두 가지 형태가 있습니다. **호출자 인벤토리 (caller inventory)**는 어떤 컴포넌트나 컨벤션(convention)을 누가 사용하는지 나열합니다. 이는 누군가 검색을 시작하기 전에 "이것을 변경하면 무엇이 영향을 받는가?"라는 질문에 답해줍니다. **레트로핏 백로그 (retrofit backlog)**는 기존의 어떤 사이트들이 아직 컨벤션을 충족하지 못하는지 나열합니다. 두 형태 모두 메커니즘은 공유하지만, 바라보는 방향이 다릅니다. 하나는 규칙의 사용자들을 바라보고, 다른 하나는 규칙의 미결 부채(open debts)를 바라봅니다.
인벤토리는 별도의 문서화 세션에서 유지되는 것이 아니라, 코드 변경과 동일한 커밋(commit) 내에서 유지됩니다. 다이얼로그를 추가하는 사람은 테이블에도 이를 추가합니다. 레트로핏(retrofit)을 완료하는 사람은 상태를 ✅로 설정합니다. 이는 높은 수준의 규율을 요구하는 것처럼 들릴 수 있습니다. 하지만 에이전트 워크플로우(agent workflow)에서는 이것이 가장 비용이 적게 드는 시점입니다. 왜냐하면 에이전트는 규칙의 범위 내에서 작업할 때 보통 규칙 파일을 이미 컨텍스트(context)에 포함하고 있기 때문입니다.
적용되는 곳에서만 로드되는 규칙들
파일 수가 늘어남에 따라, 컨텍스트 비용(context-cost) 문제가 다시 제기됩니다. 27개의 파일이 항상 모두 로드된다면, 이는 동일한 비용을 소모하는 분할된 CLAUDE.md와 다를 바 없습니다. 이에 대응하는 레버(lever)는 규칙을 특정 경로 범위(path scope)에 바인딩하는 paths: 프런트 매터(front matter)입니다:
---
paths:
- "src/app/api/**"
...
프로젝트 내 27개 파일 중 3개가 이 프런트 매터를 포함하고 있습니다: 백엔드 규칙, 프런트엔드 규칙, 그리고 보안 모델입니다. 선택 기준은 간단합니다. 이 세 파일은 크기가 크며, 그 범위가 프로젝트의 명확하게 경계 지어진 서브트리(subtree)이기 때문입니다. 순수 프런트엔드 작업 내에 있는 백엔드 규칙은 죽은 컨텍스트(dead context)입니다. 나머지 24개의 파일은 크기가 작거나, 커밋 컨벤션(commit conventions)처럼 프로젝트 전체에 적용되기 때문에 범위 지정 없이(unscoped) 로드됩니다.
이 글에서는 여기서 더 깊이 들어가지 않기로 했습니다. Claude Code가 언제 무엇을 컨텍스트 (context)에 로드하는지, 규칙 (rules)과 기술 (skills)을 구분하는 기준은 무엇인지, 그리고 비용이 어떻게 누적되는지와 같은 메커니즘은 Skills vs. Rules in Claude Code의 주제입니다. 이 글의 구조적 질문에 대해서는 다음의 발견만으로 충분합니다: paths: 스코핑 (scoping)이 27개의 파일이 27배의 비용을 의미하지 않는 주요 이유입니다.
솔직한 단점
이 정도 규모의 규칙 시스템은 공짜가 아니며, 이를 숨기는 경험 보고서는 광고에 불과할 것입니다.
유지보수는 실제 작업입니다. 모든 규칙 파일은 컨벤션 (convention)이 변경될 때마다 주의를 기울여야 하며, 인벤토리 (inventories) 역시 동일한 커밋 내에서 업데이트되어야 하고, 규칙이 이동하면 파일 간의 상호 참조 (cross-references)가 오래되어 쓸모없게 됩니다. 이 노력은 일회성 투자가 아니라 지속적인 비용입니다. 이 프로젝트에서 이는 보상을 받는 종류의 작업이지만, 당신이 이를 승인한다고 해서 작업이 사라지는 것은 아닙니다.
규칙들은 결국 충돌하게 됩니다. 27개의 파일이 있으면 두 규칙이 서로 다른 관점에서 동일한 사례를 규정하는 일이 발생합니다. 예를 들어, 대화 규칙 (dialog rule)은 아이콘을 원하지만, 확인 대화 규칙 (confirmation-dialog rule)은 특수한 경우를 위해 아이콘을 금지합니다. 해결 방법은 매번 동일합니다: 충돌 내용을 명시적인 예외 사항 (carve-out)으로 양쪽 파일 모두에 작성하고, 서로를 참조하게 만드는 것입니다. 결정되지 않은 충돌은 규칙 시스템에 발생할 수 있는 최악의 상황입니다. 왜냐하면 우선순위 (prioritization)가 모호한 상태로 남게 되어, 어떤 규칙이 우선하는지가 특정 컨텍스트 (context)와 당면한 작업에 따라 달라지기 때문입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기