Context Engineering
핵심 아이디어
"agent 입장에서 context window에 없는 건 존재하지 않는 것과 같다"
AC test, ADR, Skill이 있어도 agent가 읽지 않으면 없는 것과 같다. Context Engineering은 올바른 정보를 올바른 타이밍에 context에 넣는 방법을 다룬다.
세 가지 문제
| 문제 | 현상 | |---|---| | 너무 많이 넣음 | Context rot — 긴 context에서 모델이 앞부분을 사실상 잊음, 성능 저하 | | 너무 적게 넣음 | 필요한 정보 부재 → 잘못된 판단 | | 잘못된 걸 넣음 | 관련 없는 정보가 노이즈 → 판단이 흐려짐 |
핵심 전략
1. 정적 context
매 세션 항상 주입되는 것. 가볍게 유지해야 한다.
OpenAI가 AGENTS.md를 ~100줄로 제한하고 나머지는 docs/로 포인터만 둔 이유:
- AGENTS.md 전체를 context에 넣으면 무거워짐
- "더 깊은 정보는 docs/adr/0003.md 참고" 식으로 포인터만 유지
2. 동적 context
작업에 따라 그때그때 필요한 것만 가져온다.
인증 모듈 작업 중 → ADR-0003만 읽어라
DB 레이어 작업 중 → ADR-0001, ADR-0002 읽어라
3. 계층화된 요약
오래된 정보는 압축해서 보관. claude-progress.txt가 이 역할.
전체 git log를 다 읽는 게 아니라 요약된 progress 파일을 읽는다.
4. Sub-agent 분리
context가 무거운 작업은 별도 sub-agent에게 위임. → parent agent의 context를 깨끗하게 유지. → sub-agent는 자기 작업 범위의 context만 갖고 "스마트 존" 유지.
Harness 레이어별 context 설계
Goal layer feature_list.json 항상 읽음, 짧게 유지 (JSON)
Knowledge layer ADR + skill 필요한 것만 동적으로 읽음
State layer claude-progress.txt 전체 log 대신 요약
Environment layer init.sh 세션 시작 시 한 번 읽음
각 레이어 파일을 "얼마나, 언제, 어떻게 읽게 할 것인가"가 Context Engineering의 실체.
AGENTS.md 설계 원칙
# AGENTS.md (좋은 예 — 포인터 구조)
## 아키텍처
레이어 구조: docs/architecture.md 참고
## 주요 결정
DB 선택: docs/adr/0001-why-sqlite.md
인증 방식: docs/adr/0003-auth-strategy.md
## 규칙
- tests/test_architecture.py 항상 통과시킬 것
- 새 라이브러리 추가 시 ADR 작성 후 진행
AGENTS.md 자체는 짧게. 깊은 내용은 다른 파일에.
Context Engineering과 다른 개념의 관계
- AC test가 있어도 → agent가
tests/test_architecture.py존재를 모르면 실행 안 함 - ADR이 있어도 → agent가 읽을 타이밍을 모르면 의미 없음
- Skill이 있어도 → context window에 안 들어오면 따르지 않음
→ Context Engineering이 나머지 모든 것의 기반 레이어
관련 개념
- harness-layer-structure — 레이어 전체 구조
- architectural-constraints — AC test를 agent가 언제 실행하게 할 것인가
- context-history-documentation — ADR을 context에 효율적으로 넣는 방법
- initializer-coding-agent-pattern — claude-progress.txt의 요약 역할
1. 정적 vs 동적 context — 언제 뭔 넣을지
정적 context
매 세션이 시작될 때 항상 context에 들어오는 정보. agent가 요청하지 않아도 자동으로 주입된다.
예: AGENTS.md, init.sh, feature_list.json
핵심 원칙: 가볍게 유지. 정적 context는 모든 세션의 context를 "기본 점유"한다. 크면 클수록 실제 작업에 쓸 수 있는 공간이 줄어든다. → OpenAI가 AGENTS.md를 ~100줄로 제한한 이유.
동적 context
agent가 필요한 순간에 직접 가져오는 정보. 자동 주입이 아니라 agent가 판단해서 읽는다.
예: ADR 파일들, 특정 모듈 코드, progress.txt 특정 섹션
인증 작업 중 → ADR-0003만 읽음
DB 작업 중 → ADR-0001만 읽음
→ 필요한 시점에만 context에 들어온다.
설계 기준
정적에 넣어야 하는 것:
- 모든 세션에서 항상 필요한 것 (아키텍처 개요, 핵심 규칙)
- 짧게 쓸 수 있는 것
- "이게 없으면 agent가 방향을 못 잡는다"
동적에 넣어야 하는 것:
- 특정 작업에만 필요한 것 (특정 ADR, 특정 모듈)
- 길고 상세한 것
- 작업에 따라 달라지는 것
넣으면 안 되는 것:
- 현재 작업과 관련 없는 ADR
- 완료된 feature의 상세 내용
- 오래된 git log 전체
실제 구현 — AGENTS.md에 명시
## 작업 시작 시 읽을 것
1. feature_list.json — 다음 작업 선택
2. claude-progress.txt — 현재 상태 파악
## 필요할 때만 읽을 것
- DB 관련 작업: docs/adr/0001-why-sqlite.md
- 인증 관련 작업: docs/adr/0003-auth-strategy.md
- 새 모듈 추가: docs/architecture.md
## 읽지 말 것
- 완료된 feature의 테스트 코드
- 전체 git log (최근 20개만)
agent에게 "이건 이때 읽어라"를 명시적으로 알려준다. 알아서 판단하게 하면 과적재가 생길 수 있다.
RAG 방식과 Context Engineering의 관계
문제 구분
| 방식 | 푸는 문제 | 적합한 상황 | |---|---|---| | Long-context (현재 Harness) | 코드베이스 탐색, 구조적 파악 | 명확한 파일 위치, 작은 규모 | | Vector RAG | 유사 청크 검색 | 문서가 많고 정해진 패턴 | | GraphRAG | 엔티티 관계 추론, multi-hop | 복잡한 관계망, 도메인 지식 | | LightRAG | GraphRAG의 경량화 | 소형 모델, 제한된 하드웨어 | | AgenticRAG | 자율적 검색·평가·재시도 | 복잡한 다단계 질의 |
Minimum Viable Context — 미래 방향
현재: 인간이 "이때 이걸 읽어라"를 수동으로 AGENTS.md에 명시 → agent가 지시 따라 읽음
RAG 통합 시: agent가 상황 판단 → RAG가 자동으로 관련 정보 검색 → 필요한 것만 context 주입 → 동적 context 설계 자체가 자동화
현재 한계
잘 작동하는 영역: 문서 중심 시스템 (법률, 의료, 기술 문서) 아직 실험적인 영역: 코드베이스 + ADR + 아키텍처를 통합한 "개발 지식 그래프"
코드는 자연어보다 관계가 엄밀해서 GraphRAG의 엔티티 자동 추출 품질 문제가 더 심각하게 나타남. → OpenAI, Anthropic이 여전히 "파일을 직접 읽어라" 방식을 쓰는 이유.
Mugyeon 프로젝트와의 연결
Mugyeon (PDF → Markdown → Obsidian → RAG)은 문서 중심 시스템이라 LightRAG가 적합. 코드베이스 context engineering에 RAG를 통합하는 건 별도 문제. 두 영역이 나중에 합쳐질 가능성은 있으나 현재는 분리해서 접근하는 것이 현실적.
2. Context rot — 왜 길면 성능이 떨어지는가
Lost in the Middle 현상
Context window 안에서 위치에 따라 주의도가 다르다:
[앞부분] ← 주의 높음
[중간부분] ← 주의 낮음 (정보를 잘 놓침)
[뒷부분] ← 주의 높음
중요한 정보가 중간에 있으면 agent가 사실상 그걸 "못 본" 상태로 작업한다.
코딩 agent에서 나타나는 방식
초반: "레이어 의존성 지켜야 한다" 인식 → 잘 지킴
중반: 작업 누적, context 증가
후반: AGENTS.md 규칙이 "희석됨"
→ 편의상 레이어 무시하는 코드 작성 시작
agent가 의도적으로 규칙을 어기는 게 아니다. context가 길어지면서 앞에 있던 정보의 영향력이 약해지는 것. Anthropic: "compaction이 있어도 충분하지 않다"
해결 전략
Compaction (요약 압축) context가 일정 길이를 넘으면 오래된 부분을 자동 요약·압축. 한계: 요약 과정에서 세부사항 손실 가능.
세션 분리
장기 작업을 여러 세션으로 쪼개고, 세션 간에는 claude-progress.txt로 핵심만 전달.
긴 context 하나 > 짧은 context 여러 개. 후자가 더 신뢰할 수 있다.
핵심 규칙은 매 세션 앞부분에 AGENTS.md를 매 세션 시작 시 항상 주입. "앞부분 주의 높음" 특성을 의도적으로 활용.
구조화된 형식 사용 자연어보다 JSON, 코드가 context rot에 더 강하다. → feature list를 Markdown 대신 JSON으로 쓰는 이유 중 하나.
핵심 교훈
context window를 가능한 한 짧고 신선하게 유지하는 것이 긴 context를 잘 처리하는 것보다 낫다.
→ "정적 context는 가볍게, 동적 context는 필요할 때만"의 근거.
3. AGENTS.md 포인터 구조
핵심 원칙
AGENTS.md는 지도(map)다. 지식은 다른 파일에 있다.
AGENTS.md는 매 세션 정적으로 주입된다. 무거우면 context rot 직결. → "어디를 봐야 하는가"만 남기고 나머지는 전부 다른 파일로 뺀다.
나쁜 설계 vs 좋은 설계
# 나쁜 설계 — 모든 걸 AGENTS.md에
## 아키텍처
우리 시스템은 Types → Config → Repo → ...
각 레이어는... (500줄 계속)
# 좋은 설계 — 포인터만 (~100줄)
## 시작 시 읽을 것
1. feature_list.json
2. claude-progress.txt
## 규칙
- tests/test_architecture.py 항상 통과시킬 것
- 새 라이브러리 추가 → docs/adr/ 에 ADR 먼저 작성
## 작업별 참고 문서
- 인증: docs/adr/0003-auth-strategy.md
- DB: docs/adr/0001-why-sqlite.md
## 모르는 게 있으면
docs/ 디렉토리를 먼저 탐색할 것
전체 문서 계층 구조
프로젝트/
├── AGENTS.md ← 지도 (100줄 이하)
├── docs/
│ ├── architecture.md ← 전체 구조 (첫 세션만)
│ ├── adr/ ← 결정의 "왜" (동적, 필요할 때만)
│ └── conventions.md ← 네이밍, 코드 스타일
├── feature_list.json ← 목표 (항상)
├── claude-progress.txt ← 히스토리 (항상)
└── init.sh ← 환경 (항상)
두 가지 참고 패턴
항상 읽는 것 (정적):
## 시작 시 필수
- feature_list.json — 다음 작업 결정
- claude-progress.txt — 현재 상태 파악
조건부로 읽는 것 (동적):
## 작업별 참고
- 인증 관련 수정 시: docs/adr/0003-auth-strategy.md
- 새 테이블 추가 시: docs/adr/0001-why-sqlite.md
- 모듈 경계 변경 시: docs/architecture.md
agent가 현재 작업을 보고 스스로 판단해서 읽는다. AGENTS.md는 그 판단의 기준만 제공.
한 줄 원칙
AGENTS.md에서 삭제할 수 있는 건 전부 삭제하고 다른 파일로 빼라. 남기는 건 "어디를 봐야 하는가"뿐이다.
4. Sub-agent로 context 분리
핵심 원리
Parent agent는 sub-agent에게 작업을 위임하고 결과만 받는다. 중간 과정 (tool call, 탐색, 실패·재시도)은 sub-agent context 안에서만 일어난다.
Parent agent context:
[현재 작업 흐름]
"리서치 필요 → sub-agent 위임"
[결과 요약만 수신] ← 수백 줄이 한 줄로 압축됨
[계속 진행]
Sub-agent context (별도):
[리서치 쿼리]
[웹 검색 × 10]
[결과 정리]
[요약 반환] ← 이것만 parent에 전달
Sub-agent로 보내기 좋은 작업
리서치 → 수십 번의 검색이 parent context에 쌓이지 않음
테스트 생성 → 테스트 코드 전체가 parent context에 안 들어옴
코드 분석 → 파일 수십 개 읽는 과정이 parent에 안 보임
Sub-agent로 보내면 안 되는 작업
핵심 설계 결정 → parent가 직접 해야 맥락 유지
레이어 간 연결 → sub-agent가 전체 구조를 모름
ADR 작성 → 인간이 검토해야 하는 결정
전체 구조
인간
└→ Parent agent (context: 작업 흐름 + 핵심 규칙)
├→ Sub-agent A: 리서치 (context: 검색만)
├→ Sub-agent B: 테스트 (context: 테스트만)
└→ Sub-agent C: 분석 (context: 분석만)
각 sub-agent는 자기 범위의 context만 갖고 "스마트 존" 유지. Parent는 항상 가볍게 유지.
Git worktree와의 연결
Sub-agent들이 병렬로 작업할 때 같은 repo를 동시에 체크아웃:
git worktree add ../work-auth feature-auth # Sub-agent A
git worktree add ../work-db feature-db # Sub-agent B (동시에)
worktree 없이는 branch switching이 직렬 → 병렬 작업 불가.