본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 15. 14:44

Claude Code에 장기 기억을 부여하는 4계층 아키텍처 — '매번 처음부터 설명하기'를 그만둔 이야기

요약

Claude Code의 세션 간 기억 상실 문제를 해결하기 위해 신선도와 목적에 따라 데이터를 4계층으로 분류하는 아키텍처를 제안합니다. 원천 로그부터 인간용 Wiki까지 일방향 흐름을 통해 데이터 오염을 방지하고 효율적인 문맥 유지를 구현합니다.

핵심 포인트

  • 데이터 성격에 따라 4개 계층(원천 로그, 휘발성 버퍼, 확정 사실, 인간용 Wiki)으로 분리
  • 하류 계층이 상류를 덮어쓰지 않는 일방향 데이터 흐름 원칙 준수
  • Stop hook을 활용하여 세션 종료 시 대화 로그를 Markdown으로 자동 변환
  • 도구 실행 결과(tool_result)를 제외하여 로그 데이터의 폭발적 증가 방지

Claude Code는 세션을 넘어가면 잊어버립니다. 새로운 세션을 열 때마다 프로젝트의 배경, 과거에 결정한 사항, 자신의 취향을 다시 설명해야 합니다. 이를 수개월 동안 지속한 결과, "기억을 하나의 메모에 전부 쓰는" 것이 아니라, 신선도와 독자에 따라 4계층으로 나누는 설계로 정착되었습니다.

이 기사에서는 해당 4계층 아키텍처의 설계, 구현, 그리고 운용하며 겪었던 함정(Pitfalls)에 대해 작성합니다. 마지막에 "오늘 30분 만에 따라 할 수 있는 최소 구성"을 남겨두었으니, 전부 읽지 않더라도 그 부분만 가져가셔도 충분합니다.

고민의 정체: 기억에는 종류가 있다

"Claude Code에 기억을 갖게 하고 싶다"라고 한마디로 말해도, 그 내용은 성질이 다른 4가지가 섞여 있습니다.

  • 실제로 무엇이 일어났는지에 대한 생(Raw) 로그 (변형되면 안 됨. 양이 많음)
  • 최근 며칠간의 작업 문맥 (Context) (금방 부패함. 다음 세션으로 이어가고 싶음)
  • 확정된 사실·취향·방침 (부패하지 않음. 매 세션 읽게 하고 싶음)
  • 인간인 내가 다시 읽는 정리된 지식 (LLM용 형식으로는 읽기 어려움)

이를 하나의 파일에 섞으면, 생 로그가 취향을 묻어버리고, 오래된 작업 메모가 현재의 판단을 오염시킵니다. 그래서 계층을 나누고, 계층마다 "작성해도 좋은 주체"를 하나로 고정했습니다.

설계: 4계층과 일방향 플로우

#계층실체역할작성자
1원천 로그~/knowledge-base/raw/conversations/모든 세션의 생 로그. 불변·추가 전용Stop hook 스크립트만
2휘발성 버퍼~/.remember/최근 작업의 기억. SessionStart에서 문맥으로 로드공식 remember 플러그인만
3확정 사실~/.claude/projects/<dir>/memory/확정된 프로필·방침·진행 중인 안건Claude가 의도적으로 작성
4인간용 WikiObsidian Vault내가 읽는 정리된 지식Claude가 ingest를 통해 작성

흐름은 일방향입니다.

원칙은 단 하나입니다. 하류는 상류를 덮어쓰지 않는다. 권위는 항상 계층(1)에 있으며, (2)(3)(4)는 거기서 파생된 것입니다. 불일치가 발생하면 (1)을 참조하여 수정합니다.

구현

계층(1): Stop hook으로 대화 로그를 Markdown화 하기

Claude Code는 세션의 전문을 ~/.claude/projects/ 하위에 JSONL로 남깁니다. 이를 Stop hook(세션 종료 시 발화하는 hook)을 통해 Markdown으로 변환하여, 추가 전용 디렉토리에 저장합니다.

