결론부터 말하면, 클로드 코드(Claude Code)의 메모리 시스템은 소스코드를 분석해보니 파일 기반 영속 저장소 + 백그라운드 추출 에이전트 + Sonnet 기반 관련성 검색 세 축으로 돌아가는 구조였습니다. 대화가 끝날 때마다 포크된 서브에이전트가 기억할 만한 내용을 자동으로 뽑아 파일로 저장하고, 다음 대화에서 Sonnet이 관련 기억만 골라서 시스템 프롬프트에 주입합니다.
목차
- 메모리는 어디에 저장되나요?
- 기억은 어떤 종류가 있나요?
- 대화 끝나면 기억을 어떻게 뽑아내나요?
- MEMORY.md 인덱스는 왜 200줄로 제한하나요?
- 다음 대화에서 기억은 어떻게 불러오나요?
- 메모리 추출 에이전트는 뭘 할 수 있나요?
- 정리
- 관련글
메모리는 어디에 저장되나요?
별도 DB가 아닙니다. ~/.claude/projects/<프로젝트>/memory/ 디렉토리에 마크다운 파일로 저장됩니다.
// src/memdir/paths.ts
export const getAutoMemPath = memoize(
(): string => {
const override = getAutoMemPathOverride() ?? getAutoMemPathSetting()
if (override) {
return override
}
const projectsDir = join(getMemoryBaseDir(), 'projects')
return (
join(projectsDir, sanitizePath(getAutoMemBase()), AUTO_MEM_DIRNAME) + sep
).normalize('NFC')
},
() => getProjectRoot(),
)
Git 워크트리가 여러 개여도 canonical root를 찾아서 하나의 메모리 디렉토리를 공유합니다. 프로젝트별로 격리되니까 A 프로젝트 기억이 B 프로젝트에 섞이는 일은 없어요.
기억은 어떤 종류가 있나요?
4가지 타입으로 분류됩니다. 코드에서 파생 가능한 정보(패턴, 아키텍처, git 히스토리)는 의도적으로 제외합니다.
// src/memdir/memoryTypes.ts
export const MEMORY_TYPES = [
'user', // 사용자 역할, 선호도
'feedback', // 교정/확인 내역
'project', // 프로젝트 맥락 (코드 외)
'reference', // 외부 시스템 참조
] as const
특히 feedback 타입이 인상적입니다. "그렇게 하지 마" 같은 교정뿐 아니라, "그래 그게 맞아" 같은 확인도 저장합니다. 교정만 기억하면 점점 소극적이 되니까, 성공 패턴도 함께 기억하는 설계입니다.
대화 끝나면 기억을 어떻게 뽑아내나요?
핵심은 extractMemories.ts에 있습니다. 대화의 매 턴이 끝날 때 포크된 에이전트가 백그라운드로 돌면서 기억을 추출합니다.
// src/services/extractMemories/extractMemories.ts
const result = await runForkedAgent({
promptMessages: [createUserMessage({ content: userPrompt })],
cacheSafeParams,
canUseTool,
querySource: 'extract_memories',
forkLabel: 'extract_memories',
skipTranscript: true,
maxTurns: 5,
})
runForkedAgent는 메인 대화의 완벽한 복제본입니다. 프롬프트 캐시를 공유하기 때문에 추가 비용이 적고, maxTurns: 5로 제한해서 토끼굴에 빠지는 걸 방지합니다. 메인 에이전트가 이미 메모리를 직접 작성한 경우엔 hasMemoryWritesSince()로 감지해서 추출을 건너뜁니다.
MEMORY.md 인덱스는 왜 200줄로 제한하나요?
MEMORY.md는 매 대화마다 시스템 프롬프트에 통째로 로드됩니다. 무한정 커지면 토큰 낭비가 심해지니까 이중 캡을 겁니다.
// src/memdir/memdir.ts
export const MAX_ENTRYPOINT_LINES = 200
export const MAX_ENTRYPOINT_BYTES = 25_000
200줄 또는 25KB 중 먼저 도달하는 쪽에서 잘립니다. 바이트 캡은 한 줄이 비정상적으로 긴 경우를 잡기 위한 안전장치입니다. 초과하면 경고 메시지가 자동으로 붙어서 "인덱스를 정리하라"고 알려줍니다.
다음 대화에서 기억은 어떻게 불러오나요?
모든 기억을 다 불러오진 않습니다. Sonnet이 사용자 질문과 메모리 목록을 보고 관련 있는 최대 5개만 골라냅니다.
// src/memdir/findRelevantMemories.ts
const result = await sideQuery({
model: getDefaultSonnetModel(),
system: SELECT_MEMORIES_SYSTEM_PROMPT,
messages: [{
role: 'user',
content: `Query: ${query}\n\nAvailable memories:\n${manifest}${toolsSection}`,
}],
max_tokens: 256,
output_format: { type: 'json_schema', /* ... */ },
signal,
querySource: 'memdir_relevance',
})
sideQuery로 Sonnet에게 물어봅니다. 재미있는 건, 최근 사용한 도구 목록도 같이 전달한다는 점입니다. 이미 쓰고 있는 도구의 레퍼런스 문서를 또 불러오는 건 낭비니까요. 다만 해당 도구의 주의사항이나 알려진 이슈는 여전히 불러옵니다.

