Episode 02 - Context Engineering
이 글에서 다루는 것
지난 편에서는 '시작하기 전에 결정을 끝내는 법'을 봤어요. 그런데 결정을 아무리 잘 내려놔도, 에이전트가 그걸 까먹거나 헷갈려 하면 사실 다 소용없죠. 한 번쯤 겪어보셨을 거예요 — 분명히 정해준 규칙을 몇 번 주고받다 보면 슬그머니 잊어버리는 그 느낌이요.
에이전트가 한 번에 보고 기억하는 공간을 컨텍스트(context) 라고 불러요. 이 컨텍스트엔 약점이 두 개 있는데요. 하나는 생각보다 좁다는 거예요. 게다가 많이 채운다고 똑똑해지는 게 아니라, 오히려 중요한 걸 놓치기 시작하죠. 다른 하나는 세션이 끝나면 통째로 사라진다는 거고요. 다음 세션은 아무것도 기억 못 하는 빈 상태로 다시 시작하거든요.
그래서 컨텍스트는 그냥 두면 안 되고, 좀 설계를 해줘야 해요. 이 글에선 그 두 약점을 다루는 네 가지를 정리해봤어요 — 좁은 공간을 가볍게 유지하는 세 가지(덜어내기·떼어내기·그때그때 끌어오기)랑, 사라지는 기억을 넘겨주는 한 가지(기억하기)요.
핵심 메시지
많이 넣으면 왠지 더 똑똑해질 것 같은데, 사실은 반대예요. 컨텍스트는 채운다고 좋아지는 게 아니거든요. 관련 없는 게 끼면 에이전트의 주의가 흐려져서, 방금 정한 것도 놓치고 엉뚱한 데를 보죠. 그래서 우리가 할 일은 채우기가 아니라 오히려 덜어내기예요.
크게 네 가지로 정리돼요.
- 덜어내기 — 단계 넘어갈 때 핵심만 압축해서 넘기기
- 떼어내기 — 시끄러운 작업은 따로 맡기고 요약만 받기
- 그때그때 — 미리 다 넣지 말고, 필요할 때 가져오기
- 기억하기 — 세션을 넘겨야 할 건 파일에 적어두기
오늘 볼 패턴들은 전부, 이 좁은 공간을 쓸데없는 걸로 채우기 전에 핵심만 남기는 도구들인 셈이에요.
컨텍스트: 가볍게 유지 vs 꽉 채움
1. Intentional Compaction - 단계마다 핵심만 압축
길어진 대화가 주의를 흐린다
에이전트랑 길게 일하다 보면 대화가 수십 단계로 쌓이잖아요. 리서치하고, 계획하고, 구현하고… 그 모든 기록이 컨텍스트에 그대로 남거든요. 그런데 컨텍스트가 길어질수록 에이전트는 중간에 있는 정보를 슬슬 놓치기 시작해요. 앞에서 분명히 정해둔 중요한 제약이, 뒤로 갈수록 묻혀버리는 거죠.
단계마다 핵심만 압축해서 넘기기
Intentional Compaction은 단계를 넘어갈 때마다 꼭 필요한 것만 추려서 다음 단계로 넘기는 방식이에요. 리서치가 끝나면 그 과정의 수다는 다 버리고 결론만 계획 단계로, 계획이 끝나면 또 그 결론만 구현 단계로 넘기는 거죠.
[리서치 → 계획] 으로 넘기는 것:
- 결론 3줄
- 건드릴 파일 5개
- 지켜야 할 제약 2개
(탐색 과정의 로그·시행착오는 버림)
이렇게 하면 매 단계가 깨끗한 상태에서 출발하니까, 에이전트가 덜 흐트러져요. 전 이게 짧은 작업보단 단계가 여럿이고 길게 이어지는 작업일수록 진가가 난다고 봐요. 짧게 끝나는 일엔 사실 압축할 것도 별로 없거든요.
리서치 → 계획 → 구현, 단계마다 핵심만 압축해 넘김
그리고 대화가 너무 길어지기 전에, 에이전트한테 스스로 핵심만 남기고 정리(compact) 하게 시키는 것도 같은 결이에요. 직접 추려 넘기든, 에이전트한테 줄이게 시키든 — 목표는 하나죠. 좁은 공간을 깨끗하게 유지하기.
Claude Code에선 /compact 한 줄이면 돼요.
그냥 /compact만 쳐도 대화를 핵심만 남기고 줄여줘요.
❯ /compact
무엇을 남길지 콕 집고 싶으면 뒤에 포커스를 붙이면 돼요. 그러면 그 기준으로만 추려주고요.
❯ /compact 결정과 바뀐 파일만 남겨
단계를 넘길 때(리서치 끝 → 계획 시작) 한 번 쳐주면, 다음 단계가 깨끗한 상태에서 출발해요. 컨텍스트가 꽉 차오르면 Claude가 알아서 compact를 제안하기도 하고요.
작업이 아예 딴 걸로 바뀔 땐, 압축보다 /clear로 통째로 비우는 게 나아요(→ 아래 Context Reset Hygiene).
❯ /clear
단, 비우기 전에 남길 규칙은 파일로 넘겨두세요(→ 4번 Persistent Memory). 안 그러면 그 대화에 있던 게 같이 날아가거든요.
2. Subagent Isolation - 시끄러운 일은 따로 맡기기
검색·로그가 메인을 가득 채운다
코드베이스를 한 번 검색하면 수백 줄이 우르르 나오고, 테스트를 돌리면 로그가 쏟아지죠. 그런데 정작 우리한테 필요한 건 "아, 그 파일에 있구나" 같은 결론 한두 줄이잖아요. 그 수백 줄이 메인 대화에 그대로 쌓이면, 중요한 맥락을 밀어내고 주의를 흐려놓거든요.
시끄러운 일은 따로 맡기고 요약만 받기
Subagent Isolation은 검색·테스트처럼 출력이 많은 일을 별도의 서브에이전트(하위 에이전트)한테 맡기는 거예요. 그 친구가 수백 줄을 다 들여다보고, 메인한테는 정리된 요약만 돌려주죠. 시끄러운 작업은 따로 격리해서 처리하고, 메인은 결론만 받는 셈이에요.
메인은 요약만 받고, 시끄러운 작업은 서브에이전트가 처리
수백 줄짜리 로그가 메인에 안 쌓이니까, 메인 대화는 핵심만 남아서 가벼워져요. 다만 출력이 짧은 일까지 굳이 떼어내면 오히려 오가는 게 번거롭죠. 출력이 많고, 그 과정이 메인엔 필요 없을 때 쓰는 게 좋습니다.
Claude Code에선 서브에이전트를 파일 하나로 정의해요. .claude/agents/researcher.md를 만들고:
---
name: researcher
description: 코드베이스를 검색해 요약만 돌려준다. 출력 많은 탐색에 위임.
tools: Read, Grep, Glob
model: haiku
---
너는 코드 리서처다. 요청 주제를 조사하고 핵심 요약만 돌려줘.
그럼 메인 대화에서 이름만 부르면 그 친구한테 일이 넘어가요.
❯ researcher로 결제 로직이 어디 있는지 조사해줘
(이름을 안 불러도 description만 보고 Claude가 알아서 위임하기도 해요.)
검색으로 나온 수백 줄은 그 서브에이전트 자기 컨텍스트 안에서 처리되고, 메인 대화엔 이런 요약만 돌아와요 — 메인은 그 수백 줄을 아예 안 봐요:
결제 로직은 src/payment/ 아래에 있어요.
- 환불 처리: refund.ts:42
- 결제 검증: verify.ts:88
tools로 권한을 좁히고 model: haiku처럼 싼 모델을 붙이면 비용도 아껴요. 서브에이전트를 만들고 관리하는 건 /agents로 하고요.
3. Just-in-Time - 필요할 때 그때그때
미리 다 넣으면, 대부분은 안 쓴다
"혹시 필요할까 봐" 관련 문서랑 코드를 미리 컨텍스트에 다 욱여넣는 경우가 많아요. 그런데 솔직히 그중 대부분은 이번 작업이랑 상관없거든요. 안 쓰는 정보가 자리만 차지하면서, 또 주의를 흐려놓죠.
필요할 때 가져오게 하기
Just-in-Time은 미리 채우는 대신, 에이전트가 필요한 순간에 직접 가져오게 하는 방식이에요. 파일 읽는 도구, 검색하는 도구를 쥐여주면, 그때그때 지금 작업에 관련된 것만 끌어오거든요.
미리 다 넣기 vs 그때그때 끌어오기
미리 넣기랑 그때그때 — 둘 다 같은 정보를 쓰긴 하는데, 그때그때 쪽은 관련된 것만, 필요한 만큼만 컨텍스트에 들어와요. 그럼 늘 그때그때가 정답이냐 하면, 그건 또 아니에요. 매번 똑같이 필요한 핵심 정보(프로젝트 규칙 같은 거)는 그냥 미리 넣어두는 게 낫죠. 그때그때는 가끔, 그때만 필요한 것에 쓰는 거예요.
Claude Code에선 기본이 이미 그때그때예요. 도구(Read·Grep·Glob)를 미리 싣지 않고, 에이전트가 필요할 때만 부르거든요.
특정 파일을 지금 보고 싶으면 @경로로 그 순간 끌어와요. 예를 들어 대화창에 이렇게 치면 —
❯ @src/payment/checkout.ts 이 환불 흐름 좀 봐줘
그 파일 하나만 그 순간 컨텍스트에 올라오죠. 결제 폴더 전체를 미리 열어둘 필요가 없어요.
가끔만 쓰는 절차·지식은 Skill로 빼둡니다. .claude/skills/<이름>/SKILL.md에 적어두면 부를 때만 로드되고, 안 부르면 토큰을 0으로 차지해요. 외부 데이터는 MCP 서버로 그때그때 가져오고요.
규칙도 그때그때로 — .claude/rules/
프로젝트가 커지면 규칙도 많아져요. API 규칙, 테스트 규칙, 보안 규칙… 이걸 전부 CLAUDE.md 하나에 몰아넣으면, 지금 API만 만지는 중인데도 테스트·보안 규칙까지 매 세션 따라다니며 자리를 먹죠.
이럴 땐 규칙을 .claude/rules/ 폴더에 주제별로 나눠 둬요. 폴더는 이런 모양이 돼요:
your-project/
├── .claude/
│ ├── CLAUDE.md # 항상 로드되는 전역 지침
│ └── rules/
│ ├── api.md # API 규칙
│ ├── testing.md # 테스트 규칙
│ └── security.md # 보안 규칙
└── src/ ...
그리고 각 규칙 파일 맨 위에 paths:로 적용 범위를 정해요. api.md라면 이렇게요:
# .claude/rules/api.md
---
paths:
- "src/api/**/*.ts"
---
- 모든 API 엔드포인트는 입력값 검증 필수
- 표준 에러 응답 형식 사용
- OpenAPI 문서 주석 포함
이렇게 두면 이 규칙은 평소엔 컨텍스트에 안 올라와요. Claude가 src/api/users.ts 같은 파일을 읽는 그 순간에만 불려오죠. 지금 프론트엔드 코드를 만지고 있다면 이 API 규칙은 아예 안 들어오고요 — 상관없는 규칙이 자리를 차지하지 않는 거예요.
정리하면 이렇게 나눠요:
- 매번 필요한 규칙(빌드 명령, 전역 컨벤션)은 →
CLAUDE.md에. 항상 로드. - 특정 영역에서만 필요한 규칙은 →
.claude/rules/에paths:로 묶어서. 그 영역을 만질 때만 로드.
(paths:를 안 붙이면 그 규칙 파일도 CLAUDE.md처럼 매 세션 항상 로드돼요. 경로 패턴은 src/**/*.ts, *.md, src/components/*.tsx처럼 glob으로 자유롭게 쓸 수 있고요.)
4. Persistent Memory - 세션을 넘겨 기억하기
세션이 끝나면 다 사라진다
에이전트는 세션이 끝나는 순간 컨텍스트가 통째로 날아가요. 다음에 다시 부르면, 우리 프로젝트 규칙도 지난번에 합의한 것도 하나도 기억 못 하죠. 그래서 매번 같은 걸 또 설명하게 되고요. 솔직히 좀 답답하죠.
남길 건 파일에 적어두기
Persistent Memory는 세션을 넘겨야 할 것 — 프로젝트 규칙, 반복되는 결정, 한 번 데인 교훈 같은 거 — 을 파일에 적어두는 거예요. 보통 CLAUDE.md 같은 파일에요. 그러면 매 세션이 시작할 때 그 파일을 먼저 읽고, 같은 규칙 위에서 일을 시작하거든요.
# CLAUDE.md
- 결제 콜백은 비동기 → 응답 전 DB 커밋 금지
- 날짜는 항상 UTC로 저장
- 새 API는 Zod 스키마부터
지난 편의 spec.md도 사실 같은 원리예요. 한 번 끄집어낸 결정을, 사라지지 않게 밖에 적어두는 거죠. 다만 이번 한 번만 쓰고 말 일회성 정보까지 다 쌓으면 그 파일이 금세 지저분해져요. 반복해서 필요한 것만 남기는 게 포인트입니다.
Claude Code에선 /init 한 번이면 프로젝트를 훑어 CLAUDE.md 초안을 만들어줘요.
❯ /init
이게 프로젝트 메모리예요 — git으로 팀과 공유되죠. 규칙을 두는 위치가 몇 군데 있어요:
./CLAUDE.md— 프로젝트 규칙 (팀과 공유)~/.claude/CLAUDE.md— 나만 쓰는 전역 규칙 (모든 프로젝트에 적용)- 하위 폴더의
CLAUDE.md— 그 폴더에서만 통하는 규칙 (가까운 게 더 우선)
편집은 /memory로 하면 되고요.
여기까진 내가 미리 적어두는 방식이에요. 그런데 작업하다 알게 된 걸 그때그때 기억시킬 수도 있어요.
❯ 앞으로 npm 말고 pnpm 써. 기억해둬
❯ 방금 정한 환불 정책, 새 세션에서도 쓰게 기억해둬
이렇게 말하면 Claude가 그걸 스스로 관리하는 메모(auto memory)에 저장해, 다음 세션이 그대로 이어받아요. 규칙을 미리 다 적어두지 못했어도, 대화 중 나온 중요한 건 이렇게 넘겨두면 새 세션에서 안 날아가죠.
세션을 넘겨 기억하기
함께 보면 좋은 패턴
위 네 가지 곁에, 한 발 더 들어가면 만나는 패턴들이에요. 대표만큼 깊게는 안 가고, 각각 뭘 하는지·대표 중 무엇과 짝인지만 짚고 갈게요.
Context Reset Hygiene : 꼬인 대화는 고치지 말고, 비우고 새로 시작
작업이 바뀌었거나 대화가 한참 꼬였을 때, 그걸 어떻게든 되돌리려 애쓰는 대신 /clear로 컨텍스트를 통째로 비우고 지금 필요한 것(시드)만 다시 넣어 출발하는 방식이에요. 망가진 대화를 계속 끌고 가면 그 잡음이 끝까지 따라오는데, 깨끗하게 리셋하는 게 대개 더 빠르거든요.
1번(Intentional Compaction)과 목표는 같고, 방법이 달라요. Compaction이 단계마다 핵심만 추려서 넘긴다면, Reset은 통째로 비우고 처음부터예요 — 점진적 압축 vs 한 번에 리셋. 대화가 길어 흐려졌으면 압축, 아예 꼬였으면 리셋.
Raw vs Distilled Context : 요약만 보되, 원본으로 되짚는 링크를 달기
서브에이전트한테 일을 떼어 맡기고 요약만 받으면 가볍긴 한데, 그 요약이 사실을 빠뜨리거나 슬쩍 왜곡할 위험이 있죠. 이 패턴은 원본(로그·문서·녹취)은 그대로 두고 정제본(결정·위험·사실)만 보되, 정제본의 각 항목에 원본으로 되짚는 링크를 달아둬요. 그러면 요약을 믿고 쓰다가도 미심쩍을 때 원본을 바로 확인할 수 있죠.
2번(Subagent Isolation)의 안전장치예요. Isolation이 시끄러운 일을 떼어 요약만 받는다면, Raw vs Distilled는 그 요약이 사실을 잃지 않게 출처를 같이 매어두는 짝이에요. 가볍게 쓰되, 근거는 잃지 않게.
AST-Aware Code Search : grep 말고 코드 구조(심볼) 단위로 가져오기
JIT로 그때그때 코드를 끌어올 때, 무엇을 도구로 가져오느냐가 정확도를 갈라요. 단순 문자열 검색(grep)은 이름만 비슷한 엉뚱한 곳까지 긁어오지만, 코드 구조(AST)·심볼 단위로 검색하는 도구는 "이 함수가 실제로 불리는 곳" 같은 의미 단위로 모아주죠. 에이전트한테 어떤 검색 도구를 쥐여주느냐가 곧 맥락의 질이 되는 거예요.
3번(Just-in-Time)의 정확도를 끌어올리는 짝. JIT가 언제 가져오냐(필요할 때)라면, AST-Aware는 어떻게 잘 가져오냐(의미 단위로)예요. 그때그때 끌어오되, 엉뚱한 걸 끌어오지 않게.
Structured Handoff : 세션을 끝낼 때, 다음 세션에 인계서를 넘기기
한 세션이 끝나면 컨텍스트가 통째로 사라지죠. Structured Handoff는 끝내기 전에 지금까지의 진행 상태(무엇을 했고, 어디까지 됐고, 다음은 무엇인지)를 압축 문서로 적어 다음 세션이 그대로 이어받게 해요. 사람 교대근무의 인수인계서와 같은 거죠.
4번(Persistent Memory)과 비슷해 보이지만, 담는 게 달라요. CLAUDE.md(Memory)는 항상 맞는 규칙을 영구로 두고 매 세션 읽히는 거라면, Handoff는 이 작업의 진행 상태를 한 번 넘기고 역할이 끝나는 일회성 바통이에요. 영구 규칙 vs 작업 인계.
이 편의 나머지 패턴
이외에도 컨텍스트 엔지니어링으로 묶이는 패턴은 많은 것들이 있더군요. 전부 열여덟 개쯤 되는데, 위에서 깊게 본 네 가지와 방금 본 보조 넷을 빼면 나머지는 열 개. 이름과 한 줄로 훑고 갈게요.
| 패턴 | 한 줄 |
|---|---|
| Self-Improving Memory Promotion | 반복해 나오는 패턴을 임시 메모에 적었다가, 사람이 승인하면 정식 규칙으로 승격 |
| Progressive Disclosure (Skills) | 가끔만 쓰는 지식은 SKILL.md로 떼어, 필요한 순간에만 불러 읽기 |
| Context Up-Front (PRP) | 예시 코드 + 초기 설명으로 맥락을 미리 빵빵하게 채워 한 번에 생성→실행 |
| Codebase Bundling (Brownfield) | 기존 코드베이스 전체를 한 덩어리로 묶어 통째로 맥락에 넣고 그 위에서 작업 |
| Standards-Injection Layer | 코드베이스에서 뽑은 팀 표준을 상황에 맞춰 그때그때 맥락에 끼워 넣기 |
| External Progress File | 진행 상태를 progress 파일 + git으로 컨텍스트 바깥에 저장해, 세션이 끊겨도 안 잃기 |
| Prime-Command Context Boot | 세션을 열 때마다 슬래시 커맨드(/prime)로 맥락을 시작부터 떠먹이기 |
| Hierarchical Instruction Composition | 경로별 지시 파일을 현재 폴더에 가까울수록 우선해 겹쳐 합치기 (모노레포) |
| Conditional Rule Activation | 규칙을 파일 경로(glob)·키워드에 묶어, 해당 상황일 때만 자동으로 켜기 |
| Caveman Token-Compression | 군더더기를 다 빼고 핵심만 남긴 압축 말투로 토큰을 크게 절약 |
마무리 - 이것 만큼은 기억하기
여러분도 좀 느꼈나요? 핵심은 한 줄이에요 — 컨텍스트는 채운다고 좋아지지 않는다! 가볍게 유지하고, 남길 건 밖에 적어두는 거죠.
네 가지는 결국 두 가지 문제를 푸는 거예요. 컨텍스트가 좁다는 것(덜어내기·떼어내기·그때그때)이랑, 세션이 끝나면 사라진다는 것(기억하기)이요.
| 할 일 | 패턴 | 한 줄 |
|---|---|---|
| 덜어내기 | Intentional Compaction | 단계마다 핵심만 압축해 넘기기 |
| 떼어내기 | Subagent Isolation | 시끄러운 일은 맡기고 요약만 받기 |
| 그때그때 | Just-in-Time | 미리 말고 필요할 때 가져오기 |
| 기억하기 | Persistent Memory | 세션 넘길 건 파일에 적어두기 |
다음 편 — 오케스트레이션과 병렬. 지금까진 에이전트 하나랑 잘 일하는 법이었어요. 다음은 여럿을 동시에 굴리고, 알아서 돌아가게 만드는 법을 다뤄볼게요.
참고 영상
