본문 바로가기

Coding, Testing, Challenge

Claude Code가 세션마다 다 잊어버린다, 사업 9개를 돌리며 기억 서버를 붙인 이유

혼자서 사업 9개를 돌리는데 기억이 문제였습니다

AI 에이전트에게 일을 맡기다 보면 같은 설명을 몇 번이고 다시 하게 됩니다.

어제 정한 규칙도, 지난주에 밟은 함정도 새 대화창을 열면 처음 듣는 이야기가 되기 때문입니다.

저는 미니앱, 블로그, 제휴 채널, 소설, 제안서까지 흐름 9개를 혼자 굴리고 있어서 이 문제가 유난히 크게 다가왔습니다.

이번 포스팅에서는 흩어진 기억을 서버 한 곳에 모으게 된 경위와, 그 과정에서 틀렸던 대목을 순서대로 풀어 보도록 하겠습니다.

세션을 닫으면 AI는 전부 잊습니다

Claude Code 같은 도구에서는 대화 하나가 곧 기억의 전부입니다.

창을 닫으면 그 안에서 합의한 것도 함께 닫힙니다.

게다가 저는 한 자리에서만 일하지 않습니다. PC가 여러 대이고, 도구도 Claude Code와 Codex, 메모용 Obsidian을 오갑니다.

한 기기에서 정한 것을 다른 기기의 AI는 알 길이 없었습니다.

처음에는 메모리 파일로 버텼습니다. 세션이 열릴 때마다 자동으로 딸려 오는 목차 파일입니다.

그런데 이 파일에는 24KB라는 한도가 있어서, 흐름이 늘수록 한 줄 요약으로 욱여넣는 일이 점점 빠듯해졌습니다.

그리고 그 파일은 그 PC 한 대에만 있습니다.

모아 보니 대화 35건, 12,425턴이었습니다

9월 18일, 8월 2일부터 쌓인 대화를 한곳으로 옮겼습니다.

세션이 35건, 주고받은 턴이 12,425번, 그 안에서 불려 나간 서브에이전트가 199개였습니다.

결정과 함정은 이 대화들 어딘가에 다 들어 있었지만, 제가 다시 꺼내 볼 방법은 없었습니다.

원본 기록 파일은 801MB였습니다.

그대로 옮기지 않고 사람과 AI가 나눈 말만 남겼더니 본문이 5.8MB로 줄었습니다.

도구 호출과 그 결과, 붙여넣은 이미지, 시스템 안내문을 버렸기 때문입니다.

나중에 다시 읽을 때 필요한 건 무엇을 왜 정했는지였고, 명령이 쏟아낸 출력은 거의 쓸 일이 없었습니다.

원본 파일은 지우지 않고 제자리에 둡니다. 정제본이 모자라면 원본에서 다시 만들면 되기 때문입니다.

⚠️ 대화 기록을 서버로 옮기실 계획이라면 비밀값부터 가리셔야 합니다. 터미널에 친 비밀번호가 기록에 그대로 남아 있었고, 가린 것만 144건이었습니다. 가려서 올려도 로컬 원본 파일에는 그대로 있다는 점도 함께 기억해 두셔야 합니다.

기억은 개인 VPS 한 대에 두기로 했습니다

이 저장소를 Hub라고 부르고, 9월 12일에 만들기 시작했습니다.

개인 VPS 한 대에 PostgreSQL을 올렸고, 비용은 월 $12입니다.

처음 정한 원칙은 하나였습니다. 무엇이든 정본은 한 곳에만 둔다는 것입니다.

일감과 결정, 실행 기록 같은 상태는 DB가 정본이고, 코드와 에이전트 정의는 git이 정본입니다. Obsidian은 보기만 하는 창으로 남겼습니다.

같은 내용을 두 군데서 고치면 어느 쪽이 맞는지 매번 다시 따져야 하기 때문입니다.

DB는 매일 마크다운으로 덤프해서 git에 커밋합니다.

알아 둘 것은 사실, 결정, 교훈, 문제, 참고자료 다섯 종류로 나눴습니다. 이 가운데 결정과 사실은 사람이 승인해야 확정됩니다.

AI가 추측한 내용이 확정된 사실처럼 굳어 버리면 곤란하기 때문입니다.

코드는 끝나 있었는데 비밀번호 칸 한 줄이 막고 있었습니다

처음 세운 일정은 4주짜리였습니다.

서버 준비와 코드는 9월 15일에 이미 끝나 있었는데, 가동은 그 뒤로 미뤄졌습니다.