메모리 추출 에이전트는 뭘 할 수 있나요?
보안 측면에서 꽤 빡빡하게 제한합니다. 읽기 도구(Read, Grep, Glob)는 자유롭게 쓸 수 있지만, 쓰기는 메모리 디렉토리 안에서만 가능합니다. Bash도 읽기 전용 명령어만 허용됩니다.
// src/services/extractMemories/extractMemories.ts
if (tool.name === BASH_TOOL_NAME) {
const parsed = tool.inputSchema.safeParse(input)
if (parsed.success && tool.isReadOnly(parsed.data)) {
return { behavior: 'allow' as const, updatedInput: input }
}
return denyAutoMemTool(tool, 'Only read-only shell commands...')
}
서브에이전트가 실수로 코드를 수정하거나 시스템에 영향을 주는 걸 원천 차단하는 구조입니다. MCP 도구도 전부 차단됩니다.
정리
- 저장:
~/.claude/projects/<프로젝트>/memory/에 마크다운 파일로 저장, 프로젝트별 격리 - 4가지 타입: user(사용자), feedback(교정/확인), project(맥락), reference(외부 참조)
- 자동 추출: 매 턴 종료 시 포크된 서브에이전트가 백그라운드로 기억 추출 (최대 5턴)
- 선택적 리콜: Sonnet이 질문 관련성을 판단해 최대 5개 기억만 시스템 프롬프트에 주입
- 이중 보호: MEMORY.md 인덱스는 200줄/25KB 캡, 추출 에이전트는 메모리 디렉토리 밖 쓰기 차단
관련글
- Claude Code 동적 프롬프트 분석: 매번 다르게 말하는 비밀 — 메모리도 동적 프롬프트에 주입됩니다
- Claude Code 시스템 프롬프트 분석: 915줄은 어떻게 조립되는가 — 메모리 프롬프트가 시스템 프롬프트에 합류하는 지점
'AI 코딩 에이전트' 카테고리의 다른 글
| Claude Code IDE 브릿지 분석: VS Code 안에서 동작하는 원리 (해부학 Part 14) (0) | 2026.04.02 |
|---|---|
| Claude Code 터미널 UI 분석: React로 터미널 앱을 만든다고? (해부학 Part 13) (0) | 2026.04.02 |
| Claude Code MCP 구현 분석: AI의 USB 포트를 직접 만들어봤다 (해부학 Part 11) (0) | 2026.04.02 |
| Claude Code 권한 시스템 분석: rm -rf를 못 치게 막는 법 (해부학 Part 10) (0) | 2026.04.01 |
| Claude Code 멀티에이전트 분석: AI가 AI를 부리는 구조 (해부학 Part 9) (0) | 2026.04.01 |
