3장. 컨텍스트·메모리·상태
학습 목표
- 컨텍스트 rot과 주의 예산을 설명하고, 컨텍스트에 넣을 정보를 고르는 기준을 세운다.
- 압축, 도구 결과 정리, 구조화된 메모, 하위 에이전트 가운데 작업 성격에 맞는 기법을 고른다.
- 대화 기록·작업 상태·장기 기억·업무 원장을 구분하고, 장기 실행에서 컨텍스트 오염을 막는다.
- 체크포인트와 멱등성으로 중단 후 재개를 설계하고, 재개 시점의 외부 상태를 확인한다.
- 여러 세션에 걸친 작업을 다음 실행자가 이어받을 수 있는 인계 구조로 만든다.
들어가며
이틀짜리 작업을 맡긴 에이전트가 둘째 날 오후에 이상한 말을 합니다. "작업이 거의 끝났습니다." 확인해 보니 절반은 손도 대지 않았고, 첫날 오전에 팀과 합의한 규칙 하나는 흔적도 없이 사라졌습니다. 에이전트가 게을러서가 아닙니다. 그동안 컨텍스트는 여러 번 가득 찼고, 그때마다 요약으로 갈아 끼워졌으며, 요약은 흐름을 이어 주었지만 정확한 상태를 지키지는 못했습니다.
사람으로 치면 메모 없이 기억만으로 긴 프로젝트를 하는 셈입니다. 이 장은 에이전트에게 메모장과 업무 일지를 쥐여 주는 법을 다룹니다. 컨텍스트에 무엇을 넣고 밖에 둘지, 압축·외부 메모리·하위 에이전트를 어떻게 고를지, 오염을 어떻게 막을지를 정리한 뒤 체크포인트, 재개, 인계로 넘어갑니다.
핵심 개념
컨텍스트는 유한한 예산이다
Anthropic은 컨텍스트 엔지니어링을 추론 중 모델에 들어가는 최적의 토큰 집합을 선별하고 유지하는 전략의 총체로 정의합니다. 프롬프트 엔지니어링이 지시문을 다듬는 일이라면, 컨텍스트 엔지니어링은 시스템 프롬프트, 도구 정의, 도구 결과, 메시지 기록, 외부 데이터까지 모델이 보는 모든 것을 다룹니다.
근거는 컨텍스트 rot(맥락 부패)입니다. 컨텍스트의 토큰이 늘수록 그 안의 정보를 정확히 떠올리는 능력이 떨어진다는 관찰입니다. 같은 글은 LLM에 주의 예산(attention budget)이 있다고 설명합니다. 트랜스포머는 토큰마다 컨텍스트의 다른 토큰들과의 관계를 계산하므로 관계의 수가 토큰 수의 제곱(n²)에 비례해 늘고, 토큰이 늘수록 주의가 얇게 퍼집니다. 새 토큰 하나하나가 이 예산을 조금씩 씁니다.
비유하면 컨텍스트는 책상 위 공간입니다. 책상이 넓어도 서류를 다 펼쳐 놓으면 지금 필요한 한 장을 찾기 어렵습니다. 창이 크다는 것은 많이 넣을 수 있다는 뜻이지, 넣은 것을 똑같이 잘 쓴다는 뜻이 아닙니다.
무엇을 넣을까: 고도, 도구, 예시
같은 글은 컨텍스트 구성 요소마다 기준을 줍니다.
| 요소 | 피할 것 | 지향할 것 |
|---|---|---|
| 시스템 프롬프트 | 복잡하고 깨지기 쉬운 if-else 논리를 박아 넣기, 반대로 구체적 신호가 없는 막연한 지침 | 행동을 이끌 만큼 구체적이면서 유연한 "알맞은 고도" |
| 도구 | 기능이 너무 넓거나, 어느 도구를 쓸지 판단이 모호한 비대한 도구 세트 | 사람 엔지니어도 어느 도구를 쓸지 바로 말할 수 있는 구성 |
| 예시 | 모든 경계 사례를 늘어놓은 목록 | 기대 행동을 잘 보여 주는 다양하고 대표적인 예시 몇 개 |
"알맞은 고도"는 비행기의 고도에 빗댄 표현입니다. 너무 낮게 날면 지형 하나하나에 걸리고, 너무 높이 날면 목적지가 보이지 않습니다. 예외 사례 180개를 규칙으로 나열한 프롬프트는 규칙 하나를 고칠 때마다 다른 사례가 깨집니다. 원칙과 대표 예시로 바꾸고, 기대 행동은 평가 세트(4장)로 지키는 편이 유지하기 쉽습니다.
적시 검색과 점진적 공개
모든 데이터를 미리 넣는 대신, 에이전트가 파일 경로·저장된 쿼리·링크 같은 가벼운 식별자만 들고 있다가 필요할 때 도구로 불러오는 방식을 적시 검색(just-in-time retrieval)이라고 합니다. Claude Code는 큰 데이터를 통째로 읽지 않고 head와 tail 같은 명령으로 필요한 부분만 봅니다. 에이전트가 탐색하며 필요한 맥락을 조금씩 찾아가는 것을 점진적 공개(progressive disclosure)라고 부릅니다. 사람이 책 전체를 외우지 않고 목차와 책갈피를 쓰는 것과 같습니다.
적시 검색이 늘 이기지는 않습니다. 실행 중 탐색은 미리 넣는 것보다 느리기 때문입니다. 그래서 같은 글은 혼합 전략을 소개합니다. Claude Code는 CLAUDE.md를 처음부터 넣고 나머지 파일은 glob과 grep으로 그때그때 찾습니다. 거의 매번 필요한 안정적 자료는 미리, 크고 자주 바뀌는 자료는 찾아서 쓰는 식이며, 법률이나 금융처럼 맥락이 덜 동적인 영역은 미리 넣는 비중을 높일 수 있습니다.
검색에 성공했다고 정답을 찾은 것은 아닙니다. 검색 결과에는 출처의 신뢰도, 문서의 적용 시점, 현재 사용자의 접근 권한이 함께 따라와야 합니다. 근거를 찾지 못했을 때 "없다"고 단정하지 않고 "찾지 못했다"고 말하게 하는 것도 검색 설계의 일부입니다.
정보의 네 층
장기 실행 시스템에는 성격이 다른 정보가 넷 있습니다. 이를 섞으면 사고가 납니다.
| 층 | 예 | 권위 | 수명 |
|---|---|---|---|
| 대화 기록 | 메시지와 도구 결과 | 낮다. 요약되고 잘린다 | 세션 |
| 작업 상태 | 진행 파일, 체크포인트 | 재개의 근거 | 작업이 끝날 때까지 |
| 장기 기억 | 사용자 선호, 배운 교훈 | 참고 자료. 검증 필요 | 정한 유효기간까지 |
| 업무 원장 | 주문, 송금, 승인 기록 | 가장 높다. 사실의 기준 | 법적·업무적 보존 기간 |
업무 원장(system of record)은 업무상 사실의 최종 기준이 되는 시스템입니다. 에이전트가 "환불을 처리했다"고 기억해도, 환불이 실제로 있었는지는 결제 시스템의 원장이 정합니다. 재개할 때 다음 할 일을 정하는 근거는 대화 기록이 아니라 작업 상태이고, 작업 상태와 원장이 어긋나면 원장이 이깁니다.
압축과 도구 결과 정리
압축(compaction)은 창이 한도에 가까워지면 대화를 요약하고 그 요약으로 새 창을 시작하는 기법입니다. Anthropic은 좋은 압축이 아키텍처 결정, 해결되지 않은 버그, 구현 세부를 남기고 중복된 도구 출력을 버린다고 설명하며, 압축 프롬프트는 먼저 빠뜨리는 것이 없도록(재현율) 다듬고 그다음 군더더기를 줄이는(정밀도) 순서로 조정하라고 권합니다.
가장 가볍고 안전한 압축은 도구 결과 정리입니다. 대화 깊숙이 남은 원문 도구 결과는 대개 다시 볼 필요가 없기 때문입니다. 플랫폼 기능도 있습니다. Claude API의 컨텍스트 편집(context editing)은 서버 쪽에서 오래된 도구 결과를 지우는 전략을 제공하며, 언제 시작할지(trigger), 최근 몇 개를 남길지(keep), 한 번에 최소 얼마를 지울지(clear_at_least), 지우지 않을 도구(exclude_tools)를 정할 수 있습니다. Claude API는 서버 쪽 압축(베타)도 제공하고, OpenAI Agents SDK에는 세션 기록을 Responses API로 압축하는 세션 구현이 있습니다. 이름과 옵션은 바뀔 수 있으니 문서를 확인하세요.
주의
요약은 흐름을 이어 주지만 정확한 상태를 지키지 못할 수 있습니다. "어디까지 했는가", "무엇을 결정했는가"처럼 정확해야 하는 정보는 압축에 맡기지 말고 컨텍스트 밖의 구조화된 기록으로 두세요.
구조화된 메모와 외부 메모리
구조화된 메모는 에이전트가 컨텍스트 창 밖에 메모를 쓰고 나중에 다시 읽는 기법입니다. Anthropic의 예는 Claude Code의 할 일 목록, NOTES.md 파일, 수천 단계에 걸쳐 진행 상황과 지도를 기록한 포켓몬 게임 실험입니다. 분명한 이정표가 있는 반복 작업에 잘 맞습니다.
이를 제품 기능으로 만든 것이 메모리 도구입니다. Claude의 메모리 도구는 클라이언트 쪽에서 동작합니다. 모델이 /memories 아래 파일 작업을 요청하면 애플리케이션의 처리기가 자신이 정한 저장소에서 실행하므로, 안전장치도 애플리케이션 몫입니다. 문서는 모든 경로를 정규화해 /memories 밖으로 나가지 않는지 검증하고(../ 같은 경로 이동 공격 방지), 민감 정보를 걸러 내고, 파일 크기에 상한을 두고, 오래 쓰지 않은 파일을 지우라고 권합니다.
Google ADK는 두 층을 구분합니다. 세션과 상태는 지금 대화 하나의 단기 기억이고, 메모리 서비스는 여러 지난 대화에서 찾아 쓰는 장기 기억 저장소입니다(add_session_to_memory로 넣고 search_memory로 찾습니다). 개발용 인메모리 구현은 재시작하면 사라지므로 운영에는 영속 구현을 씁니다.
하위 에이전트로 컨텍스트를 격리한다
하위 에이전트 구조는 전문화된 하위 에이전트가 깨끗한 창에서 집중된 일을 하고, 압축된 결과만 돌려주는 방식입니다. Anthropic에 따르면 하위 에이전트는 수만 토큰을 탐색해도 대개 1,000~2,000토큰 분량의 요약을 돌려줍니다. 탐색의 잡음이 주 에이전트의 창에 들어오지 않으니 주 에이전트는 종합과 판단에 집중할 수 있습니다. 병렬 탐색이 이득인 복잡한 조사에 잘 맞습니다.
요약으로는 안 되는 결과도 있습니다. 표나 코드처럼 한 글자도 바뀌면 안 되는 산출물을 주 에이전트가 다시 옮겨 적으면, 컨텍스트도 차고 옮기는 과정에서 틀립니다. Anthropic의 리서치 시스템은 하위 에이전트가 결과를 외부 저장소(파일 등)에 쓰고 가벼운 참조(파일 경로, 저장소 키 등)만 돌려주게 해 정보 손실과 토큰 낭비를 줄였습니다. 같은 글은 컨텍스트가 200,000토큰을 넘으면 잘리므로 리드 에이전트가 계획을 메모리에 저장해 두는 방식도 소개합니다.
세 기법의 쓰임은 다음과 같이 정리됩니다.
| 기법 | 잘 맞는 작업 | 잃을 수 있는 것 |
|---|---|---|
| 압축 | 긴 주고받기가 필요한 작업 | 정확한 상태, 초반의 결정 |
| 구조화된 메모 | 이정표가 분명한 반복 작업 | 메모에 적지 않은 것 |
| 하위 에이전트 | 병렬 탐색이 이득인 조사 | 요약에서 빠진 세부(원문은 참조로 보존) |
컨텍스트 오염을 막는다
컨텍스트 오염은 틀리거나 낡거나 신뢰할 수 없는 정보가 컨텍스트에 쌓여 이후 판단을 계속 비트는 현상입니다. 원인은 셋입니다. 실패한 시도의 흔적(같은 오류를 내는 시도가 줄줄이 남아 모델이 그 경로에 붙잡힌다), 신뢰할 수 없는 내용(웹 페이지나 문서 속 지시문), 낡은 기억(이미 바뀐 사실)입니다.
막는 규칙은 다음과 같습니다.
- 쓸모를 다한 원문 도구 결과는 지우고, 필요한 요점과 참조만 남긴다.
- 같은 실패가 반복되면 실패 기록을 요약 한 줄로 줄이고, 새로운 접근을 명시해 다시 시작한다. 필요하면 깨끗한 하위 에이전트에게 맡긴다.
- 외부에서 온 내용은 출처를 표시해 지시와 구분하고, 그 안의 문장을 지시로 따르지 않는다(5장).
- 기억 항목에는 출처와 관찰 시각을 붙이고, 오래된 항목은 다시 확인하거나 버린다.
- 사용자 발화를 검증 없이 시스템 지침 수준으로 올리지 않는다. 기억은 데이터이지 권한이 아니다.
프롬프트 캐시와 컨텍스트 구성
장기 실행 에이전트는 비슷한 앞부분을 수십, 수백 번 다시 보냅니다. 프롬프트 캐시는 이 반복되는 앞부분(prefix)의 처리를 재사용해 비용과 지연을 줄입니다. Claude API 문서 기준으로 캐시는 tools, system, messages 순서로 앞부분을 만들고, 어느 층이 바뀌면 그 층과 뒤의 모든 층이 무효가 됩니다. 도구 정의를 바꾸면 캐시 전체가 무효입니다. 기본 수명은 5분이며 쓸 때마다 갱신되고, 1시간 옵션도 있습니다. 모델마다 캐시할 수 있는 최소 길이가 있어, 그보다 짧은 앞부분은 표시해도 캐시되지 않습니다. 응답의 cache_read_input_tokens와 cache_creation_input_tokens로 캐시 적중을 확인합니다.
캐시를 깨는 흔한 실수는 요청마다 바뀌는 값(현재 시각, 요청 번호)을 고정 지침보다 앞에 두기, 도구 정의를 매번 새로 만들며 내용이나 순서를 바꾸기, 키 순서가 무작위로 바뀌는 JSON 직렬화 쓰기입니다. 변하지 않는 것을 앞에, 변하는 것을 뒤에 두는 것이 원칙입니다. 도구 결과 정리도 캐시와 충돌합니다. 지운 지점부터 캐시가 무효가 되므로, 문서는 한 번에 충분히 지워 무효화의 대가를 감수할 가치가 있게 하라고(clear_at_least) 권합니다.
체크포인트와 멱등성
외부에 영향을 남기는 장기 작업은 실패했을 때 처음부터 다시 하면 안 됩니다. Anthropic의 리서치 시스템 글은 에이전트가 상태를 가지며 오류가 누적된다고 지적하고, 오류가 난 지점에서 재개하는 시스템에 재시도 로직과 정기 체크포인트 같은 결정적 안전장치를 결합했다고 적습니다. 작은 실패도 치명적일 수 있으니 도구가 실패하고 있다는 사실을 에이전트에게 알리라고도 권합니다.
체크포인트는 재개할 수 있도록 단계별 결과를 영구 저장한 지점이고, 멱등 키는 같은 요청이 반복돼도 효과가 한 번만 일어나게 하는 식별자입니다. 설계 요소는 셋입니다.
- 단계별로 무엇을, 언제, 어떤 결과로 했는지 영구 저장소에 기록한다.
- 외부 호출에는 작업과 대상에서 결정적으로 만든 멱등 키를 붙인다(예:
작업ID:대상ID:단계). - 재개할 때는 모델의 기억이 아니라 저장된 기록과 원장으로 다음 할 일을 정한다.
중단 후 재개 설계
저장한 지점에서 이어 간다고 재개가 안전해지지는 않습니다. 저장한 뒤 세상이 바뀌었을 수 있기 때문입니다. 재개 절차에는 다음 확인을 넣습니다.
| 확인 | 이유 |
|---|---|
| 외부 상태 대조 | 마지막 기록 이후 외부 작업이 실제로 일어났는지 원장이나 조회 API로 확인 |
| 만료 확인 | 승인, 자격 증명, 미리보기 식별자, 핸들이 아직 유효한지 |
| 실행 소유권 | 같은 작업을 다른 실행기가 이미 잡지 않았는지(일정 시간만 유효한 점유권인 임대와 그 만료로 관리) |
| 버전 호환 | 저장된 상태를 지금 코드와 에이전트 정의로 읽을 수 있는지 |
프레임워크도 이를 돕습니다. OpenAI Agents SDK는 사람 승인을 기다리는 실행을 RunState로 직렬화해 데이터베이스나 큐에 저장했다가 복원해 이어 갈 수 있게 합니다. 문서는 직렬화된 상태에 승인 결정, 대기 중인 도구 호출과 그 인자까지 들어 있으므로 서버가 통제하는 저장소에 두고 신뢰할 수 있는 스냅샷만 복원하며, 에이전트 정의나 SDK의 버전 표시를 상태와 함께 저장하라고 권합니다. Google ADK에서는 상태를 이벤트의 state_delta로 기록해야 저장되며, 서비스에서 받아 온 세션의 session.state를 직접 고치면 추적되지 않아 저장되지 않을 수 있습니다. 상태 값은 직렬화할 수 있는 기본 형식만 써야 합니다.
장기 작업의 인계
Anthropic의 장기 코딩 에이전트 실험은 두 실패를 관찰했습니다. 한 번에 너무 많은 일을 하려다 중간에 컨텍스트가 바닥나는 실패, 그리고 뒤의 세션이 부분 진행을 보고 일이 끝났다고 선언하는 실패입니다. 해결책은 역할 분리였습니다.
- 초기화 에이전트(첫 세션): 개발 서버를 띄우는
init.sh, 에이전트가 한 일을 적는claude-progress.txt, 처음 추가한 파일을 보여 주는 첫 커밋, 그리고 200개가 넘는 기능을 모두 '실패'로 표시한 기능 목록을 만든다. - 코딩 에이전트(이후 세션): 한 번에 기능 하나만 진전시키고, 설명적인 커밋과 진행 기록으로 다음 세션을 위한 흔적을 남기며, 환경을 깨끗한 상태로 두고 끝낸다.
기능 목록은 마크다운보다 모델이 부적절하게 고치거나 덮어쓸 가능성이 낮은 JSON으로 썼고, 코딩 에이전트에게는 passes 필드만 바꾸게 했으며, 시험을 지우거나 고치는 것은 허용되지 않는다고 못 박았습니다. 새 세션은 작업 디렉터리를 확인하고, Git 기록과 진행 파일을 읽고, 기능 목록에서 우선순위가 가장 높은 미완료 기능을 고르고, 개발 서버를 띄워 기본 동작을 시험한 뒤에 일을 시작했습니다. 기능은 사람처럼 끝에서 끝까지 시험해 확인한 뒤에만 통과로 표시했습니다.
이 실험을 일반화하면 인계 패키지가 됩니다. 다음 실행자가 긴 대화 전체를 읽지 않고도 이어받을 수 있게 하는 문서입니다. 목표와 완료 기준, 완료된 항목과 그 검증 결과, 남은 일과 우선순위, 확인된 사실과 아직 가정인 것, 산출물과 외부 작업 식별자, 다음 행동의 전제와 추가 승인이 필요한 지점을 담습니다. "거의 끝났다" 같은 자기평가 대신 검증된 산출물을 적는 것이 핵심입니다.
대화 상태를 어디에 둘까
대화 기록을 누가 관리하는지도 정해야 합니다. OpenAI Agents SDK는 세 방식을 둡니다. 결과를 다음 입력 목록으로 직접 넘기는 수동 관리, 실행 전 기록을 불러오고 실행 후 새 항목을 저장하는 세션, 그리고 서버 쪽 대화 관리(conversation_id 또는 previous_response_id)입니다. 문서는 대화마다 지속 전략 하나를 고르라고 하며, 같은 실행에서 세션과 서버 쪽 이어가기 옵션을 함께 쓸 수 없고, 클라이언트 관리 기록과 서버 관리 상태를 섞으면 맥락이 중복될 수 있다고 경고합니다.
Google ADK의 상태는 키 접두사로 범위를 정합니다.
| 접두사 | 범위 |
|---|---|
| 없음 | 현재 세션 |
user: |
같은 앱 안에서 그 사용자의 모든 세션 |
app: |
그 앱의 모든 사용자와 세션 |
temp: |
한 번의 호출(invocation) 안. 끝나면 버려진다 |
범위를 잘못 고르면 한 사용자의 정보가 다른 사용자에게 새거나, 필요한 정보가 다음 세션에 사라집니다.
깊이 읽기
체크포인트와 외부 부작용 사이의 틈
체크포인트 저장과 외부 시스템 변경은 한 트랜잭션으로 묶이지 않습니다. 외부 호출이 성공한 직후, 결과를 기록하기 전에 프로세스가 죽을 수 있습니다. 재개 코드가 기록만 보면 "아직 안 했다"고 판단해 같은 일을 다시 합니다.
이 틈을 다루는 표준 절차는 의도 기록 → 실행 → 결과 기록입니다. 실행 전에 "이 멱등 키로 이 일을 하려 한다"를 먼저 적고, 실행하고, 결과를 적습니다. 재개할 때 의도는 있는데 결과가 없는 항목을 만나면, 다시 실행하기 전에 멱등 키로 외부 시스템에 처리 여부를 조회합니다. 처리되었으면 결과만 기록하고, 처리되지 않았으면 같은 키로 실행합니다. 외부 시스템이 멱등 키를 지원하지 않는다면, 중복 실행의 피해가 큰 작업일수록 사람 확인을 거치게 하세요. 모든 단계를 되돌릴 수 없는 작업이라면 5장의 보상 작업을 함께 설계해야 합니다.
기억의 수명주기
장기 기억은 한 번 잘못 저장되면 여러 작업에 반복해서 영향을 줍니다. 그래서 기억에도 생애가 있어야 합니다.
- 승격 기준: 무엇을 기억으로 남길지 정한다. 한 번 지나간 말이 아니라 반복되거나 사용자가 확인한 정보만 남긴다.
- 출처와 시점: 누가 언제 말했는지, 어떤 근거로 확인했는지를 함께 저장한다.
- 충돌 해결: 새 정보가 옛 기억과 다르면 최신성과 출처의 권위로 정하고, 바뀐 이력을 남긴다.
- 만료와 재확인: 유효기간을 두고, 지나면 다시 확인하거나 버린다.
- 정정과 삭제의 전파: 사용자가 삭제를 요청하면 원본뿐 아니라 검색 색인과 그 기억에서 만든 요약까지 지운다.
다섯째 단계는 개인정보 보호 의무와 맞닿으므로, 보존·삭제 기준은 적용받는 법령과 약관에 맞춰 개인정보 담당자와 함께 정하세요. 기술적으로는 기억 저장소를 사용자별로 격리하고, 삭제가 실제로 일어났는지 확인하는 시험을 둡니다.
메모리와 압축 정책도 평가한다
압축 프롬프트를 바꾸거나 기억 정책을 바꾸면 비용은 줄어도 정확도가 떨어질 수 있습니다. 정책 자체를 평가 대상으로 삼으세요. 기억이 없는 기준선과 비교하고, 압축 직후에 이전 결정을 정확히 따르는지 묻는 과제를 넣고, 일부러 낡은 기억을 심어 두고 그것을 걸러 내는지 봅니다. 강제로 중단한 뒤 재개 성공률을 재는 것도 좋은 지표입니다.
실무 장면
미리내북스: 1,800권 변환 작업이 잊어버린 결정
전자책 유통사 '미리내북스'는 구형 전자책 1,800권을 새 형식으로 변환하고 접근성 정보를 채우는 일을 에이전트에게 맡겼다. 첫 시도는 자동 압축을 켠 긴 세션 하나였다. 사흘째, 에이전트는 첫날 팀과 정한 규칙("표 이미지의 대체 텍스트는 원문 캡션에서 가져온다")을 잊고 140권을 다른 방식으로 처리했다. 검증기를 돌리지 않은 채 '완료'로 표시한 책도 60권이었다.
팀은 두 대안을 기각했다. 더 큰 컨텍스트 창을 가진 모델로 바꾸는 안은 결정이 요약 과정에서 사라지는 문제를 미룰 뿐이라고 봤다. 시스템 프롬프트에 "결정을 잊지 말라"고 쓰는 안은 기억을 모델에게 맡기는 같은 실수라고 봤다.
새 구조에서 첫 세션은 초기화만 한다. 1,800권의 상태(pending, converted, validated, failed)와 검증 결과 경로를 담은 books.json, 합의된 변환 규칙을 적는 decisions.md, 변환기와 검증기를 실행하는 init.sh를 만들고 커밋한다. 이후 세션은 시작할 때 세 파일과 Git 기록을 읽고, 한 번에 20권씩 처리한다. 상태는 검증기가 통과한 뒤에만 validated로 바꿀 수 있고, 검증기의 원문 로그는 요점만 남기고 컨텍스트에서 지운다. 새 규칙이 생기면 decisions.md에 먼저 적고 커밋한 뒤 일을 계속한다.
다음 1,000권에서 재작업은 없었고, 검증 없이 완료로 표시된 책도 없었다. 세션당 컨텍스트 사용량은 오히려 줄었다.
이랑정책연구소: 사흘짜리 조사를 이어받기
'이랑정책연구소'는 전국 기초자치단체의 청년 주거 지원 정책을 사흘 동안 조사해 비교표를 만든다. 첫날 세션은 "41곳 중 23곳 조사 완료"라는 요약을 남겼다. 둘째 날 아침, 의뢰처가 비교 기준에 소득 요건을 추가했고, 조사한 지자체 두 곳이 지원 금액을 바꿔 공고했다. 둘째 날 세션은 첫날 요약을 그대로 믿고 나머지 18곳만 조사했다. 최종 표에는 바뀌기 전 금액 두 건이 남았고, 첫날 조사한 23곳은 소득 요건 칸이 비어 있었다.
팀은 대안을 비교했다. 첫날 대화 전체를 다음 세션에 넘기는 안은 컨텍스트를 채우면서도 무엇이 바뀌었는지 알려 주지 않는다. 매일 처음부터 다시 조사하는 안은 비용이 세 배였다. 팀은 인계 패키지와 재개 점검을 택했다.
인계 패키지에는 비교 기준 문서의 버전, 지자체별 상태와 조사한 필드, 근거 URL과 확인 시각, 아직 가정인 항목, 다음 세션의 첫 할 일을 적는다. 새 세션은 일을 시작하기 전에 기준 문서 버전을 확인하고, 버전이 바뀌었으면 새로 생긴 필드가 비어 있는 지자체를 다시 조사 대상으로 돌린다. 확인 시각이 24시간을 넘은 근거는 공고 페이지의 갱신 여부를 먼저 본다. 조사 결과는 지자체별 파일로 저장하고, 세션은 그 파일의 경로만 들고 다닌다.
다음 조사에서 기준이 한 번, 공고가 다섯 곳에서 바뀌었지만 최종 표의 낡은 값은 0건이었다.
자주 틀리는 지점
- "창이 크면 컨텍스트 관리는 필요 없다." 숫자가 커지면 다 들어갈 것 같지만, 창이 찰수록 회상 정확도가 떨어집니다. 큰 창은 관리의 필요를 미룰 뿐입니다.
- "압축 요약이면 진행 상태도 보존된다." 요약을 읽으면 흐름이 이어져 안심되지만, 정확한 상태와 초반의 결정은 빠질 수 있습니다. 정확해야 하는 것은 구조화된 기록으로 둡니다.
- "재개는 모델에게 어디까지 했는지 물으면 된다." 모델이 그럴듯하게 답해 주니 편하지만, 새 프로세스의 모델은 이전 실행을 모릅니다. 상태는 기록과 원장으로 판단합니다.
- "체크포인트에서 이어 가면 안전하다." 저장했다는 사실이 안심을 주지만, 저장 이후 외부 상태가 바뀌었거나 승인이 만료되었을 수 있습니다. 재개 전에 대조합니다.
- "하위 에이전트가 표를 통째로 돌려주면 정확하다." 원본을 직접 받으니 정확해 보이지만, 리드가 다시 옮겨 적으며 컨텍스트가 차고 값이 틀립니다. 결과는 저장소에 두고 참조를 넘깁니다.
- "사용자 발화를 그대로 장기 기억에 넣으면 개인화가 된다." 가장 빠른 개인화 방법이지만, 검증 없는 승격은 낡은 정보와 지시 주입의 통로가 됩니다.
- "도구 결과를 자주 지울수록 좋다." 지울수록 창이 가벼워지지만, 지울 때마다 프롬프트 캐시가 무효가 될 수 있습니다. 충분한 양을 한 번에 지웁니다.
한눈에 정리
| 항목 | 기억할 답 |
|---|---|
| 컨텍스트가 유한한 이유 | 컨텍스트 rot, 주의 예산, 토큰 n²개 관계 |
| 시스템 프롬프트 기준 | 알맞은 고도, 대표 예시 몇 개 |
| 적시 검색 | 가벼운 식별자 + 필요할 때 로드, 안정적인 핵심 자료는 미리 |
| 가장 가벼운 압축 | 오래된 도구 결과 정리 |
| 기법 선택 | 주고받기 많으면 압축, 이정표 있으면 메모, 병렬 조사면 하위 에이전트 |
| 정확한 상태의 자리 | 컨텍스트 밖 구조화된 기록. 원장과 어긋나면 원장 |
| 캐시를 지키는 배치 | 변하지 않는 것 앞, 변하는 것 뒤 |
| 재개 절차 | 기록 읽기 → 외부 상태 대조 → 만료·소유권·버전 확인 → 멱등 키로 실행 |
| 인계 | 검증된 산출물, 사실과 가정 구분, 다음 행동의 전제 |
공식 문서로 확인하기
- Anthropic: Effective context engineering for AI agents — 컨텍스트 rot, 알맞은 고도, 적시 검색, 장기 작업의 세 기법
- Anthropic: Effective harnesses for long-running agents — 초기화·코딩 에이전트, JSON 기능 목록, 세션 시작 절차
- Claude API: Context editing — 도구 결과 정리 옵션과 캐시와의 관계
- Claude API: Memory tool — 클라이언트 쪽 메모리, 경로 이동 방지, 크기와 만료
- Claude API: Prompt caching — 캐시 순서, 무효화 규칙, 수명
- OpenAI Agents SDK: Sessions — 세션 구현과 서버 쪽 이어가기와의 관계
- OpenAI Agents SDK: Human-in-the-loop —
RunState직렬화와 저장 시 주의 - Google ADK: State — 상태 접두사, 영속성, 상태 갱신 방법
셀프 체크
3-1. 컨텍스트 창이 커져도 컨텍스트 관리가 필요한 이유를 '주의 예산'이라는 말을 써서 설명하라.
3-2. 오래된 도구 결과를 지우는 것이 가장 가벼운 압축으로 꼽히는 이유는 무엇이며, 프롬프트 캐시와 함께 쓸 때 무엇을 주의해야 하는가?
3-3. 대화 기록, 작업 상태, 장기 기억, 업무 원장 가운데 재개 시 다음 할 일을 정하는 근거는 무엇이어야 하며, 그것이 원장과 어긋나면 어떻게 하는가?
3-4. 장기 코딩 하네스가 기능 목록을 JSON으로 두고 통과 여부 필드만 바꾸게 한 설계는 어떤 실패를 막으려는 것인가?
3-5. 체크포인트를 '의도 기록 → 실행 → 결과 기록' 순서로 남기는 이유를, 결과 기록 직전에 프로세스가 죽은 경우를 들어 설명하라.
3-6. 장기 기억 항목마다 출처와 관찰 시각을 함께 저장하는 이유 두 가지를 들어라.
3-7. 사흘짜리 조사 작업을 다른 실행자에게 넘기는 인계 문서의 목차를 다섯 줄로 설계하고, 각 줄에 들어갈 내용을 한 문장씩 적어라.
실습 과제
실습
진행 파일과 강제 중단 재개 (60분)
- 항목 50개 이상을 순서대로 처리하는 작업(문서 요약, 데이터 변환 등)을 고른다.
- 항목별 상태(
pending,in_progress,done,failed), 멱등 키, 결과 경로를 담는 JSON 진행 파일을 설계한다. - 외부에 쓰는 동작에는 의도 기록 → 실행 → 결과 기록 순서를 적용한다.
- 실행 중 임의 시점에 프로세스를 세 번 강제로 끝내고 다시 실행한다. 한 번은 외부 쓰기 직후에 끝낸다.
완료 기준: 재실행이 진행 파일 기준으로 이어지고, 어떤 항목도 두 번 처리되지 않았으며, 최종 결과가 중단 없이 돌린 경우와 같으면 완료다.
실습
압축 전후 정보 손실 검사 (40분)
- 30턴 이상 이어진 실제 에이전트 대화 하나를 고른다(민감 정보는 지운다).
- 그 대화에서 뒤 작업에 꼭 필요한 정보 10개(결정, 미해결 문제, 식별자, 수치)를 사람이 먼저 뽑아 목록으로 만든다.
- 지금 쓰는 압축 프롬프트로 요약을 만들고, 10개 중 몇 개가 정확히 남았는지 센다.
- 빠진 항목을 기준으로 압축 프롬프트를 고치고 다시 센다. 그다음 요약 길이를 줄여도 점수가 유지되는지 본다.
완료 기준: 고친 프롬프트가 10개 중 9개 이상을 보존하고, 고치기 전후의 보존 개수와 요약 길이가 표로 남아 있으면 완료다.