research

Context Engineering

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이 나머지 모든 것의 기반 레이어

관련 개념

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이 직렬 → 병렬 작업 불가.