20만 토큰의 뇌절단(Lobotomy)을 살아남기: Unix init.d와 '메멘토'가 AI 코딩 에이전트를 컨텍스트 압축으로부터 면역화시킨
요약
최신 AI 코딩 에이전트가 긴 세션에서 컨텍스트 압축 기능을 사용할 때, 방대한 대화 기록을 산문 요약으로 대체하는 것이 치명적인 문제를 일으킨다. 이로 인해 에이전트는 이전의 거버넌스 규칙이나 아키텍처 불변성을 잊고 잘못된 행동(예: 무단 커밋)을 할 수 있다. 따라서 소프트웨어 엔지니어링은 서사적 요약보다 이산적이고 구체적인 '기억'에 의존해야 하며, 이를 위해 Unix init.d와 같은 원시적이고 불변한 메커니즘이 필요하다.
핵심 포인트
- AI 에이전트의 컨텍스트 압축은 중요한 세션 정보를 손실시킨다.
- 소프트웨어 엔지니어링은 산문 요약보다 이산적인 '불변성'에 의존한다.
- 에이전트에게는 전체 대화 기록을 보존하는 원시적 메모리 메커니즘이 필요하다.
IDE의 자동 컨텍스트 요약 기능에 의존하는 것이 함정인 이유—그리고 1980년대 유닉스 부트 스크립트가 자율 에이전트에게 파괴 불가능한 메모리를 제공하는 방법.
"시스템이 필요하지? 메모해. 구체적인 메모... 기억은 믿을 수 없어."
— 레너드 셸비(Leonard Shelby), 메멘토(Memento) (2000)
1. 20만 토큰의 뇌절단: 장기 에이전트 세션의 조용한 살인자
Claude Code, Google Antigravity, Cursor, 또는 Gemini CLI와 같은 최신 에이전트 코딩 환경을 실제 프로덕션 티켓에 사용해 본 적이 있다면, 복잡한 세션이 20만 토큰을 넘어서는 순간 느껴지는 공포감을 이미 알고 있을 것입니다.
터미널 구석에서 작은 시스템 배너가 깜빡입니다:
[Context compacted: 235,246 tokens → 14,800 tokens]
겉보기에는 '컨텍스트 압축(context compaction)'이 도움이 되는 플랫폼 기능처럼 들립니다. 대화가 컨텍스트 창의 한계에 다다르면, 호스트 런타임은 에이전트를 일시 중지시키고 전체 23만 토큰 분량의 기록을 백그라운드 요약 모델에 전달한 다음, 이력을 세 단락짜리 산문 요약으로 대체하고 에이전트가 계속 진행하도록 합니다.
하지만 압축된 지 30초 후에 무슨 일이 일어날까요?
당신의 에이전트는 방금 전두엽 절제술(prefrontal lobotomy)을 겪었습니다.
압축되기 전, 당신과 에이전트는 미묘한 아키텍처 불변성(architectural invariants)을 확립하는 데 45분을 보냈습니다:
- 당신의 적대적 코드 리뷰어는 라운드 1과 2에서 두 가지 결함 있는 구현을 거부했고,
didChangeDependencies에 대한 거짓 양성 경고를 무시했습니다. - 당신의 워크플로우 규칙은 인간의 승인 에어록(airlock)에서 중단하지 않고
git commit이나git push를 실행하는 것을 엄격히 금지합니다.
그런 다음 호스트 요약기가 모든 280단계 과정을 공손하고 일반적인 기업체 장황한 이야기로 압축합니다:
"요약: 사용자 및 어시스턴트는 BlocSignal 리포지토리의 Issue #320에서 Flutter 및 Jaspr 위젯의 커스텀 동등성(custom equality)을 지원하기 위해 작업하고 있습니다. 여러 파일이 수정되고 검토되었습니다. 어시스턴트는 현재 리뷰 피드백을 처리하고 있습니다."
방금 압축된 에이전트가 다음 턴에서 깨어날 때:
- 거버넌스 법규를 잊어버린다—그리고 즉시 질문 없이
git commit과git push를 실행한다. - Round 1에서 왜 실패했는지 잊는다—그리고 방금 100 스텝을 들여 제거했던 정확한 순진한 버그를 즐겁게 재구현한다.
- 빌드 그래프에서의 위치를 잃어버린다—코드베이스 고고학(codebase archaeology)을 다시 실행하거나 어떤 티켓을 작업하고 싶은지 당신에게 묻는다.
왜 호스트 압축(host compaction)은 소프트웨어 엔지니어링에서 그렇게 치명적으로 실패하는가?
그 이유는 산문 요약(prose summarization)이 서사적 핵심(narrative gist)에 최적화되는 반면, 소프트웨어 엔지니어링은 이산적이고 협상 불가능한 불변성(discrete, non-negotiable invariants)에 의존하기 때문이다. 230,000 토큰 분량의 컴파일러 및 아키텍처 세션을 세 단락의 산문으로 요약하는 것은 실행 가능한 바이너리를 그 헥스 덤프(hex dump)의 JPEG 스크린샷을 찍는 것과 같다.
2. 메멘토 원칙: 요약을 믿지 마라—타투를 신뢰하라
크리스토퍼 놀란의 2000년 네오-느와르 걸작 _메멘토(Memento)_에서 주인공 레너드 셸비는 전향성 기억상실증(anterograde amnesia)을 앓고 있다. 매 15분마다 그의 작업 기억(working memory)은 완전히 초기화된다—이는 생물학적 컨텍스트 압축이다.
레너드는 곧 생존의 치명적인 규칙을 발견한다: 그는 휘갈겨 쓴 메모나 모호한 인상에 의존할 수 없다, 왜냐하면 그의 미래 자아가 그것들을 오해하거나, 덮어쓰거나, 혹은 조종당할 것이기 때문이다.
대신 레너드는 두 가지 계층의 외부 기억 아키텍처를 구축한다:
- 불변 타투(Immutable Tattoos) (
Fact 1,Fact 2, ...): 영구적이며, 한 번 쓰여지면 수정할 수 없는 물리적 진실들로, 그의 미래 자아가 깨어날 때 가장 먼저 읽어야 하는 엄격한 계층 구조를 가지고 피부에 직접 새겨진다. - 폴라로이드 사진 (활성 전선, The Active Frontier): 세상의 물리적 객체(
His Car,The Motel Room)에 대한 구체적이고 검증 가능한 스냅샷이며, 간결하고 사실적인 상태 캡션이 붙어 있다.
AI 코딩 에이전트를 컨텍스트 압축으로부터 면역화하기 위해, 우리는 정확히 동일한 분할(split)이 필요했다: 호스트 LLM 요약기(host LLM summarizer)가 당신의 워크플로우나 아키텍처 제약을 보존할 것이라고 결코 믿지 말아야 한다.
3. 단일 TODO.md 또는 PROGRESS.md 스크래치패드가 실패하는 이유
개발자들이 컨텍스트 압축(context compaction)을 우회하려고 할 때, 보통 에이전트에게 다음과 같이 지시합니다:
"작업하는 동안
PROGRESS.md나TODO.md파일을 업데이트하여, 컨텍스트가 초기화되어도 읽을 수 있도록 해줘."
만약 이것을 시도해 본 적이 있다면, 얼마나 빨리 낡아버리는지 알고 있을 겁니다:
- 파괴적인 덮어쓰기 함정(The Destructive Overwrite Trap):
PROGRESS.md는 단일한 변경 가능한 파일이기 때문에, 에이전트가 파일을 하단에서 현재 단계로 업데이트할 때마다, 이 파일은 재-생성되거나 편집됩니다. 그 과정에서 파일 상단에 있던 아키텍처 규칙과 계획 제약 사항들이 점진적으로 압축되거나, 변형되거나, 실수로 삭제됩니다. - 모놀리식 비대화 함정(The Monolithic Bloat Trap): 혹은 반대의 일이 발생합니다. 에이전트가
PROGRESS.md에 800줄 분량의 의식의 흐름 노트(stream-of-consciousness notes)를 추가하여, 활성 명령어 포인터(active instruction pointer)를 '중간에서 길을 잃음(Lost in the Middle)' 주의 집중 저하 지점(attention sink)이 발생하는 오래된 텍스트 벽 속에 파묻어 버립니다.
단일한 스크래치패드 파일은 **불변의 법칙(immutable laws)**과 **변경 가능한 프로그램 카운터(mutable program counters)**를 혼동하기 때문에 실패합니다.
4. 1983년 Unix init.d (rc.d): 어휘적 실행 레벨 상태 파일 (Lexical Runlevel State Files)
1983년, AT&T System V Unix는 /etc/init.d와 /etc/rc.d 부팅 디렉토리를 도입했습니다. 패키지 하나가 편집하려고 할 때마다 깨지는 거대하고 취약한 단일 /etc/rc 셸 스크립트 대신, 유닉스는 시스템 초기화 과정을 번호가 매겨지고 어휘적으로 순서가 지정된 파일로 분리했습니다:
/etc/rc.d/
├── S00_sysctl
├── S10_network
...
유닉스가 부팅하거나(또는 실행 레벨을 변경할 때), init은 단순히 어휘적 순서(00 → 99)에 따라 S*를 글로브(glob)합니다. 각 번호가 매겨진 파일은 단일하고 격리된 생명 주기 책임만을 가집니다.
우리는 LLM 컨텍스트 압축에서 깨어나는 것이 유닉스의 웜 리부트(warm reboot)와 동일하다는 것을 깨달았습니다.
다음으로 Part 3.6에서는 에이전트에게 Stuart Feldman의 1976년 Makefile DAG(Target 1부터 Target 8)를 부여했습니다. 다음으로, 세션의 비공개 아티팩트 디렉토리(<brain>/state/)에 위치한 init.d 디렉토리인 **Target 0: read-init-d**를 추가했습니다. 이 디렉토리에는 어휘적으로 번호가 매겨진 다섯 개의 파일이 포함되어 있습니다:
<brain>/state/
├── 00_governance.md # 부팅 시 한 번 쓰기(Write-once): 활성 워크플로우 스킬 경로 및 인간 게이트 에어록
├── 10_ticket.md # Target 1에서 한 번 쓰기: 이슈 ID, 브랜치, 작업 트리 및 요구 사항
...
flowchart TD
Compact["💥 호스트 컨텍스트 압축 실행 (235,246 토큰 → 14,800 토큰)"] --> Boot["Target 0: read-init-d
(어휘적 순서로 <brain>/state/*.md 전역 검색)"]
Boot --> F00["00_governance.md
(불변: 워크플로우 SKILL.md 포인터 및 인간 승인 에어록 법규)"]
...
이러한 어휘적 00 → 99 분리가 왜 완벽한지 살펴보겠습니다:
- 한 번 쓰기 단조성 래치 (
00,10,20):00_governance.md(활성SKILL.md경로 + 인간 일시 정지 게이트),10_ticket.md(이슈 범위), 그리고20_plan_approved.md(승인된 아키텍처)는 한 번만 기록되며 구현 과정 중에는 절대 편집되지 않아 에이전트가 진행 상황을 업데이트하는 동안 자신의 법규를 덮어쓰는 것이 물리적으로 불가능하게 만듭니다. - 추가 전용 부정 기억 (
30_critic_summary.md): Target 4에서 발생하는 모든 적대적 비평가(Adversarial Critic) 라운드는 그 판결(차단된 문제 해결 + 거짓 양성 사소한 지적 무시)을 여기에 추가하여, 컨텍스트 압축 후 에이전트가 거부된 함정으로 다시 루프하는 것을 방지합니다. - 변경 가능한 프로그램 카운터 및 실시간 리더보드 (
99_next_action.md):99_next_action.md만 각 전환 시 덮어쓰여 생명 주기 체크리스트와 하단 세 개의 필드를 포함합니다:Current Target,Last Completed Step, 그리고Next Permitted Action.
.stamp 센티넬 파일 및 콘텐츠 주소 지정 영수증 (git add -N + shasum -a 256): r/AI_Agents에서 Part 3.6의 두 독자가 make와 git 플러밍(plumbing)이 깨어남에 따라 어떻게 교차하는지 발견했습니다:
- Ctbhatia: "파일을 생성하지 않는 타겟은 호출될 때마다 재실행되므로, API를 호출하는 단계에는 스탬프 파일(stamp file)을 제공해야 합니다. 그렇지 않으면 수면에서 깨어난 것이 댓글 게시를 재현합니다."
- Previous_Tea_2250: "인간 승인 타겟은 단순히 존재하는 파일을 넘어 정확한 입력/diff 해시와 연결된 영수증이어야 합니다... 작은 git의 함정: git diff HEAD는 추적되지 않은 파일(untracked files)을 놓치고, 반면 git write-tree는 스테이징 영역(index)을 기록할 뿐, 스테이징되지 않은 편집 내용은 기록하지 않습니다."
이 git의 함정은 티켓 #321에서 매우 중요하게 입증되었습니다. 당시 저희 TDD 서브 에이전트가 완전히 새로운 추적되지 않은 파일(deep_collection_equality.dart)을 생성했기 때문입니다. branch.diff 렌더링 전에 git add -N . (--intent-to-add)를 실행하고, 30_critic_summary.md를 shasum -a 256 branch.diff에 바인딩한 다음, git commit 직전에 SHA-256 해시를 검증하는 과정은 추적된 파일(tracked), 스테이징되지 않은 파일(unstaged files), 그리고 추적되지 않은 파일을 단일하고 위변조 방지되는 영수증으로 압축(compactions)하여 잠그는 역할을 했습니다.
- 사이버네틱스가 이것을 "스티그머지(Stigmergy)"라고 부르는 이유 — 문자 그대로 "흉터 주도 작업" (Grassé, 1959): Facebook에서 시스템 엔지니어 Mike Mol은 Part 3.6에 두 단어짜리 댓글을 남겼습니다: "참고: 스티그머지(stigmergy)." 1959년, 동물학자 Pierre-Paul Grassé는 그리스어
στίγμα(stigma: 표시, 천공 또는 흉터) +ἔργον(ergon: 작업)에서 유래한 스티그머지라는 용어를 만들어냈습니다. 이는 개별 기억이 거의 없는 흰개미들이 물리적 환경에 상태를 직접 인코딩함으로써 어떻게 대성당 무덤을 조정하는지를 설명하기 위함이었으며, 문자 그대로는 **"흉터 주도 작업(scar-driven work)"**을 의미합니다./etc/init.d파일 (00→99)은 _세마테크토닉 스티그머지(sematectonic stigmergy)_를 제공하며 (디스크의 아티팩트가 다음Makefile타겟을 트리거함),SCAR_REGISTRY.md는 _표식 기반 스티그머지(marker-based stigmergy)_를 제공합니다 (음의 무한 페로몬 장벽).
전역적인 AGENTS.md / GEMINI.md에 있는 단 하나의 부트 로더 규칙이 디렉터리를 모델에 연결합니다:
Memento Bootloader (Target 0: read-init-d): "만약 `/state/.md`가 존재한다면—그리고 어떤 컨텍스트 압축(context compaction)에서 깨어날 때 즉시—다른 어떠한 조치를 취하기 전에 `/state/.md` 내의 모든 파일을 사전식 순서(00 → 99)로 읽는다."
00 → 99를 읽는 작업이 압축 후에 발생하므로, 이 다섯 개의 간결한 파일들(총 약 1,800 토큰)은 신선한 컨텍스트 창의 맨 끝에 배치되어 최대의 최신성 어텐션(recency attention)을 누리게 됩니다!
5. 방어 계층 1: init이 C 코드를 컴파일하지 않는 이유 (fork() / wait() 서브 에이전트)
init.d가 세션을 압축으로부터 복구해야 할 상황에 놓이기 전에, 유닉스(Unix)는 메모리 관리에 대해 훨씬 더 깊은 교훈을 가르쳐 줍니다: PID 1 (init)이나 GNU make는 리눅스 커널을 빌드할 때 왜 메모리가 고갈되지 않는가?
왜냐하면 make는 kernel/sched/core.c를 자체 주소 공간 내에서 컴파일하지 않기 때문입니다! 이는 fork()와 exec()를 호출하여 일시적인 자식 gcc 프로세스를 생성하고, gcc가 디스크에 core.o를 작성하고 exit 0을 기다린 다음, 자식의 메모리 100%를 회수합니다.
순진한 에이전트 코딩(agentic coding)에서는 단일 거대 에이전트가 25개의 파일을 읽고 (+60k 토큰), 장황한 테스트 스위트를 네 번 실행하며 (+90k 토큰), 1,100줄짜리 git diff를 하나의 컨텍스트 창에서 읽어냅니다. 이는 심지어 git commit에 도달하기 전에 작업 메모리에 190,000 토큰의 죽은 컴파일러 출력을 채워 넣는 행위입니다.
flowchart TD
T2["Depth-0 Orchestrator: Target 2 (approved-plan)"] -->|"fork()"| W1["Ephemeral Archaeology Subagent\n(Reads 20 files, writes plan.md → exit 0)"]
W1 -->|"wait(): 15-line summary"| T3["Depth-0 Orchestrator: Target 3 (implementation-diff)"]
...
우리의 Make-Fork 서브 에이전트 아키텍처 (SCAR-PROC-95) 하에서는 다음과 같습니다:
주요 에이전트는 자체 컨텍스트 창에서 무거운 검색, 테스트 스위트 또는 편집 루프를 실행하는 것이 금지된 Depth-0 오케스트레이터 (GNU make) 역할을 엄격하게 수행합니다.
모든 무거운 단계(Target 2 고고학, Target 3 TDD, Target 4 식스-필러 비평가, Target 7a CI 분류)에 대해, 이는 자체 격리된 창에서 100k–220k 토큰을 흡수하고, 아티팩트를 디스크에 작성하며, 99_next_action.md를 업데이트하고, 15줄 요약을 반환한 후 종료(exit 0)하는 임시 Level-1 서브 에이전트를 포크합니다.
BlocSignal 이슈 #321 (PR #348, 11개 파일에 걸쳐 +916 / -92 라인)에서 자식 서브 에이전트들은 440,000개 이상의 토큰을 흡수했으며, Depth-0 오케스트레이터는 압축(compactions) 없이 196단계(53분) 만에 완료되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기