설정 파일의 DB 접속 비밀번호 칸에 자리만 잡아 둔 CHANGE_ME 가 그대로 들어 있었기 때문입니다.

그 한 칸을 채우자 9월 18일에 전부 통과했습니다.

코드가 끝났다는 것과 돌아간다는 것 사이에 설정 한 줄이 끼어 있었던 셈입니다.

세션이 끝나는 순간에는 AI가 없습니다

대화를 한 번 옮긴 걸로 끝나면 다음 날부터 다시 쌓입니다. 세션을 닫을 때마다 알아서 올라가야 했습니다.

처음 떠올린 건 CLAUDE.md에 "끝날 때 올려 달라"고 적는 방법이었는데, 이건 성립하지 않았습니다.

CLAUDE.md는 모델에게 주는 지침이라 따를 수도, 안 따를 수도 있습니다.

더 큰 문제는 세션이 끝나는 시점에는 그 지침을 읽을 모델이 이미 없다는 점입니다.

세션 종료는 모델이 아니라 하네스 쪽에서 일어나는 사건이라, 그 순간 반드시 도는 건 SessionEnd 훅뿐입니다.

훅은 전역 설정에 한 번 걸어 두면 어느 프로젝트에서 열든 적용됩니다.

끝날 때마다 대화 본문과 실행 기록 한 건이 올라가고, 같은 세션이 두 번 끝나도 한 행만 남습니다.

실패하면 로그 파일에 적어 두고, 세션은 막지 않습니다. 종료 시점에 뜨는 오류는 사람이 볼 수 없기 때문입니다.

여기서 제가 한 번 헛다리를 짚었습니다.

시험 삼아 훅을 돌렸는데 아무것도 올라가지 않아서, 훅이 고장 났다고 두 번이나 판단했습니다.

단계별로 다시 돌려 보니 훅은 전부 통과였습니다.

틀린 건 시험하는 쪽이었습니다. 셸이 JSON 안의 역슬래시와 경로를 망가뜨려 훅에는 빈 {} 가 들어갔고, 훅은 설계대로 조용히 넘어간 것입니다.

그 뒤로는 시험 데이터를 셸 echo 대신 파이썬 json.dumps 로 만듭니다.

"허브에 저장" 한마디면 서버로 갑니다

세션이 끝날 때까지 기다리지 않고 바로 올리고 싶은 것도 있습니다. 방금 알아낸 함정 같은 것입니다.

이쪽은 CLAUDE.md로 됩니다. 세션 중에는 모델이 살아 있기 때문입니다.

전역 CLAUDE.md에 "허브에 저장", "서버에 저장", "허브에 올려"를 신호로 적어 두었고, 이 말을 들으면 에이전트가 아래 명령을 부릅니다.

org knowledge add "<내용>" --auto --type LESSON

--auto 는 지금 열려 있는 폴더를 보고 어느 프로젝트에 넣을지 정합니다. 제가 매번 고르지 않아도 되게 하려는 것입니다.

결정에 해당하는 내용은 제안까지만 올라가고, 승인은 사람만 합니다.

올린 지식은 대시보드의 "올린 지식" 카드에 보이게 했습니다. 올렸는데 화면에 안 보이면 올렸다는 사실 자체를 모르고 지나가기 때문입니다.

"기억해"는 종전대로 그 PC의 메모리 파일로 갑니다. 말마다 가는 곳이 다른 이유는 다른 편에서 따로 풀어 보겠습니다.

기억을 붙잡으려고 제가 정한 것

1. 대화창을 기억 장소로 쓰지 않습니다. 닫히면 사라지는 곳이기 때문입니다.

2. 정본은 한 곳에만 둡니다. 상태는 DB, 코드는 git입니다.

3. 기록을 옮길 때는 대화만 남기고, 비밀값은 가린 뒤에 올립니다.

4. 반드시 돌아야 하는 일은 지침이 아니라 훅에 겁니다.

5. 훅이 조용하면 훅보다 시험하는 쪽을 먼저 의심합니다.

9개를 굴리면서 가장 먼저 바닥난 건 제 기억력이었습니다.

일손은 AI가 얼마든지 빌려 줬지만, 어제 한 일을 오늘로 이어 주는 장치는 제가 따로 만들어야 했습니다.

혹시 AI와 여러 프로젝트를 오가고 계시다면, 이번 주에 같은 설명을 몇 번 반복하셨는지부터 세어 보시는 건 어떨까요?

그러면 오늘도 모두 스테이블 하세요.


만든 것들