Claude Code 소스 유출이 드러낸 아키텍처 — 3편: 메모리와 컨텍스트 압축
들어가며
2편에서 에이전틱 루프가 max_iterations: usize::MAX로 사실상 무한 반복한다는 것을 확인했습니다. 그런데 여기서 현실적인 문제가 생깁니다 — 컨텍스트 윈도우는 유한하다는 것입니다.
모델이 파일을 읽고, 코드를 분석하고, 도구 결과를 받을 때마다 대화 히스토리는 점점 커집니다. 한 시간 정도 복잡한 작업을 하면 수십만 토큰이 쌓입니다. 컨텍스트 한계에 도달하면 에이전트는 더 이상 작동할 수 없습니다.
Claude Code는 이 문제를 네 가지 전략으로 해결합니다. 4계층 메모리 시스템, 자동 컨텍스트 압축, 자기 치유 메모리, 그리고 도구의 지연 로딩입니다.
4계층 메모리 시스템
아키텍처 분석에서 드러난 가장 흥미로운 설계 중 하나는 메모리가 단일 시스템이 아니라 4개의 계층으로 구성되어 있다는 점입니다.
| 계층 | 범위 | 저장 위치 | 수명 |
|---|---|---|---|
| CLAUDE.md | 프로젝트 | 프로젝트 루트 파일 | 영구 (사용자 관리) |
| memdir | 세션 간 | .claude/ 디렉토리 | 영구 (자동 정리) |
| SessionMemory | 세션 내 | 세션 파일 | 세션 종료 시 소멸 |
| agentMemory | 에이전트 | 에이전트 스코프 | 에이전트 종료 시 소멸 |
1계층: CLAUDE.md — 프로젝트 지침서
가장 상위에 위치하는 메모리입니다. 2편에서 다뤘듯이, 부트스트랩 4단계에서 로딩되어 시스템 프롬프트에 직접 주입됩니다.
CLAUDE.md의 특별한 점은 사용자가 직접 관리하는 유일한 메모리 계층이라는 것입니다. 다른 세 계층은 시스템이 자동으로 관리하지만, CLAUDE.md는 사용자가 내용을 작성하고 수정합니다. 이것은 일종의 "헌법"과 같은 역할을 합니다 — 에이전트의 모든 행동이 이 문서의 지침을 따릅니다.
Rust 포트의 config.rs에서는 CLAUDE.md 외에도 .claude.json 설정 파일을 함께 로딩합니다. 두 파일이 합쳐져서 프로젝트 수준의 컨텍스트를 형성합니다.
2계층: memdir — 자기 치유 메모리
원본의 memdir/ 서브시스템(8개 모듈)이 이 계층을 담당합니다.
memdir/
├── findRelevantMemories.ts # 관련 메모리 검색
├── memdir.ts # 메모리 디렉토리 관리
├── memoryAge.ts # 메모리 유효기간/자동 정리
├── memoryScan.ts # 메모리 스캔
├── memoryTypes.ts # 메모리 타입 정의
├── paths.ts # 경로 관리
├── teamMemPaths.ts # 팀 메모리 경로
└── teamMemPrompts.ts # 팀 메모리 프롬프트
memdir은 .claude/ 디렉토리에 파일로 저장되는 메모리입니다. 새 세션이 시작될 때 memoryScan.ts가 저장된 메모리를 스캔하고, findRelevantMemories.ts가 현재 컨텍스트와 관련된 메모리를 선별하여 시스템 프롬프트에 주입합니다.
"자기 치유"라는 이름이 붙은 이유는 memoryAge.ts 때문입니다. 이 모듈이 오래된 메모리를 자동으로 정리합니다. 메모리에는 유효기간이 있고, 시간이 지나면 자동으로 제거되거나 갱신됩니다. 단순히 쌓이기만 하는 것이 아니라 스스로 정리하고 갱신하는 메모리인 것입니다.
teamMemPaths.ts와 teamMemPrompts.ts의 존재도 주목할 만합니다. 팀 메모리라는 개념이 있다는 것은, 여러 에이전트가 공유 메모리를 통해 협업할 수 있는 구조가 설계되어 있다는 뜻입니다.
3계층: SessionMemory — 세션 내 기억
원본의 services/SessionMemory/에 위치한 모듈입니다.
services/SessionMemory/
├── sessionMemory.ts # 세션 내 메모리 관리
└── sessionMemoryUtils.ts # 유틸리티
SessionMemory는 현재 대화 세션 내에서만 유효한 메모리입니다. 대화가 진행되면서 누적되는 컨텍스트를 관리하며, 세션이 종료되면 소멸합니다.
다만 Python 포트의 session_store.py에서 볼 수 있듯이, 세션 자체는 JSON 파일로 영속화할 수 있습니다. Claude Code에서 /resume 명령으로 이전 대화를 이어갈 수 있는 것이 이 메커니즘 덕분입니다. 세션 데이터가 파일로 저장되어 있으면, 새 프로세스에서 이를 복원하여 대화를 계속할 수 있습니다.
4계층: agentMemory — 에이전트별 독립 기억
원본의 tools/AgentTool/ 하위에 위치합니다.
tools/AgentTool/
├── agentMemory.ts # 에이전트 메모리
└── agentMemorySnapshot.ts # 메모리 스냅샷
서브에이전트가 생성될 때 독립적인 메모리 공간이 할당됩니다. 메인 에이전트와 서브에이전트는 서로의 메모리에 직접 접근하지 않습니다. agentMemorySnapshot.ts는 에이전트가 종료될 때 메모리 상태를 스냅샷으로 남기는 역할을 하는 것으로 보입니다 — 서브에이전트의 작업 결과를 메인 에이전트에게 전달하는 메커니즘인 것입니다.
4계층의 상호작용
┌────────────────────────────────────────────────┐
│ CLAUDE.md (프로젝트 지침) │
│ ┌──────────────────────────────────────────┐ │
│ │ memdir (세션 간 기억) │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ SessionMemory (세션 내 기억) │ │ │
│ │ │ ┌─────────────────────────────┐ │ │ │
│ │ │ │ agentMemory (에이전트 기억) │ │ │ │
│ │ │ └─────────────────────────────┘ │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
바깥 계층일수록 수명이 길고 범위가 넓습니다. CLAUDE.md는 프로젝트가 존재하는 한 유지되고, memdir은 세션이 바뀌어도 유지되며, SessionMemory는 세션 내에서만, agentMemory는 에이전트 생명주기 내에서만 유효합니다.
이 계층 구조의 설계 원칙은 "적절한 범위에 적절한 수명의 기억을"입니다. 프로젝트 규칙은 영구적으로, 이전 대화에서 배운 것은 세션 간에, 현재 작업 컨텍스트는 세션 내에, 특정 에이전트의 작업 상태는 에이전트 내에 저장됩니다.
컨텍스트 압축 — 200K 토큰의 벽을 넘는 법
4계층 메모리가 "무엇을 기억할 것인가"의 문제를 다룬다면, 컨텍스트 압축은 "기억이 너무 많아지면 어떻게 할 것인가"의 문제를 다룹니다.
Rust 포트의 compact.rs에서 이 메커니즘이 상세하게 구현되어 있습니다.
압축 트리거 조건
압축 설정:
- 자동 트리거 임계값: 200,000 입력 토큰
- 보존할 최근 메시지 수: 4개
- 요약 토큰 한도: 10,000 토큰
입력 토큰이 200K를 초과하면 자동으로 압축이 시작됩니다. 이때 최근 4개 메시지는 보존하고, 나머지를 요약합니다.
압축 알고리즘의 단계
요약에 포함되는 정보는 단순한 텍스트 축약이 아닙니다. 구조화된 분석이 이루어집니다.
압축 시 추출/보존하는 정보:
1. 대화 범위 통계
- user / assistant / tool 메시지 수
2. 사용된 도구 목록
- 어떤 도구가 몇 번 호출되었는지
3. 최근 사용자 요청 3개
- 가장 최근의 의도를 보존
4. 보류 중인 작업 감지
- "TODO", "next", "pending", "remaining" 키워드 스캔
- 미완료 작업이 요약에서 누락되지 않도록
5. 참조된 핵심 파일
- 확장자 기반 추출 (.ts, .tsx, .py 등)
- 어떤 파일을 다루고 있었는지 보존
6. 현재 작업 컨텍스트
- 전체적으로 무엇을 하고 있었는지
7. 타임라인
- role: content 형식의 축약된 대화 흐름
4번 항목이 특히 인상적입니다. "TODO", "next", "pending", "remaining" 같은 키워드를 스캔해서 미완료 작업을 찾습니다. 압축 후에도 "아직 안 한 일"이 사라지지 않도록 하는 안전장치입니다.
압축 후 컨텍스트 복원
압축된 요약은 XML 태그 구조(<summary>, <analysis>)로 포맷되어 System 역할 메시지로 주입됩니다. 이때 함께 전달되는 연속성 메시지가 있습니다.
"This session is being continued from a previous conversation
that ran out of context. The summary below covers the earlier
portion of the conversation.
Continue the conversation from where it left off without
asking the user any further questions.
Resume directly — do not acknowledge the summary,
do not recap what was happening."
마지막 두 줄이 핵심입니다 — "요약을 인지하지 말고, 무엇을 하고 있었는지 요약하지 말고, 바로 이어서 진행하라." 사용자 입장에서는 압축이 일어났다는 사실을 거의 느끼지 못하도록 설계된 것입니다.
실제로 Claude Code를 장시간 사용하다 보면 "The conversation was automatically compacted" 같은 메시지를 가끔 볼 수 있습니다. 그 순간이 바로 이 알고리즘이 동작한 시점입니다. 그리고 그 이후에도 에이전트가 이전 맥락을 잘 기억하고 있는 것처럼 느껴지는 것은, 이 구조화된 요약 덕분입니다.
번들드 스킬 "remember" — 명시적 기억 요청
자동 메모리 관리 외에, 사용자가 명시적으로 "이것을 기억해"라고 요청할 수 있는 메커니즘도 있습니다. 번들드 스킬 17개 중 하나인 remember가 이 역할을 합니다.
원본의 번들드 스킬 목록:
batch, claudeApi, debug, keybindings, loop, loremIpsum,
remember, scheduleRemoteAgents, simplify, skillify,
stuck, updateConfig, verify, ...
remember 스킬은 사용자의 "이것을 기억해"라는 요청을 처리하여 memdir에 영속적인 메모리 파일을 생성합니다. 이것이 제가 사용하고 있는 auto memory 시스템의 기반인 것입니다.
stuck이라는 스킬도 눈에 띕니다 — 에이전트가 막혔을 때 자동으로 다른 접근법을 시도하는 "자가 복구" 메커니즘으로 추정됩니다.
지연 로딩 — 도구 스키마의 토큰 최적화
메모리 관리의 또 다른 축은 시스템 프롬프트의 크기를 줄이는 것입니다. 2편에서 도구 스키마가 시스템 프롬프트에 포함된다고 했는데, 184개 도구의 전체 JSON Schema를 매번 보내면 어마어마한 토큰이 소비됩니다.
Python 포트의 DeferredInit
지연 초기화 결과:
- trusted: boolean → 신뢰 검증 통과 여부
- plugin_init: boolean → 플러그인 초기화 여부
- skill_init: boolean → 스킬 초기화 여부
- mcp_prefetch: boolean → MCP 프리페치 여부
- session_hooks: boolean → 세션 훅 등록 여부
부트스트랩의 신뢰 게이트를 통과한 후에야 플러그인, 스킬, MCP, 훅이 초기화됩니다. 이것 자체가 "필요할 때만 로드"하는 지연 로딩 패턴입니다.
ToolSearch의 역할
도구 레벨에서는 ToolSearchTool이 지연 로딩의 진입점입니다. 동작 방식을 정리하면 다음과 같습니다.
도구 로딩 전략:
1. 항상 로드 (primitive)
→ Read, Write, Edit, Bash, Glob, Grep, Agent, WebSearch, WebFetch
→ 시스템 프롬프트에 전체 스키마 포함
2. 조건부 로드 (MCP)
→ 연결된 MCP 서버의 도구만 로드
→ 서버 연결/해제 시 동적 추가/제거
3. 필요 시 로드 (deferred)
→ ToolSearch로 검색 후 활성화
→ 사용자가 요청하기 전까지 스키마 미포함
→ 결과: 매 API 호출의 시스템 프롬프트 크기 최소화
→ 토큰 절약 + API 응답 속도 향상
이 설계를 이해하고 나면, 이전에 메모리에 기록해둔 "MCP 도구는 로드만으로 매 메시지 시스템 프롬프트에 풀 스키마 포함 → 토큰 소비"라는 관찰이 정확했다는 것을 확인할 수 있습니다. MCP 서버를 많이 연결할수록 primitive 도구처럼 항상 로드되는 스키마가 늘어나고, 매 턴마다 소비되는 토큰이 증가하는 것입니다.
트랜스크립트 관리 — 대화의 기록
Python 포트의 transcript.py에서 TranscriptStore라는 모듈이 대화 기록의 관리를 담당합니다. 이 모듈의 핵심 기능은 compact — 즉, 대화 기록을 압축하는 것입니다.
TranscriptStore는 앞서 살펴본 컨텍스트 압축과 연결됩니다. 대화 기록이 일정 크기를 초과하면 compact를 수행하여 오래된 부분을 요약으로 대체합니다.
원본의 history.ts(루트 레벨)는 HistoryLog라는 이벤트 로깅 시스템을 제공합니다. TranscriptStore가 "대화 내용"을 관리한다면, HistoryLog는 "무슨 일이 일어났는지"를 기록합니다 — 도구 호출, 오류, 성능 메트릭 등의 이벤트입니다.
프리페치 — 부팅 시간 최적화
Python 포트의 prefetch.py에서 부팅 시 사전 로딩하는 항목들이 드러납니다.
프리페치 항목:
1. MDM (Mobile Device Management) 정책 읽기
2. 키체인 프리페치
3. 프로젝트 디렉토리 스캔
MDM 정책 읽기가 첫 번째라는 것이 흥미롭습니다. 기업 환경에서 MDM으로 관리되는 기기에 Claude Code가 설치된 경우, 기업의 보안 정책을 먼저 확인하겠다는 것입니다. 이것은 Claude Code가 개인 개발자뿐 아니라 기업 환경도 타겟으로 하고 있다는 것을 시사합니다.
키체인 프리페치는 인증 토큰이나 API 키를 시스템 키체인에서 미리 로드하는 과정입니다. 프로젝트 디렉토리 스캔은 현재 작업 디렉토리의 구조를 파악하여 컨텍스트를 구성하는 과정입니다.
3편을 마치며 — 기억의 아키텍처
Claude Code의 메모리 시스템을 살펴보면, AI 에이전트 설계에서 "기억"이 얼마나 복잡한 문제인지를 실감하게 됩니다.
단순히 "대화 내용을 저장한다"가 아닙니다. 무엇을 기억할지(4계층 분리), 얼마나 오래 기억할지(memoryAge), 기억이 넘치면 어떻게 할지(compact), 언제 기억을 불러올지(findRelevantMemories), 누구의 기억인지(agentMemory vs teamMemory) — 이 모든 차원을 고려한 설계입니다.
특히 인상적이었던 것은 압축 알고리즘이 "TODO" 키워드를 스캔하여 미완료 작업을 보존한다는 점입니다. 컨텍스트가 압축되더라도 "아직 해야 할 일"은 사라지지 않습니다. 이런 세심한 설계가 Claude Code를 장시간 작업에서도 신뢰할 수 있게 만드는 것이 아닐까 생각합니다.
다음 편에서는 Claude Code의 세 번째 축인 연결과 확장을 다룹니다. 31개 모듈로 구성된 Bridge 아키텍처, 5종 트랜스포트를 지원하는 MCP 통합 레이어, 그리고 6개 빌트인 에이전트의 멀티 에이전트 오케스트레이션을 살펴보겠습니다.
시리즈 안내
1편: 512,000줄의 전체 조감도
2편: 에이전틱 루프 — 도구, 권한, 훅의 삼중주
3편: 메모리와 컨텍스트 — 잊지 않는 AI의 비밀 (현재 글)
4편: Bridge, MCP, 멀티 에이전트 — 단순 CLI를 넘어서
관련 글
Claude Code 소스 유출이 드러낸 아키텍처 — 2편: 에이전틱 루프, 도구, 권한의 삼중주
Claude Code의 심장은 ConversationRuntime의 무한 에이전틱 루프입니다. 184개 도구를 손과 발로, 5단계 권한 모델을 안전장치로, Hook 시스템을 감시자로 — 이 세 가지가 어떻게 맞물려 자율 에이전트를 구현하는지 살펴봅니다.
Claude Code 소스 유출이 드러낸 아키텍처 — 1편: 512,000줄의 전체 조감도
2026년 3월 31일, npm 패키징 실수로 Claude Code의 TypeScript 소스 512,000줄이 유출되었습니다. 1,902개 파일, 34개 서브시스템, 207개 커맨드, 184개 도구 — 이 숫자들이 말해주는 AI 코딩 에이전트의 내부 구조를 조감도로 살펴봅니다.
Claude Code 소스 유출이 드러낸 아키텍처 — 4편: Bridge, MCP, 멀티 에이전트
Claude Code는 단독 CLI가 아닙니다. 31개 모듈의 Bridge가 IDE와 연결하고, 5종 트랜스포트의 MCP가 외부 도구를 통합하고, 6개 빌트인 에이전트가 팀으로 협업합니다. 마지막 편에서는 이 '연결의 아키텍처'를 살펴봅니다.