AI 코딩 에이전트를 위한 2계층 문서화 패턴
요약
AI 코딩 에이전트의 성능을 극대화하기 위한 2계층 문서화 패턴을 제안합니다. 매 세션 로드되는 짧은 CLAUDE.md와 상세 정보를 담은 agent_docs/ 폴더를 분리하여 컨텍스트 효율성을 높이는 방법을 다룹니다.
핵심 포인트
- CLAUDE.md는 300라인 미만으로 짧게 유지하여 지침 예산 확보
- 상세 내용은 agent_docs/에 저장하고 라우팅 테이블로 안내
- 라우팅 테이블은 요약이 아닌 작업(task) 설명 형식으로 작성
- 문서 간의 명시적인 관계 설정 및 주기적인 감사 필요
요약 (TL;DR)
CLAUDE.md를 짧게 유지하세요 (약 300라인 미만). 이 파일은 모든 세션에 자동으로 로드되며, 제한된 지침 예산(instruction budget) 내에서 시스템 프롬프트(system prompt)와 경쟁하기 때문입니다.- 상세한 내용은
agent_docs/에 넣고,CLAUDE.md에 잘 작성된 테이블을 통해 해당 경로로 안내하세요. - 라우팅 테이블(routing-table) 트리거를 작성할 때는 내용 요약이 아니라, 작업(task) 설명(누군가 업무를 할당할 때 할 법한 말) 형식으로 작성하세요.
- 다중 문서 간의 관계를 명시적으로 만드세요 ("참조" 행, "공통 다중 문서 작업" 섹션 등).
- 라우팅 테이블을 감사(audit)하고 유지 관리하세요. 오래된 트리거는 향후 모든 세션의 성능을 저하시킵니다.
- 아래 사례 연구의 증거: 잘 작성된 문서는 결함이 있는 코드가 배포되는 것을 방지할 수 있는 두 가지 기능적 결함을 막아냈습니다.
서론
새로운 팀원이 첫날부터 바로 작동하는 코드를 배포하는 경우는 드뭅니다. 그들은 문서를 읽고, 질문을 하고, 컨벤션(conventions)을 배우며, 이 특정 코드베이스가 작동하는 방식을 점진적으로 내재화합니다. 하지만 AI 코딩 에이전트에게는 이러한 준비 기간(ramp-up)이 없습니다. 매 세션마다 에이전트는 눈앞에 있는 것 외에는 프로젝트에 대해 아무것도 모르는 상태로 새로 시작합니다.
이 글은 바로 그 간극에 대해 다룹니다. 우리의 경험에 따르면, AI 에이전트를 위해 할 수 있는 가장 영향력 있는 일 중 하나는 인간에게 제공하는 것과 동일한 종류의 온보딩(onboarding) 문서를 제공하되, 에이전트가 적절한 시점에 적절한 부분을 읽을 수 있도록 구조화하는 것입니다.
실질적으로 이는 두 계층을 의미합니다: 저장소 루트(repository root)에 있는 짧은 CLAUDE.md 파일(매 세션마다 읽음)과, 작업이 요구할 때만 에이전트가 가져오는 참조 문서(reference docs) 폴더입니다. 이 글의 나머지 부분에서는 이 패턴, 이를 작성하며 배운 교훈, 그리고 동일한 작업에 대해 문서가 있는 에이전트와 없는 에이전트가 각각 무엇을 만들어냈는지 비교하는 사례 연구를 살펴봅니다.
이 페이지의 내용:
- 문서화 접근 방식 (The documentation approach): 에이전트에게 적절한 시점에 적절한 컨텍스트 (Context)를 제공하는 2계층 모델 (
CLAUDE.md+agent_docs/)과 효과적인 라우팅 테이블 (Routing table) 작성을 위한 베스트 프랙티스. - 증거 (Evidence): 동일한 작업에 대해 에이전트 문서가 있는 경우와 없는 경우를 비교한 사례 연구로, 코드 품질, 아키텍처의 정확성, 기능적 완성도에서 나타나는 구체적인 차이를 보여줍니다.
이 내용은 VS Code 및 AI 코딩 어시스턴트에 대한 기본적인 이해가 있다는 것을 전제로 하지만, Claude Code에 대해 구체적으로 알고 있을 필요는 없습니다. Claude Code가 처음이신가요? 빠른 오리엔테이션을 위해 부록 A를 참조하세요. 아래의 모든 내용은 Claude Code가 설치되어 있다고 가정합니다. 이 패턴들은 모든 코드베이스에 일반화될 수 있습니다. 마지막에 나오는 사례 연구는 추상화된 예시를 사용하므로 여러분의 프로젝트에 쉽게 적용할 수 있습니다.
컨텍스트 관리 (Context management)가 중요한 이유
Claude가 프로젝트를 처음 접할 때, 컨텍스트 (Context)는 전혀 없는 상태입니다. 즉, 아키텍처, 명명 규칙 (Naming conventions), 또는 주의해야 할 함정들을 알지 못합니다. 가이드가 없다면, Claude는 컨텍스트 윈도우 (Context window)의 상당 부분을 탐색하는 데 소비하게 되며, 빠르게 컨텍스트 부패 (Context rot) 상태에 직면할 수 있습니다. 이는 작업 기억 (Working memory)이 너무 포화되어 에이전트가 환각 (Confabulating, 흔히 말하는 "hallucinating"의 기술적 용어)을 일으키기 시작하는 지점을 의미합니다.
이는 "중간에서 길을 잃는 (Lost in the Middle)" 현상과 밀접한 관련이 있습니다. Liu et al. (2023)의 연구에 따르면 다음과 같습니다:
"성능은 관련 정보가 입력 컨텍스트의 시작 부분이나 끝 부분에 나타날 때 가장 높은 경우가 많으며, 모델이 긴 컨텍스트의 중간에서 관련 정보에 접근해야 할 때 성능이 현저히 저하됩니다."
이는 직접적인 실무적 함의를 갖습니다. 모든 문서를 한꺼번에 에이전트의 컨텍스트에 쏟아붓는 것은 단순히 컨텍스트 예산 (Context budget)을 낭비하는 것뿐만 아니라, 모델이 방대한 컨텍스트의 중간에서 올바른 정보를 검색하는 데 어려움을 겪기 때문에 성능을 능동적으로 저하시킵니다.
가이드 원칙: 점진적 공개 (Progressive disclosure)
해결책은 점진적 공개(Progressive disclosure)입니다. 에이전트에게 모든 정보를 한 번에 주는 것이 아니라, 적절한 시점에 필요한 정확한 정보를 제공하는 것입니다. 아래 설명된 패턴(가벼운 CLAUDE.md 파일과 agent_docs/ 폴더)은 HumanLayer의 좋은 CLAUDE.md 작성 관련 블로그 게시물에서 영감을 받았습니다. 실제로 점진적 공개란 다음을 의미합니다:
- 항상 로드되는(Always loaded): 에이전트에게 방향을 제시하고 더 깊은 정보를 어디서 찾을 수 있는지 알려주는 가벼운
CLAUDE.md파일. - 요청 시 로드되는(Loaded on-demand): 에이전트가 작업을 수행하는 데 필요할 때만 읽는 상세 참조 문서.
- 상호 참조되는(Cross-referenced): 문서를 관련 문서에 연결하여, 에이전트가 필요할 때 인접한 지식을 끌어올 수 있도록 하는 것.
이것이 다음 섹션에서 설명하는 2계층 문서화 모델의 기반입니다.
명령어 예산(Instruction budget)
여기에 정량적인 차원도 있습니다. Jaroslawicz et al. (2025)의 연구에 따르면, 최첨단 사고 모델은 약 150~200개의 명령어를 안정적으로 따를 수 있으며, 명령어 수가 증가함에 따라 준수율이 감소합니다. 특히 두 가지 발견이 관련성이 높습니다:
- 균일한 저하(Uniform degradation): 명령어 수가 증가함에 따라, 최신 명령어뿐만 아니라 모든 명령어에서 준수율이 균일하게 떨어집니다. 가치가 낮은 명령어를 추가하면 가치가 높은 명령어의 신뢰성도 떨어지게 만듭니다.
- 주변부 편향(Peripheral bias): LLM은 프롬프트의 아주 시작 부분과 아주 끝 부분에 있는 명령어에 더 강하게 주의를 기울이는 경향이 있으며, 이는 위에서 언급된 '중간에서 길을 잃음(lost in the middle)' 발견과 일치합니다.
Claude Code 자체 시스템 프롬프트만으로도 사용자 콘텐츠가 추가되기 전에 이미 상당한 비율의 이 예산을 소모합니다. (정확한 개수는 논문이 Claude Code를 구체적으로 측정하기보다는 이산적인 벤치마크 명령어를 계산했기 때문에 직접 비교할 수는 없습니다.) 하지만 방향성은 여전히 유효합니다: 사용자의 CLAUDE.md는 나머지 부분을 놓고 경쟁하며, 추가하는 모든 줄은 다른 모든 줄의 준수율을 떨어뜨립니다.
실질적인 길이 가이드라인: 커뮤니티의 합의된 의견은 CLAUDE.md를 300행 이내로 유지하는 것입니다. HumanLayer의 자체 루트 CLAUDE.md는 60행 미만입니다. 모든 작업에 보편적으로 적용 가능한 지침만 포함하세요. 작업별 세부 사항은 agent_docs/에 있어야 합니다.
이 모든 것이 중요한 이유는 CLAUDE.md가 잠재적인 오류 연쇄 (error cascade)의 최상단에 위치하기 때문입니다:
CLAUDE.md → 조사 (research) → 계획 (plan) → 코드 (code)
결함이 있는 코드 한 줄은 단지 하나의 잘못된 줄일 뿐입니다. 계획의 결함이 있는 한 줄은 많은 잘못된 코드 줄을 만들어냅니다. 하지만 CLAUDE.md의 결함이 있는 한 줄은 모든 세션의 모든 단계와 생성되는 모든 결과물 (artifact)에 영향을 미칩니다. 이로 인해 CLAUDE.md는 에이전트 추론 (agentic reasoning) 및 솔루션을 적용할 때 프로젝트 전체에서 가장 레버리지가 높은 파일 중 하나가 됩니다. 따라서 많은 편집적 주의를 기울일 가치가 있습니다.
CLAUDE.md: 정의 및 사용 방법
Claude가 CLAUDE.md 파일을 사용하는 방식
CLAUDE.md는 자동 로드됩니다. 프로젝트 디렉토리에서 Claude Code 세션이 시작될 때마다, 사용자의 프롬프트가 처리되기 전 CLAUDE.md가 대화 컨텍스트 (conversation context)에 자동으로 주입됩니다.
주의해야 할 몇 가지 사항:
-
agent_docs는 자동 로드되지 않습니다. 오직CLAUDE.md만 자동 로드됩니다.agent_docs/에 있는 파일들은 필요할 때 (on-demand) 읽히며, 이것이 라우팅 테이블 (routing-table) 설명이 중요한 이유입니다. -
라우팅 테이블이 핵심 메커니즘입니다.
CLAUDE.md에 있는 테이블은 작업 의도 (task intent)를 문서와 매핑합니다:
| 문서 | 읽어야 할 때 |
|---|---|
| architecture.md | 프로젝트 구조를 이해할 때... |
| writing_tests.md | 명명 규칙 (naming conventions), AAA 구조... |
Claude가 작업을 받으면, 작업의 의도를 "읽어야 할 때" 열과 대조하여 행동하기 전에 관련 문서(들)를 읽습니다.
품질 체인 (quality chain):
명확한 라우팅 설명 → Claude가 올바른 문서를 선택 → 문서가 패턴/규칙을 제공 → Claude가 일관된 코드를 생성.
이는 모든 새로운 문서가 자체적인 내용과 함께, 서술적인 "읽어야 할 때(When to read)" 트리거가 포함된 라우팅 테이블(routing table)의 업데이트된 행(row)을 모두 필요로 함을 의미합니다.
2계층 문서화 모델 (The two-layer documentation model)
Layer 1: CLAUDE.md (진입점)
이 파일은 에이전트가 매 세션 시작 시 읽기 때문에, 의도적으로 짧고 빠르게 훑어볼 수 있어야 합니다. 여기에는 다음 내용이 포함됩니다:
- 프로젝트 개요: 프로젝트의 방향을 설명하는 한 단락의 오리엔테이션.
- 빠른 명령 (Quick commands): 복사하여 바로 붙여넣을 수 있는 빌드/테스트 명령.
- 문서 로딩 지침 (A doc-loading directive): 작업(task)과 일치하는 트리거를 가진 모든 문서를 읽으라고 에이전트에게 지시하는 한 줄의 명령 (아래의 '부드러운 권유가 아닌 강력한 지침 사용하기' 참조).
- 라우팅 테이블 (A routing table): 작업 유형을 관련
agent_docs파일에 매핑하는 테이블. - "공통 다중 문서 작업" 섹션: 빈번하게 조합되는 문서 관계를 명시적으로 나타내는 선택적 후속 테이블 (아래의 '문서 간의 관계를 명시적으로 만들기' 참조).
부록 B(Appendix B)는 이 모든 요소가 적용된 완전한 작업 예시를 보여줍니다.
Layer 2: agent_docs/ (심층 가이드)
라우팅 테이블이 지시할 때만 에이전트가 읽는 상세 참조 문서입니다. 카테고리별로 구성된 전형적인 구조는 다음과 같습니다:
| 카테고리 | 예시 문서 | 목적 |
|---|---|---|
| 아키텍처 (Architecture) | architecture.md | 프로젝트 구조, 실행 흐름, 전체 데이터 모델 |
| ... |
핵심 통찰은 에이전트가 자신에게 필요한 것만 읽는다는 점입니다. UI 변경 작업을 수행하는 에이전트는 UI 문서를 읽고, 새로운 기능을 추가하는 에이전트는 레시피(recipe) + 컨벤션(conventions) + DI 가이드를 읽습니다. 모든 작업에 대해 모든 문서를 로드하는 것은 컨텍스트 예산(context budget)을 낭비하고 집중력을 분산시킬 것입니다.
복사본보다는 포인터를 선호하십시오. agent_docs를 작성할 때 코드 스니펫(code snippets)을 직접 삽입하는 것은 피하십시오. 코드베이스가 진화함에 따라 해당 스니펫이 오래된 정보(stale)가 될 위험이 높습니다. 대신, 실제 소스 코드를 가리키는 file:line 참조를 사용하십시오 (예: 등록 패턴은 CompositionRoot.cs:45를 참조하십시오). 에이전트는 작업 시점에 참조된 파일을 읽으므로, 항상 최신 코드를 확인할 수 있습니다.
실제 적용 시 모습: 문서화가 갖춰지면, 에이전트는 스스로 규칙을 만들어내는 대신 실제 프로젝트 컨벤션 (Conventions)을 따릅니다. 또한 일반적인 작업에 대한 단계별 레시피 (Recipe)를 파악하고, 알려진 함정(오타가 있는 폴더명, DI 경계 규칙, 비동기 패턴 등)을 피하며, 위험한 변경 후에는 검증 테스트를 실행합니다. 요컨대, 기존 코드베이스의 나머지 부분과 이질감이 없는 코드를 생성합니다.
좋은 라우팅 테이블 (Routing Table) 작성하기
자체적인 라우팅 테이블을 반복적으로 개선하는 과정에서 세 가지 반복되는 문제와, Claude가 올바른 문서를 훨씬 더 안정적으로 선택할 수 있도록 개선한 해결책을 발견했습니다.
부드러운 권유가 아닌 명확한 지시 사항을 사용하세요
기존의 지시 사항은 다음과 같았습니다: "해당 영역을 수정하기 전에 관련 문서를 읽으십시오."
이는 사람에게는 합리적으로 들리지만, 에이전트는 이를 너무 보수적으로 해석했습니다. 작업에 두 개 또는 세 개의 문서가 필요할 때조차 문서 하나도 읽지 않거나 단 하나만 읽었습니다. 해결책은 지시 사항을 명시적으로 만드는 것이었습니다:
"'언제 읽어야 하는가(When to read)' 열이 작업 내용과 일치하는 모든 문서를 읽으십시오. 대부분의 작업은 하나 이상의 문서를 필요로 합니다."
교훈: "관련된 것을 읽으라"와 같은 모호한 가이드는 성능이 좋지 않습니다. "일치하는 모든 것을 읽으라"와 같은 명시적인 지시 사항이 에이전트에게 구체적인 의사 결정 규칙을 제공합니다.
트리거 (Triggers)를 내용 요약이 아닌 작업 설명으로 작성하세요
기존의 트리거는 각 문서에 포함된 내용을 설명했습니다. 예를 들어 "이벤트 버스 구독 라이프사이클 (event bus subscription lifecycle)" 또는 _"이중 저장 시스템 (dual storage system)"_과 같은 구현 중심의 문구였습니다. 하지만 누군가 에이전트에게 _"이벤트를 발행(publish an event)"_하거나 _"레코드를 저장(save a record)"_하라고 요청할 때, 이러한 문구들은 일치하지 않습니다.
실제로 에이전트는 트리거 텍스트가 작업 설명(Task description)에 포함된 단어 및 개념과 얼마나 잘 겹치는지에 따라 문서를 선택합니다. 따라서 트리거는 사람들이 작업을 할당할 때 사용하는 것과 동일한 행동 중심의 어휘 (Action-oriented vocabulary)를 사용할 때 가장 효과적입니다.
문서별로 분류한 약한 트리거와 강한 트리거의 추가 예시는 다음과 같습니다:
| 문서 | 약한 트리거 (Weak trigger) | 강한 트리거 (Strong trigger) | 강한 버전이 효과적인 이유 |
|---|---|---|---|
architecture.md | "프로젝트 구조 이해하기" | "코드베이스 내 위치 파악, 주요 컴포넌트의 위치, 시스템을 통한 데이터 흐름" | 행동 중심적임; 사용자가 실제로 사용할 법한 여러 개의 구별된 구절 포함 |
| ... |
일반적인 어휘 불일치 (vocabulary-mismatch) 패턴:
- 의도 (intent) 대신 구현 명칭 (Implementation names) 사용. "SignalR 연결 생명주기 (SignalR connection lifecycle)"에 의해 트리거되는 문서는 "백엔드 서비스 호출하기"라고 말하는 사용자와 매칭되지 않습니다. 사용자는 보통 어떤 전송 라이브러리 (transport library)가 관여하는지 모르거나(또는 상관하지) 않습니다.
- 사용자 대상 동작 대신 내부 용어 (Internal terminology) 사용. "이중 저장 계층 (dual storage layer)"에 의해 트리거되는 문서는 "레코드 저장하기"와 매칭되지 않습니다. 이슈 트래커 (issue tracker)에 누군가가 입력할 법한 동사를 사용하세요.
- 모호성 해소 없는 중복 트리거 (Overlapping triggers). 만약
writing_tests.md와running_tests.md가 모두 단순히 "test"라는 단어에 트리거된다면, 에이전트는 잘못된 문서를 먼저 읽을 수 있습니다. 식별자(discriminators)를 추가하세요 ("테스트 작성 방법" vs "테스트 스위트 실행 방법").
핵심 요약 (Takeaway): 트리거를 작성할 때는 "이 문서가 무엇을 다루는가?"가 아니라, "누군가가 어떤 작업을 할당할 것인가?"의 관점에서 작성하세요.
문서 간의 관계를 명시적으로 만들기
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기