작은 파일 하나로 시작했습니다
처음 CLAUDE.md 를 만들 때는 단 하나의 원칙만 적혀 있었습니다. "글을 쓸 때 voice를 어떻게 잡을 것인가." 그게 전부였지요.
그런데 시간이 지나면서 이 파일이 점점 무거워졌습니다.
- 정책(글쓰기·에이전트 행동) 도 여기에 적었고
- 규약(커밋·툴링·파일 네이밍) 도 여기에 적었고
- 진행 중인 스펙 메모도 한쪽 구석에 쌓였습니다
어느 순간 어디를 고쳐야 하는가 가 헷갈리기 시작했어요. 사람도 그랬지만, 에이전트(Claude Code) 입장에서도 한 번에 너무 많은 맥락을 들이마셔야 했습니다.
한 파일이 모든 걸 담으면, 그 파일은 결국 누구도 끝까지 읽지 않는 파일이 됩니다.
첫 번째 정리 — 의도별로 쪼개기
해법은 단순했습니다. 의도가 다르면 파일도 다르다.
CLAUDE.md 는 더 이상 본문을 담지 않습니다. 어디에 무엇이 있는지 만 가리키는 인덱스가 되었지요.
정책(policy)과 규약(convention)을 나눈 이유는 따로 있습니다. 같은 규칙 이지만 성격이 다르거든요.
- 정책: 글쓰기 voice, 에이전트 행동 — 정의 의 영역
- 규약: 커밋 메시지, 파일명, 스택 도구 — 강제 의 영역
성격이 다르면 폴더도 다르게 두는 게 옳다고 생각했어요.
분리만으로는 부족했습니다
문서를 잘 나누어도 한 가지 문제는 그대로 남았습니다. 코드를 바꿨을 때 어떤 문서가 거짓이 되는가 는 여전히 사람 머릿속에만 있었어요.
예를 들어, eslint.config.js 에 새 룰을 추가합니다. stack-and-tooling.md 에는 "ESLint + Prettier 조합" 이라고 적혀 있고요. 둘 사이 동기화는요? 까먹지 않고 하면 됩니다.
사람은 까먹습니다. 에이전트도 까먹습니다. 정확히는, 에이전트는 모릅니다. 자기가 방금 수정한 파일과 어느 문서가 관련 있는지를 매번 추론하라고 하면 비싸고 부정확하지요.
매번 추론할 거면, 차라리 데이터로 두는 게 낫습니다.
동기화를 데이터로
그래서 docs/policy/agent-behavior.md 에 "문서 동기화 매핑 표" 를 박았습니다.
| 변경된 파일 패턴 | 확인할 문서 |
|---|---|
package.json, eslint.config.*, pnpm-workspace.yaml, tsconfig*.json | stack-and-tooling.md |
docs/kanban/** | kanban-workflow.md |
CLAUDE.md, docs/policy/**, docs/convention/** | agent-behavior.md + 인덱스 |
비행기 조종사가 외우지 않고 체크리스트를 읽는 것 과 같은 원리입니다. 외우는 건 사람이 약하고, 읽는 건 사람이 잘하니까요. 에이전트도 마찬가지입니다.
이 표 하나로 두 가지가 동시에 해결됐어요.
- 사람이 PR을 만들 때 내가 무엇을 놓치고 있는지 한 번 더 보게 됩니다
- 에이전트가 코드를 바꿀 때 함께 갱신할 문서가 있는지 표를 근거로 사용자에게 묻게 됩니다
문서로 인지의 단일 출처를 만든 셈이에요.
한 단계 더 — Hook으로 강제하기
다만 문서로만 두면 결국 호출 에 의존합니다. 사람이 그 표를 읽어야 하고, 에이전트도 매번 그 표를 떠올려야 하지요. 한쪽이 잠깐 게으르면 동기화는 그날부터 다시 뒤처집니다.
Claude Code의 PostToolUse hook을 하나 걸었습니다. 흐름은 다음과 같습니다.
매핑에 걸리지 않으면 침묵, 걸리면 hookSpecificOutput.additionalContext 로 reminder를 내보냅니다. 이 reminder는 Claude의 다음 turn에 system reminder로 자동 주입 되지요. 즉, 에이전트가 매핑 표를 읽지 않아도 표가 자기를 두드리는 셈입니다.
사람도 잊고, 에이전트도 잊습니다. 그래서 hook이 있습니다.
자동화의 경계
자동화에도 기능 분담 이 있습니다. hook이 하는 일은 알림까지 입니다.
- hook은 동기화하지 않습니다. 알림만 줍니다
- 판단(어디가 거짓이 됐는가) 과 실행(문서를 어떻게 갱신할 것인가) 은 여전히 사람·에이전트의 몫입니다
- 잘못 매핑된 패턴은 노이즈가 되고, 노이즈가 늘면 도구가 신뢰를 잃습니다
그래서 매핑은 최소 로 시작했어요. 자주 누락되는 패턴이 실제로 관찰되면 표를 보강하거나 hook으로 옮기는 방식으로 점진 확장하기로 했습니다. 자동화는 한 번에 다 쥐려고 하면 결국 손에서 빠져나가지요.
Memory가 아닌 이유
Claude Code에는 auto-memory 라는 게 있습니다. 에이전트가 사용자에 대해 학습한 사실을 저장하는 곳이지요. 작업 초반에 자연스럽게 떠오른 질문이 있었습니다.
"그냥 메모리에 저장하면 안 되나요?"
안 됩니다. 정확히는, 공유가 안 됩니다. auto-memory는 사용자 홈 디렉터리에 저장됩니다. git으로 트래킹되지 않고, 다른 머신·다른 협업자와 공유되지도 않아요.
이번 작업의 핵심은 팀(나 자신 + 미래의 나 + 협업자 + 에이전트)이 같은 표를 본다 입니다. 그러려면 자료가 레포 안에 있어야 하고, git으로 관리되어야 해요.
세 가지 layer의 역할 분담이 자연스럽게 정리됐습니다.
- 메모리: 개인의 학습. 공유 불가. 한 사람의 일관성을 위함.
- 문서: 명시적 공유. 사람·에이전트가 같은 텍스트를 읽음.
- Hook: 강제. 호출에 의존하지 않음.
같은 자리에 있을 필요는 없습니다. 다만 공유가 필요한 것 은 메모리에 두지 말고 문서·hook으로 옮겨야 한다는 결론이 나왔어요.
Context Engineering이 뭐냐고 묻는다면
요즘 context engineering 이라는 말이 자주 들립니다. 거창한 이름이지만, 이번 작업의 결론은 단순했어요.
- 원천을 한 곳에 두고
- 인덱스로 묶어 진입점을 만들고
- 같은 표를 사람과 에이전트가 함께 보고
- 깜빡할 수 있는 지점은 hook으로 한 번 더 강제한다
문서 분리는 사람을 위한 일 처럼 보이지만, 인덱스와 hook은 에이전트를 위한 일 이기도 합니다. 두 일을 한 레포 안에서 같이 하면 됩니다.
에이전트와 함께 사는 레포는, 결국 사람도 더 편하게 사는 레포가 됩니다.