{
"hooks": {
"Stop": [
...

변환 스크립트의 골자 (실물에서 요점만 발췌):

#!/usr/bin/env python3
"""Claude Code 대화 로그를 knowledge base용 Markdown으로 변환한다"""
import json
...

포인트는 두 가지입니다. tool_result (도구 실행 결과)는 버리는 것입니다 (양이 폭발하는 것에 비해 나중에 읽지 않음). 그리고 출력 파일명을 <프로젝트명>_<세션ID>.md로 하여, 나중에 grep으로 "그 작업 언제 했더라"를 검색할 수 있도록 하는 것입니다.

계층(2)(3): 다음 세션에 자동으로 문맥을 전달하기

계층(2)는 공식의 remember 플러그인에 맡기고 있습니다. 최근 작업이 now.md에 들어가고, 야간의 consolidate 과정에서 recent.mdarchive.md로 숙성되면서 중복이 제거되며, SessionStart에서 자동으로 문맥으로 로드됩니다.

계층(3)은 "확정된 사실만" 두는 장소입니다. MEMORY.md를 인덱스로 하여, 1토픽 1파일로 사실을 작성합니다. "이 프로젝트의 DB는 Turso이다", "위험한 조작은 실행 전에 확인을 받는다"와 같은, 부패하지 않는 정보만 여기에 넣습니다. 작업 로그를 섞지 않는 것이 요령입니다.

계층(4): 인간용 hot.md를 API 비용 제로로 자동 업데이트

Obsidian Vault 측의 hot.md에는 "최근 10개 세션의 표"가 자동으로 들어갑니다. 구조는 단순합니다. 계층(1)의 파일명과 일시 행을 정규 표현식으로 파싱하여, 마커로 둘러싸인 영역에 표를 주입할 뿐입니다. LLM을 호출하지 않으므로 비용은 제로입니다.

<!-- recent:start auto-updated by update_hot_recent.py -->
일시프로젝트첫 지시
...

운영하며 빠졌던 함정

함정 1: macOS의 TCC로 인해 launchd 작업이 조용히 종료됨

이것이 가장 큰 난관이었습니다. 야간 자동 작업을 launchd로 실행했을 때, ~/Documents 하위의 Vault에 대한 쓰기 작업만 조용히 실패했습니다. 에러조차 발생하지 않았습니다.

원인을 파악해 보니, launchd 환경에서도 bash의 쓰기는 통과되지만, claude 바이너리, git, python만 차단되었습니다. 원인은 macOS의 TCC(개인정보 보호)로, ~/Documents, ~/Desktop, ~/Downloads바이너리 단위의 전체 디스크 접근 권한(Full Disk Access, FDA)이 없으면 쓸 수 없는 영역이었기 때문입니다.

대책으로는 FDA를 일일이 부여하며 돌리는 것보다, 쓰기 대상을 보호 영역 밖으로 옮기는 것이 더 견고합니다(바이너리가 업데이트되거나 경로가 바뀌어도 유효하기 때문입니다). Vault의 실체를 ~/Documents 외부로 이전하고, 원래 위치에는 심볼릭 링크(symlink)를 생성했습니다.

함정 2: "recent가 2개 있다"는 점을 통합하고 싶어짐

계층(2)의 recent.md (LLM용)와 계층(4)의 hot.md (인간용)는 내용이 중복됩니다. 언뜻 보면 번거로워 보여 통합하고 싶어지지만, 읽는 사람이 다를 뿐 둘 다 계층(1)에서 유래한 것입니다. 어느 하나를 기준으로 삼고 다른 하나를 종속시키려 하면, 포맷 요구사항이 충돌하여 둘 다 사용하기 어려워집니다. 중복된 상태 그대로 두는 것이 정답이었습니다.

함정 3: 고장 난 것을 알아차릴 수 없음

자동 파이프라인은 조용히 멈춥니다. 조기 경고 신호를 정해두면 이를 포착할 수 있습니다.

  • now.md에 동일한 요약이 3회 이상 나열됨 → 통합(consolidate) 지연의 징후
  • 소스 로그의 인덱스가 24시간 이상 오래됨 → 변환 훅(conversion hook)이 실행되지 않았을 의심
  • hot.md의 마커 소실 → 표 주입 실패

저희 팀에서는 이를 하나의 헬스 체크(health check) 스크립트로 묶어, 모든 계층의 생존 여부를 명령어 하나로 확인할 수 있도록 구성했습니다.

오늘 30분 만에 따라 할 수 있는 최소 구성

4개 계층이 모두 필요하지는 않습니다. 계층(1)만으로도 효과가 있습니다.

  • ~/knowledge-base/raw/conversations/ 디렉토리를 만든다.
  • ~/.claude/projects/의 JSONL 파일에서 user/assistant 텍스트만 추출하여 Markdown으로 저장하는 스크립트를 작성한다 (위의 골자만으로 충분합니다. Claude Code에게 직접 작성하게 하는 것이 가장 빠릅니다).
  • settings.json의 Stop hook에 등록한다.

이것만으로도 "모든 세션이 grep 가능한 텍스트"가 됩니다. "지난주에 어떻게 고쳤더라?"라는 질문을 grep -r "레스폰시브" ~/knowledge-base/raw/로 찾아낼 수 있는 것은 상상 이상으로 강력합니다. 계층(2)~(4)는 해당 생 로그가 쌓여 불편함을 느낄 때 추가해도 늦지 않습니다.

요약

  • 기억은 양이 아니라 신선도와 읽는 이에 따라 계층을 나눈다.
  • 계층마다 쓰기 주체를 하나로 고정하고, 하류(downstream)는 상류(upstream)를 덮어쓰지 않는다.
  • launchd × ~/Documents는 TCC로 인해 조용히 죽는다. 쓰기 대상을 보호 영역 밖으로 옮겨라.
  • 우선은 Stop hook 하나를 이용한 "생 로그 계층"부터 시작하라.

이 환경에는 이 외에도 Claude가 스스로 스킬을 작성하며 성장하는 auto-skills 운영이나, 매일 아침 GitHub를 자동 순회하며 유용한 OSS를 수집하는 파이프라인이 탑재되어 있습니다. 후속편에서 다룰 예정이니, 관심이 있다면 팔로우해 주시면 감사하겠습니다.

Discussion

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0