
CLAUDE.md가 1년 만에 6,605행이 되었다. 규칙은 설계가 아니라 사고 후에 늘어난다
요약
Claude Code를 1년간 운용하며 CLAUDE.md와 규칙 파일이 6,605행까지 늘어난 실제 경험담을 다룹니다. 규칙의 팽창, 파탄, 분할 과정을 통해 AI 어시스턴트를 위한 규칙 관리의 어려움과 시행착오를 기록했습니다.
핵심 포인트
- 규칙은 설계가 아닌 실제 운용 과정에서 자연스럽게 늘어남
- 규칙이 너무 길어지면 컨텍스트 과부하 및 규칙 간 모순 발생 위험
- 파일별 규칙 자동 주입 기능은 존재하지 않으므로 수동 관리가 필요함
- 팽창과 파탄을 반복하며 규칙을 분할하고 재정리하는 과정이 필수적임
개인 개발 리포지토리에서 Claude Code용 규칙이 6,605행이 되었습니다.
내역은 다음과 같습니다.
| 파일 | 행수 |
|---|---|
CLAUDE.md | |
| 598행 | |
.claude/rules/ (24개 파일) | |
| 6,007행 | |
| 합계 | |
| 6,605행 |
먼저 말씀드리자면, 설계해서 이렇게 된 것이 아닙니다.
1년 전에 쓰기 시작했을 때는 187행이었습니다. 거기서 불어나고, 한 번 파탄 나고, 분할하고, 다시 불어나고 있습니다. CLAUDE.md
단독 커밋 횟수는 97회입니다.
이 기사는 "좋은 CLAUDE.md 작성법"이 아닙니다. 1년 동안 운용하며 알게 된, 늘어나는 법칙과 실패의 기록입니다.
작성자
개인적으로 「스로맵 AI(スロマップAI)」라는 서비스를 운영하고 있습니다. 파칭코·슬롯 점포 데이터를 분석하는 Web 서비스입니다.
| 항목 | 숫자 |
|---|---|
| 개발 기간 | 2025-07-21 ~ (1년) |
| ... |
Claude Code는 어시스턴트라기보다, 운용의 토대로서 사용하고 있습니다. 이 6,605행은 그 토대입니다.
1년의 추이: 불어나고, 깨지고, 나누다
먼저 실제 행수의 변화를 봐주세요. CLAUDE.md
단독 추이입니다.
| 시기 | 행수 | 무슨 일이 있었나 |
|---|---|---|
| 2025-07-21 | 187행 | 프로젝트 첫날 작성 |
| ... | .claude/rules/로 분할 | |
| 2026-05-20 | 830행 | 다시 불어남 |
| 현재 | 598행 | 재정리 |
예쁜 우상향 곡선이 아닙니다. 팽창 → 파탄 → 분할 → 재팽창 → 재정리를 반복하고 있습니다.
흥미로운 점은, 첫날부터 존재했다는 것입니다. 코드를 쓰기 시작한 날의 커밋에 이미 187행의 CLAUDE.md가 들어있습니다. 빈 프로젝트에 대해 규칙을 187행이나 쓴 것이라, 당연히 이 시점에는 아무것도 모르고 있었습니다.
그리고 예상대로, 그 187행의 대부분은 지금 남아있지 않습니다.
왜 1,700행에서 파탄 났는가
이유는 단순합니다. 너무 길면 읽히지 않기 때문입니다.
이것은 인간의 이야기가 아니라 AI의 이야기입니다. 1,800행의 규칙을 매 세션마다 전부 쌓으면, 그만큼의 컨텍스트 (Context)가 처음부터 채워집니다. 게다가 프론트엔드 CSS를 수정하고 있을 때 DB 규칙을 쌓아봤자 아무런 도움이 되지 않습니다.
또 하나 심각했던 것은 모순을 알아차릴 수 없게 된다는 점입니다. 1,800행이나 있으면, 3개월 전에 쓴 규칙과 오늘 쓴 규칙이 충돌하고 있어도 작성자 본인이 알아차리지 못합니다. AI는 양쪽을 모두 읽고 둘 중 하나를 선택합니다. 어느 쪽을 선택했는지는 우리 쪽에서 보이지 않습니다.
그래서 2025년 12월 14일, 분할했습니다.
.claude/rules/
├── common/ # 전체 (언어·워크플로·환경·툴)
├── frontend/ # 디자인 시스템, 컴포넌트, 퍼포먼스
...
CLAUDE.md는 183행까지 떨어졌습니다. 본체에는 "반드시 지킬 것"만 두고, 상세 내용은 각 파일로 넘기는 형태입니다.
분할할 때 기대했던 메커니즘은 존재하지 않았다
이 부분이 솔직하게 쓰고 싶은 대목입니다.
분할 커밋에 당시의 목적을 이렇게 적어두었습니다.
파일별 컨텍스트 자동 적용 (*.tsx 시 frontend/, API 시 backend/)
.tsx를 편집하면 frontend/의 규칙이 자동으로 읽힌다——그렇게 생각해서 분할했습니다.
그런 기능은 없습니다.
지금 설정을 확인해보니, .claude/settings.json에는 권한 설정밖에 들어있지 않습니다. 훅 (Hook)도 하나뿐인데, 이것은 배포 비용을 검사하는 별도의 용도입니다. 파일 종류에 따라 규칙을 자동으로 주입하는 메커니즘은 어디에도 구현되어 있지 않았습니다.
즉 8개월 동안 저는 존재하지 않는 기능을 전제로 디렉토리를 나누고 있었던 셈입니다.
그렇다면 분할은 헛수고였을까요? 헛수고는 아니었습니다. 다만 효과가 있었던 이유는 기대했던 것과는 달랐습니다.
실제로 효과를 보고 있는 것은 이것입니다. CLAUDE.md의 서두에 디렉토리 트리와 "무엇이 어디에 적혀 있는지"를 명시해 둔 것.
📋 상세 규칙 참조처
중요: 상세한 구현 규칙·실패 사례·디자인 시스템은
.claude/rules/로 분할되어 있습니다:
...
이것이 있으면, DB를 다루는 작업 시 AI가 database.md를 직접 읽으러 갑니다. 자동 주입이 아니라, 필요할 때 가져오게 하는 방식입니다.
결과적으로 "매번 전부 쌓아두기"에서 "필요할 때만 읽기"로 바뀌었습니다. 목적은 달성했지만, 메커니즘은 자동 적용이 아니라 목차였습니다.
만약 같은 일을 하려 한다면, 디렉토리를 나누는 것 자체보다 본체에 목차를 쓰는 것을 우선하세요. 효과를 보고 있는 것은 그쪽입니다.
규칙은 사고 후에야 쓸 수 있다
6,605행의 내용 중 가장 많이 사용되는 것은 과거에 밟았던 지뢰의 목록입니다.
CLAUDE.md에는 배포 사고 목록이 11건 있으며, "증상 / 근본 원인 / 대책"의 3열로 구성되어 있습니다. 증상으로부터 원인을 찾는 색인입니다.
발췌하면 다음과 같은 형태입니다.
| 사고 | 증상 | 근본 원인 |
|---|---|---|
| Edge cache 굽기 (burn) | 배포 후 CSS 깨짐 · chunks 404 | Purge 누락으로 오래된 HTML이 오래된 chunk를 참조 |
| ... | ... | ... |
이 표를 보고 깨달은 점이 있습니다. 어떤 행도 미리 쓸 수는 없었습니다.
"Cloudflare Workers에는 MessagePort가 없으므로 polyfill을 넣읍시다" —— 이것은 직접 겪기 전에는 쓸 수 없습니다. 문서에도 나와 있지 않습니다. 실제로 운영 환경에서 일부 페이지에서만 500 에러를 반환하고, 심지어 Workers의 Analytics에는 에러로 나타나지 않으며 (5xx 응답은 정상 종료로 취급됨), wrangler tail로 생로그를 보고 나서야 겨우 ReferenceError: MessagePort is not defined를 발견하고 나서야 비로소 쓸 수 있습니다.
즉, CLAUDE.md는 설계물이 아니라 퇴적물입니다.
이것은 글을 쓰기 시작하는 사람에게는 희소식이라고 생각합니다. 처음부터 좋은 것을 쓰려고 애쓰지 않아도 됩니다. 187행이면 충분합니다. 사고가 나면 1행을 추가합니다. 그것을 1년 동안 지속하면 6,605행이 됩니다.
가장 효과적이었던 방식은 "조작 실수가 아닙니다"였다
사고 목록을 1년 동안 작성해 오면서, 분명히 효과가 달랐던 작성 방식이 하나 있었습니다.
지난달에 이런 사고가 있었습니다. 릴리스할 때마다 develop 브랜치가 사라집니다. 3번 발생했습니다.
보통이라면 "develop를 삭제하지 않도록 주의"라고 적습니다. 하지만 그렇게 적어도, 다음에 사고가 났을 때 "누군가 조작을 실수했겠지"라고 생각하며 원인을 찾는 데 시간을 쓰게 됩니다.
실제로 적은 내용은 이것입니다.
리포지토리 설정
delete_branch_on_merge=true
(머지 시 head를 자동 삭제). feature 브랜치에는 유용하지만 Git Flow에서는 릴리스 PR의 head가 되기 때문에, 릴리스할 때마다 삭제됨. develop 조작 실수가 아니라 설정대로의 동작.
마지막 문장이 효과적입니다. "이것은 올바르게 작동한 결과이다"라고 명시해 두었기 때문에, 다음에 사고가 났을 때 범인 찾기를 시작하지 않습니다.
같은 형태의 기술이 다른 곳에도 있습니다. "Workers Analytics에는 나타나지 않음", "npm run dev에서는 발견되지 않음" —— 어디를 찾아봐도 찾을 수 없다고 미리 선언해 두는 것. 탐색의 헛수고를 없애는 것이 규칙의 주요 업무였습니다.
써야 할 것은 "이렇게 해라"보다 **"이렇게 보이지만, 원인은 이것이다"**입니다.
문장으로 된 규칙은 지켜지지 않는다. 효과를 본 것은 중단시킨 3가지뿐
1년 동안 해보며 가장 명확해진 점은 이것입니다.
문장으로 쓴 규칙은 잊혀집니다. 6,605행이 있어도 AI가 매번 전부를 지키는 것은 아니며, 사람(나)도 지키지 않습니다. 특히 급할 때는 지켜지지 않습니다.
그래서 중간부터 중요한 것은 문장을 버리고 실행을 중단시키는 형태로 옮겼습니다. 3가지가 있습니다.
① git push를 중단시키는 훅 (hook)
.claude/hooks/check-deploy-cost.sh (60행)를 PreToolUse에 심어 두었습니다. Claude Code가 git push를 실행하려는 순간 개입하여, main으로의 직접 push라면 차단합니다.
# git push 명령 이외에는 무시
if ! echo "$COMMAND" | grep -qE '^git\s+push'; then
exit 0
...
이유는 비용 때문입니다. 운영 환경(Production)에 반영할 때마다 Edge 캐시가 전부 퍼지(Purge)되고 재빌드(Rebuild)가 실행됩니다. 1회 배포당 비용을 실측해 본 적이 있는데, 횟수를 제한하는 것 자체가 하나의 대책이었습니다. "main에 직접 push하지 마세요"라고 적어두는 것보다, push를 못 하게 만드는 것이 더 확실합니다.
② 브랜치 보호 (최신화 필수)
오래된 브랜치를 기점으로 PR(Pull Request)을 생성하여, 타인의 PR을 소리 없이 되돌려버리는 사고가 있었습니다. UI가 몇 주 전 상태로 돌아가 있었지만 아무도 눈치채지 못했습니다.
대책으로서 main에 "PR 필수 + 머지(Merge) 전 최신화 필수"를 설정했습니다. 규칙 문서에는 다음과 같이 적혀 있습니다.
기계적으로 차단
③ 장기 생존 브랜치의 삭제 금지
방금 언급한 develop 브랜치가 삭제되는 건입니다. 원인이 "설정대로의 동작"이기 때문에 주의하는 것만으로는 해결되지 않습니다. allow_deletions=false를 추가하여 삭제할 수 없도록 만들었습니다.
이 세 가지의 공통점은 규칙을 문장에서 설정(Setting)으로 내려보냈다는 것입니다.
6,605행을 써오면서 이런 말을 하기도 좀 그렇지만, 정말로 지키게 하고 싶은 것은 문장으로 써서는 안 됩니다. 문장은 "알아두었으면 하는 것"을 위한 용도입니다. "절대로 하게 하고 싶지 않은 것"은 훅(Hook), 브랜치 보호, CI(지속적 통합)로 옮기십시오.
역으로 말하면, 문장에 남아 있는 규칙은 전부 "깨질 가능성이 있는" 것들입니다. 그렇게 생각하고 읽으면 우선순위를 정하기 쉬워집니다.
CLAUDE.md 자체가 사고를 일으킨다
의외였던 점이 이것입니다.
이 리포지토리는 두 개의 브랜치를 병행하여 운영하고 있는데(운영용과 개발용), 양쪽에서 같은 파일을 편집하면 머지 충돌(Merge Conflict)이 발생합니다. 그 상습범으로 CLAUDE.md가 지목되었습니다.
게다가 대처법까지 적혀 있습니다.
CLAUDE.md 충돌은 양쪽의 내용을 모두 남긴다 (한쪽을 버리지 않는다)
규칙 파일은 어떤 브랜치에서 작업하더라도 추가(Append)됩니다. 그래서 다른 어떤 파일보다 충돌하기 쉽습니다. 그리고 충돌을 해결할 때 한쪽을 버리면, 그 브랜치에서 배운 교훈이 사라집니다.
규칙을 한곳에 모으면 그곳이 구조적인 충돌 지점이 됩니다. 이것은 파일을 분할해도 해결되지 않았습니다 (본체인 CLAUDE.md에 추가 작업이 집중되기 때문). 현재로서는 "양쪽 모두 남긴다" 이상의 해답은 없습니다.
그리고, 부패한다
마지막으로 가장 꼴사나운 이야기를 하겠습니다.
현재 CLAUDE.md에는 다음과 같은 섹션이 있습니다.
## 📊 현황 지표 (2025년 12월)
월간 트래픽: 32,700 세션 / 83,631 PV / 26,927 UU
현재는 월 40만 PV입니다. 이 숫자는 8개월 전의 것이며, 4.8배나 차이가 납니다.
사고 기록 표는 업데이트됩니다. 밟을 때마다 아프기 때문입니다. 하지만 "현황 지표"와 같이 고통을 수반하지 않는 정보는 아무도 업데이트하지 않습니다. 그리고 오래된 숫자가 남아 있으면 AI는 그것을 현재 값으로 읽습니다. "월 8만 PV 사이트"라는 전제로 판단하게 되는 것입니다.
교훈은 이렇습니다. 변하는 것을 규칙 파일에 적지 마십시오. 수치, 현황, 진척도는 적는 순간부터 부패하기 시작합니다. 적는다면, 취득 방법(명령어나 쿼리)을 적는 것이 수명이 더 깁니다.
참고로 이 글을 쓰기 위해 자신의 규칙을 다시 읽어보다가 처음으로 이 차이를 발견했습니다. 1년을 방치하면 자신이 쓴 것이라도 이렇게 됩니다.
지금 똑같은 일을 시작한다면
1년 치의 후회를 정리하면 다음과 같습니다.
① 처음에는 짧아도 괜찮다
첫날에 187행을 썼지만 대부분 남아 있지 않습니다. 프로젝트를 이해하기 전에 작성한 규칙은 거의 버리게 됩니다. 빈 상태라도 좋으니 만들어 두고, 사고가 날 때마다 추가하는 것이 더 빠릅니다.
② 사고가 나면 그날 안에 한 줄 추가하라
다음 날이면 "왜 그렇게 되었는지"를 잊어버립니다. 특히 "어디를 찾아봐도 발견할 수 없었다"라는 정보는 해결하는 순간 가치가 사라지므로, 그 자리에서 적지 않으면 두 번 다시 적을 수 없습니다.
③ "이렇게 해라"보다 "이렇게 보이지만 원인은 이것이다"
지시보다 진단을 적으십시오. 규칙의 주요 업무는 탐색의 헛수고를 없애는 것이었습니다.
④ 정말로 막고 싶은 것은 문장에 적지 마라
훅, 브랜치 보호, CI로 내려보내십시오. 문장은 깨지기 마련입니다.
⑤ 1,000행을 넘으면 분할하라. 단, 본체에 목차를 작성하라
효과를 발휘하는 것은 디렉토리 구조가 아니라, 본체로부터의 참조입니다.
⑥ 변하는 숫자를 쓰지 마라
부패합니다. 쓴다면 취득 방법을 쓰십시오.
배운 점
CLAUDE.md는 설계물이 아니라 퇴적물이다.
처음에 좋은 것을 쓰려고 하면 손이 멈춥니다. 실제로 가치가 있는 것은 밟았던 지뢰의 기록뿐이었습니다. 그것은 사전에 쓸 수 없습니다.
문장의 규칙은 지켜질 것을 전제로 작성해서는 안 된다.
지키게 하고 싶은 것은 설정 (Setting)으로 내려보냅니다. 문장에 남아 있는 것은 '알아두었으면 하는 것'이지, '절대로 지켜져야 하는 것'이 아닙니다. 이 구분을 하면 어느 쪽에 노력을 기울여야 할지가 명확해집니다.
규칙도 부패한다.
게다가 고통이 따르지 않는 부분부터 부패합니다. 사고 기록은 업데이트되지만, 현상 설명은 방치됩니다. 변하는 것은 쓰지 않는 것이 유일한 대책이었습니다.
작성자
개인 개발로 Web 서비스를 만들어 운영하고 있습니다.
스로맵 AI (Slotmap AI) — 파칭코·슬롯 데이터 분석 서비스
- 회원 8,953명 (그 중 유료 82명) / 월간 40만 PV
- 1년간 5,207 commit · 379,022행 (모두 개인 개발)
- Next.js / Cloudflare Workers + OpenNext / Supabase / Clerk
- 설계부터 운영 · 과금 · 비용 관리까지 혼자서 수행하고 있습니다.
이런 상담을 받고 있습니다
Claude Code를 개발에 도입하고 싶지만, 사내에 지식이 없다
- 개인 개발 ~ 소규모 팀의 Web 서비스를 만들고 싶다
- 클라우드 비용이 높다 / 청구액이 급증한 원인을 조사하고 싶다
- 이미 있는 서비스의 개선 (표시 속도 · SEO · 과금 동선)
스팟 상담 (1시간~)부터 받고 있습니다. 무엇을 할 수 있는지 확인하는 것만으로도 괜찮습니다.
📧 slotdata2020+work@gmail.com
/ GitHub
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기