규칙을 늘려도 무거워지지 않게, CLAUDE.md · skill · perspectives로 분리한 3계층 구조 제안
요약
AI에게 지켜줬으면 하는 규칙(CLAUDE.md)을 관리할 때 발생하는 '지식 폭발' 문제를 해결하기 위해 3계층 구조를 제안합니다. 이 시스템은 기본 규칙, 상황별 결정 로직, 그리고 상황별 관점 파일로 분리하여 확장성과 효율성을 높였습니다.
핵심 포인트
- 규칙이 늘어날수록 모든 내용이 읽히는 '지식 폭발' 문제 해결.
- 시스템을 3계층(CLAUDE.md, skill, perspectives)으로 재구성하여 관리 용이성 확보.
- 관점(perspectives)은 상황별 질문 하나만 담아 추가 비용을 최소화함.
- 지능은 하나의 시스템이 아닌, 독립적인 부품들의 집합체에서 발생한다는 원리를 적용함.
AI에게 코드를 작성하게 할 때, 지켜줬으면 하는 것을 CLAUDE.md에 적어 나간다.
처음에는 50줄이면 충분했다. 지켜줬으면 하는 것이 늘어날 때마다 추가하다 보니 500줄을 넘어섰다.
게다가 그 500줄은 SQL을 실행할 때도, 블로그를 쓸 때도 매번 통째로 읽히고 있다.
이 글은 그것을 어떻게 재구성했는지에 대한 이야기입니다. 시스템을 만든 단계까지는 공유했지만, 운영하면서 무엇이 좋아졌는지는 아직 나오지 않았습니다. 아이디어와 설계를 공유하고, 결과는 앞으로 쓰겠습니다.
시스템은 3계층으로만 구성되어 있습니다.
CLAUDE.md: 상황에 관계없이 항상 적용되는 규칙과 작업 → 태그 대응표
skill: 언제, 무엇을 읽을지 결정하는 부분
perspectives: 상황별 관점. 1 파일 = 1가지 질문. 태그로 출현 시기를 선언함
아래 계층부터 순서대로 설명하겠습니다.
지식의 폭발과 적용 타이밍
곤란했던 점이 두 가지 있었습니다.
지식의 폭발: 쓸수록 늘어난다. 늘어난 만큼 전부, 항상 읽힌다
적용 타이밍: 필요한 상황에서 작동하지 않고, 관계없는 상황에서 읽힌다
이 두 가지는 같은 곳에서 기인합니다. 지식 자체가 '언제 사용할지'를 가지고 있지 않기 때문에, 전부 항상 들고 다닐 수밖에 없습니다.
들고 다니는 것이 늘어나면 이렇게 됩니다.
- 읽을 양이 늘어난다. 길수록 중간 부분이 작동하지 않는다.
- 추가하는 것을 망설인다. '또 길어지겠지'라고 생각하면 쓰지 않게 된다.
- 지우는 것도 망설여진다. 어디서 작동하고 있는지 알 수 없다.
지식을 늘리고 싶은데, 늘릴수록 작동하지 않게 된다. 추가/미추가 판단을 매번 해야 하는 것이 가장 괴로운 부분이었습니다.
민스키의 '마음의 사회'
답을 찾다가 떠올린 것이 마빈 민스키의 『마음의 사회』입니다.
마빈 민스키 『마음의 사회』 안사이 유이치로 역, 산업도서, 1990년
(원서: The Society of Mind, Simon & Schuster, 1986)
제1장에 '마음의 에이전트', '에이전트와 에이전시'라는 절이 있습니다. 대략적으로 말하자면 다음과 같은 주장입니다.
| 용어 | 내용 |
|---|---|
| 에이전트 | 단순하고, 그 자체로는 아무것도 이해하지 못하는 작은 부품 |
| 에이전시 | 에이전트의 집합체. 외부에서 보면 1가지 능력처럼 보인다 |
지능은 하나의 똑똑한 시스템이 아니라, 똑똑하지 않은 부품들의 집합체로부터 발생한다.
여기서 해석하면 아까의 두 가지 어려움에 실마리가 보입니다.
에이전트는 늘어나도 좋다. 단 동시에 작동하는 것은 일부만
어떤 것이 작동할지는, 그 상황이 결정한다
늘어나도 전부가 동시에 작동하지 않는다면, 늘려도 괜찮다. 이것이 원했던 것이었습니다.
에이전트로서의 관점
사용하는 것은 Markdown의 frontmatter와 10여 줄의 python만입니다. 새로운 도구나 라이브러리는 넣지 않았습니다.
그 위에서 규칙을 '관점(perspectives)'이라는 단위로 나눴습니다. 1 관점 = 1 파일입니다.
관점은 한 가지 일만 봅니다. 그 자체로는 아무것도 판단하지 않고, '〜하고 있는가'라는 질문을 하나 가질 뿐입니다.
remove-all-comments: 코드의 주석을 전부 제거하고 있는가
throw-on-impossible-state: 있을 수 없는 상황을 무시하지 않고 throw 하고 있는가
known-to-unknown: 작성과 이야기 순서가 알려진 것에서 미지의 것으로 변했는가
파일의 내용은 다음과 같습니다.
---
name: throw-on-impossible-state
applies_to: [implement, review]
...
그냥 Markdown입니다. 특별한 것은 아무것도 없습니다.
1 파일로 만들어 두면, 추가하는 비용이 거의 제로가 됩니다. 파일을 하나 놓기만 하면, 지울 때도 하나만 지우면 됩니다. '또 길어지겠지'라고 생각할 필요가 없다는 것이 큽니다.
applies_to를 통한 상황 선언
핵심은 frontmatter의 applies_to입니다.
applies_to: [implement, review]
그 관점이 '나는 어떤 상황을 담당하는가'를 선언합니다. 지식 쪽이 타이밍을 갖는 것이 이 설계의 중심입니다.
값은 계층 구조로 되어 있어서, review는 review/<리포지토리명>의 부모가 됩니다.
implement 코드를 작성하거나 수정하기
review 리뷰하기
review/myapp myapp을 리뷰하기
...
review
을 선언한 관점(perspective)은 review/myapp의 리뷰에서도 모입니다. 특정 리포지토리에만 적용하고 싶은 관점은 자식 값(child value)을 선언합니다.
반대로 '이 리포지토리에는 적용하고 싶지 않다'는 경우도 있습니다. 실제로, 어떤 명명 규칙을 가진 관점이 저희 코드베이스의 절반에 해당했습니다. 읽어보니 일탈이라기보다는 다른 규약이었고, 그쪽은 그쪽으로 일관성이 있었습니다. 이 때는 관점의 applies_to에서 대상을 제외하고, 제외한 이유를 관점에 기록해 두었습니다.
규칙을 지키게 하는 메커니즘이 아니라, 규칙을 키워나가는 메커니즘이 되었다는 것이 사용하면서 가장 기쁜 점입니다.
에이전시(Agency)로서의 skill
관점을 모아서 적용하는 것은 apply-perspectives라는 단 하나의 skill만 합니다.
이 skill은 관점을 하나도 가지고 있지 않습니다. 가지고 있는 것은 '언제, 무엇을 읽을지'뿐입니다. 민스키(Minsky)가 말한 에이전시(Agency)에 해당합니다.
예전에는 반대로, skill 안에 절차와 판단 기준이 뒤섞여 있었습니다. '작동 확인 절차'의 skill에 '실 데이터로 확인할 것'이라는 관점이 박혀 있어서, 다른 작업에서는 사용할 수 없었습니다. 판단 기준을 모두 perspectives로 빼내고, skill은 호출하는 역할만 하도록 바꾼 것이 이번 변경입니다.
모으는 처리(処理)는 이것뿐입니다.
import re, pathlib
t = 'review/myapp'
for f in sorted(pathlib.Path.home().joinpath('.claude/perspectives').glob('*.md')):
...
작업과 값의 대응표만 CLAUDE.md에 놓습니다. 항상 읽히는 것은 이 표와, 상황을 가리지 않고 적용되는 규칙뿐이 되었습니다.
코드 작성/수정 implement
리뷰하기 review / review/<리포지토리명>
SQL 실행/안내 sql
...
리뷰를 요청했을 때의 동작
'리뷰해 줘'라고 하면, 이렇게 동작합니다.
1. 작업에서 값을 결정함 review/<리포지토리명>
2. 그 값을 선언하고 있는 관점들을 모음
3. 변경 파일 종류로 필터링 frontmatter의 trigger (glob)
...
3의 trigger는 코드 리뷰용 관점만이 가지고 있는 또 다른 태그입니다.
trigger: "**/*.{ts,tsx,py,sql}"
문서만 변경된 차이점에 TypeScript 명명 규칙의 관점을 적용해도 의미가 없습니다. 변경 파일이 glob에 일치했을 때만 적용합니다.
4는 생략을 금지합니다. 모은 관점 수만큼 줄을 내기 때문에, '봤는데 해당 없음'과 '애초에 안 봤음'을 구분할 수 있습니다.
remove-all-comments 해당 없음
throw-on-impossible-state 해당 있음 — src/foo.ts:20
continue로 막아버린 발생 불가능한 분기
...
관점을 하나 늘리면, 다음 리뷰부터 자동으로 적용됩니다. 파일을 하나만 놓으면, 어디에도 등록하지 않아도 됩니다. 이것이 '늘려서 좋아졌다'의 실체입니다.
앞으로의 운영
수치로 말하면, 항상 읽히는 부분은 500줄에서 330줄로 줄었고, 상황별 관점은 95개になりました. 총량은 4.5배 늘었지만, 한 번 작업할 때 읽는 것은 그중 2~3개입니다. 늘려도 읽는 양이 늘지 않는, 목표대로의 형태가 되었습니다.
다만, 운영을 시작한 지 얼마 안 돼서, 이것으로 좋아졌다고 아직 말할 수는 없습니다. 솔직히 이 부분이 그렇습니다.
강제하는 장치(仕掛け)를 넣지 않았습니다. 대응표를 읽고 스스로 호출하는 형태이므로, 건너뛸 수 있습니다. -
관점을 95개나 바로 꺼낼 수 있었던 것은, 1년 치 쌓아둔 것이 있었기 때문입니다. 제로(0)에서 이 숫자는 나오지 않습니다. -
관점이 계속 늘어났을 때 정말 파탄 나지 않을지는, 앞으로 알게 될 것입니다.
결과는 운영하면서 작성해 나가겠습니다.
이 설계의 핵심은 지식에 '언제 사용할지'를 부여한 것뿐입니다. 메커니즘 자체는 Markdown과 10여 줄의 스크립트로만 이루어져 있습니다. 같은 어려움을 겪고 있는 분들은 관점을 하나의 파일부터 시도해 볼 수 있을 것입니다.
같은 어려움을 겪는 사람이 얼마나 되는지 알고 싶으니, 이 방향이 좋아 보인다면 '좋아요'를 눌러주시면 감사하겠습니다. 반응이 있다면 운영하면서 알게 된 내용도 계속 작성하겠습니다.
Discussion

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