Claude Code의 인계 메모가 3개월 만에 110KB로 부풀어 올라, PROGRESS.md / BACKLOG.md / auto
요약
Claude Code를 이용한 장기 프로젝트 진행 시, 인계 메모(PROGRESS.md)가 시간이 지나면서 과도하게 부풀어 오르는 문제를 해결하는 방법을 제시합니다. 정보의 수명에 따라 PROGRESS.md, BACKLOG.md, auto memory 세 가지 역할로 분리하고, '추가' 방식 대신 '덮어쓰기' 방식으로 관리하여 메모리를 효율적으로 유지할 것을 강조합니다.
핵심 포인트
- 인계 메모는 누적(Append)이 아닌 덮어쓰기(Overwrite) 원칙으로 사용해야 합니다.
- 정보의 수명에 따라 PROGRESS.md, BACKLOG.md, auto memory로 역할을 분리하세요.
- PROGRESS.md에는 '현재 위치'와 '다음 할 일' 등 핵심 정보만 간결하게 유지하는 것이 중요합니다.
- auto memory는 서브 에이전트에게 자동으로 로드되지 않으므로 별도 규칙 설정이 필요할 수 있습니다.
Claude Code는 세션마다 깨끗한 컨텍스트에서 시작합니다.
그래서 필자는 개인 개발의 육아 기록 앱을 만들면서 PROGRESS.md라는 인계 메모를 두고, '세션 시작 시 먼저 읽고, 끝난 후 업데이트한다'는 운영 방식을 하고 있었습니다.
그런데 3개월 후, 이 파일은 2.6KB → 약 110KB로 부풀어 올랐고, 같은 제목이 두 번 나오는 경우나 '이전 기록은 오류'라는 수정 사항이 몇 군데나 있는 상태가 되었습니다.
この記事では、부푼 원인과, PROGRESS.md / BACKLOG.md / auto memory 세 가지 역할에 나누어 약 6KB로 되돌린 방법을 소개합니다.
Claude Code로 수 주 이상 지속되는 프로젝트를 진행하는 분들에게 적합한 내용입니다.
- 인계 메모는 '추가' 방식으로 운영하면 반드시 부풀어 오릅니다. '덮어쓰기'하여 오래된 내용을 지우는 파일로 취급해야 합니다.
- 정보는 수명에 따라 분리합니다. 지금만의 정보 → PROGRESS.md / 할 일 및 완료 이력 → BACKLOG.md / 영구적인 학습 → auto memory
- 삭제한 경위는 git에 남아있으므로, 파일에는 '정리 전은
git show <hash>:PROGRESS.md'라고 적어두면 충분합니다. - 규칙은 '이력은 남기지 않는다'만으로는 지켜지지 않았습니다. 줄 수의 기준(150행)과 '어디로 옮길 것인지'까지 적는다고 하니 지켜지게 되었습니다.
- auto memory는 서브 에이전트에는 로드되지 않습니다. 구현을 서브 에이전트에 맡기려면, 지키고 싶은 규칙은 CLAUDE.md에도 작성해야 합니다.
| 항목 | 내용 |
|---|---|
| 툴 | Claude Code (CLI / 데스크톱 앱) |
| ... | |
| CLAUDE.md와 auto memory의 차이점 자체는 이전 기사에서 정리했습니다. |
도입 시(2026-06-24)의 CLAUDE.md에 추가된 내용은 이 정도였습니다.
## Session Memory (필독・업데이트 필수)
세션을 넘나드는 인계는 `PROGRESS.md`로 진행합니다.
- **세션 시작 시**: 먼저 `PROGRESS.md`를 읽고, 현재 위치・다음 행동・인수인계를 파악한 후에 작업을 시작합니다....
PROGRESS.md 본문의 서두에도 역할을 명확히 적었습니다.
> **이 파일의 역할**: 새로운 세션을 시작한 Claude가 '지금 어디까지 진행되었고, 다음으로 무엇을 해야 하는지'를 가장 짧게 파악하기 위한 인계 노트.
>
...
이때는 37행・2.6KB였습니다. '현재 위치', '다음 할 일', '인수인계', '환경 메모'의 네 가지 제목만 있었습니다.
git 이력에서 파일 크기를 추적하자, 다음과 같았습니다.
# 8커밋마다 PROGRESS.md의 바이트 수를 출력
for h in $(git log --format='%h' --reverse -- PROGRESS.md | awk 'NR%8==1'); do
printf "%s %s\n" "$(git log -1 --format=%ad --date=short "${h}")" \
...
| 날짜 | 크기 |
|---|---|
| 2026-06-24 (도입) | 2.6KB |
| ... | |
zsh에서 git show $h:PROGRESS.md라고 쓰면, :P가 zsh의 수정자로 해석되어 경로가 깨집니다. "${h}:PROGRESS.md"처럼 중괄호로 감싸주세요. |
113KB짜리 파일을 열어보니, 다음과 같은 상태였습니다.
- '현재 위치'가 과거 작업 로그가 되어 있었다
'최근 작업', '과거 작업'이라는 단락이 쌓이고, 한 줄이 1,000자를 넘는 목록도 있었습니다. - - 같은 제목이 두 번 있었다
## 다음 할 일
이 84행과 343행의 두 곳에 있어 어느 것이 최신인지 알 수 없는 상태였습니다. - - 오래된 기록에 대한 수정 사항이 몇 군데나 있었다
'본 섹션 후단에 'push 미실시'라고 기재했으나, 다음 세션에서 확인해 보니~', '과거의 '미 push' 기재는 오류'와 같은 수정 사항이 6군데 있었습니다. - - 환경 메모가 오래된 채로 남아 있었다
CI를 Vercel에서 GitHub Actions로 옮긴 후에도, 'push마다 Vercel의vercel-build가 CI로서 실행된다'는 기술이 남아있었습니다.
가장 문제라고 느낀 부분은 3번째와 4번째였습니다.
새로운 세션의 Claude는 오래된 기록과 수정 사항을 모두 읽고 '지금 어느 것이 맞는가'를 판단해야 합니다. 오래된 채 방치된 기록은 수정조차 되지 않았습니다. 인계용 파일이 오히려 오해의 원인이 되고 있었습니다.
규칙에는 처음부터 '히스토리는 남기지 않는다(흘러가면 지운다)'라고 적혀 있었습니다. 그럼에도 불구하고 부풀어 오른 이유는 되돌아보니 다음 두 가지라고 생각합니다.
- '업데이트한다'가 '추가한다'로 해석되었다
'작업을 마칠 때마다 현재 위치를 업데이트하라'고 지시하자, Claude는 이전 내용을 남겨둔 채 새로운 단락을 추가해 나갔습니다. 삭제해도 되는지 판단 기준이 없었기 때문입니다.
- 삭제된 정보의 행선지가 정해져 있지 않았다
완료된 작업의 경위는 '어딘가에 남기고 싶은' 정보입니다. 행선지가 없으니 PROGRESS.md에 계속 남아있었습니다.
즉, 단순히 '쓰지 마라'뿐만 아니라, '어디로 옮길 것인가'와 '어디까지 허용할 것인가' 가 필요했습니다.
정리 후에는 정보를 '얼마나 기간 동안 의미를 갖는지'에 따라 3가지로 나누었습니다.
| 계층 | 파일 | 내용 | 수명 | 매 세션 읽을지 |
|---|---|---|---|---|
| ① 현재 | PROGRESS.md | 현재 위치・다음 행동・미해결 걸림돌・환경 메모 | 며칠 (정리되면 삭제) | 읽음 (CLAUDE.md에서 필독 지정) |
| ② 대장 | BACKLOG.md | 할 일 목록(우선순위 순) 및 완료 기록 | 프로젝트 기간 내내 | 필요할 때만 |
| ③ 학습 | auto memory | 실패로부터 얻은 교훈・설계 판단・사용자 선호도 | 영구 | 인덱스(MEMORY.md )만 자동 로드됨 |
여기에 더해, '왜 그렇게 했는지'에 대한 세부 경위는 git의 커밋 메시지 에 맡겼습니다. BACKLOG의 완료 행에는 커밋 해시를 적어두고, 자세히 알고 싶을 때는 git show 로 추적할 수 있게 했습니다.
실제로 작성하는 상황에서는 다음 순서로 판단합니다.
그 정보는…
├─ 다음 세션이 '바로' 작동하기 위해 필요한가? ──→ PROGRESS.md
│ (미커밋 작업・다음 행동・미해결 결함・일시적 제약)
...
정리 후 도입부에는 부풀지 않기 위한 규칙을 두 줄 추가했습니다.
> **비대화시키기**: 완료된 작업의 경위는 BACKLOG.md의 완료 행(+git log)으로 옮기고,
> 여기부터는 삭제한다. 기준 150행 이내.
> (2026-09-23에 110KB → 정리. 정리 전 전문은 `git show <hash>:PROGRESS.md` 에서 참조 가능)
핵심 포인트는 세 가지입니다.
- 이전 위치를 명시한다:「삭제」가 아니라 「BACKLOG의 완료 행으로 옮긴 후 삭제」라고 작성합니다. 삭제에 대한 저항감이 사라집니다. - 숫자로 상한을 정한다:「비대화시키기」만으로는 기준이 되지 않습니다. 150행이라는 숫자가 있으면, 업데이트할 때마다 '초과하지 않았는지'를 확인할 기준이 됩니다. - 정리 전 위치를 적어둔다: git에 남아있으므로 삭제해도 손실되지 않습니다. 그것을 파일에 적어두면, 사용자(글쓴이)도 안심하고 삭제 판단을 할 수 있습니다.
구성 자체는 도입 시와 동일한 4개의 제목 구조를 유지합니다.
최종 업데이트: 2026-09-26
## 현재 위치
- 직근에 끝난 작업을 몇 줄. 자세한 내용은 'BACKLOG.md 완료 행' 링크로 대체
...
정리 후 3일간(2026-09-23~26)은 55행 → 68행으로, 기준인 150행을 크게 밑도는 상태를 유지하고 있습니다.
BACKLOG.md는 위쪽의 '할 일 목록'과 아래쪽의 '완료된 반복(iteration)' 표로 구성됩니다.
## 백로그 (우선순위 순)
- [ ] #93 공개 전에 비기능 요구사항을 확정하기 (착수 조건: 공개를 결정했을 때)
- [ ] #98 ~ (착수 조건: 측정값이 ○○보다 낮으면)
...
이것은 대장이므로, 늘어나는 것이 전제입니다(2026년 9월 말 기준으로 약 84KB).
CLAUDE.md에서 필독으로 지정한 것은 PROGRESS.md 뿐이기 때문에, BACKLOG.md는 필요할 때 Claude가 해당 부분을 읽으러 가는 형태로 만들었습니다.
'착수 조건'을 적어두는 것도 추천합니다. '측정값이 나쁘면 할 것', '공개를 결정하면 할 것' 같은 조건부 항목은 PROGRESS.md에 '언젠가 할 것'으로 남겨둘 필요가 없습니다.
auto memory는 Claude가 직접 작성하는 메모로, ~/.claude/projects/<프로젝트>/memory/에 저장됩니다. 공식 문서에 따르면, 인덱스인 MEMORY.md는 맨 앞 200줄 또는 25KB까지 매 세션마다 자동으로 로드되며, 개별 파일은 필요할 때 읽어가는 구조입니다.
이 프로젝트에서는 약 3개월 동안 20개 정도가 쌓였습니다. 예를 들면 다음과 같습니다.
---
name: pipe-swallows-exit-codes
description: lint/test/build의 출력을 tail/grep에 파이프하면 exit code가 무너지고, && 체인이 실패를 건너뛰게 함
...
PROGRESS.md와의 경계는 **'그 작업이 끝난 후에도 다음 다른 작업을 하는 데 도움이 되는가'**입니다.
- '〇〇의 마이그레이션(migration)이 미적용됨' → 적용하면 필요 없어짐 →
PROGRESS.md에 기록 - '새로운 테이블에는 GRANT를 명시하지 않으면 42501 에러가 발생함' → 다음에 테이블을 만들 때도 필요함 → auto memory에 기록
이렇게 분리해 두면, 교훈은 인덱스에서 한 줄로 가져올 수 있고, PROGRESS.md는 '현재' 정보만 유지할 수 있습니다.
정리(整理)와 같은 커밋으로, '데이터 양이 계속 늘어날 것을 전제로 설계한다'라는 방침을 CLAUDE.md에 추가했습니다.
이 방침은 auto memory에도 저장되어 있었습니다. 그럼에도 불구하고 CLAUDE.md에 작성한 것은, 커밋 메시지에 나와 있듯이 '서브 에이전트(sub-agent)에게도 적용하기 위해서'입니다.
공식 문서에는 메인 대화의 auto memory는 서브 에이전트가 읽지 않는다고 적혀 있습니다 (대화를 그대로 이어받는 fork는 예외).
필자의 프로젝트에서는 구현을 feature-dev라는 서브 에이전트에게 맡기고 있습니다.
auto memory에만 작성한 방침은, 구현하는 서브 에이전트에게 전달되지 않습니다. 그래서 보관 장소를 다음과 같이 분리하고 있습니다.
| 정보의 종류 | 보관 장소 |
|---|---|
| 구현할 때 반드시 지키게 하고 싶은 규칙 (예: 새로운 테이블에는 GRANT를 명시하기) | CLAUDE.md (요점만) + auto memory (이유/경위) |
| 메인 대화에서 판단에 사용하는 학습 내용・사용자 선호도 | auto memory만 |
정리를 부탁할 때는, '완료된 작업의 경위는 BACKLOG의 완료 줄과 git log에 있으니 지워도 좋다'와 같은 근거를 함께 전달하는 것이 좋습니다.
BACKLOG에 완료 줄이 없는 작업은, 지우기 전에 BACKLOG로 옮기도록 지시하면 경위가 사라지지 않습니다.
오래된 기술이 잘못되었다는 것을 알게 되었을 때, '〜라고 썼지만 오류'와 같이 추가하면 둘 다 남습니다.
PROGRESS.md는 이력이 아니므로, 원래 줄을 수정하는 것이 정답입니다. 경위가 중요하다면, 그것은 커밋 메시지에 작성합니다.
PROGRESS.md를 수정한 112개의 커밋 중, 49개는 PROGRESS.md와 BACKLOG.md만 수정한 커밋이었습니다.
커밋 메시지에 '해시(hash)'나 '장부 업데이트'가 포함된 것만 해도 24개가 있습니다.
원인은, BACKLOG의 완료 줄에 그 작업 자체의 커밋 해시를 쓰려고 했기 때문입니다.
해시는 커밋한 후에야 결정됩니다. 그래서 '구현 커밋 → 해시를 작성하는 커밋'의 2단계로 나뉘어 있었습니다.
작성을 잊어버려서, (이 세션에서 커밋 예정) 상태로 남아있는 완료 줄도 지금도 존재합니다.
대책은 다음 두 가지 중 하나라고 생각합니다.
- 완료 줄에는 해시를 쓰지 않고,
**커밋 메시지에 BACKLOG의 번호 (예:#97)를 넣는git log --grep='#97'로 찾을 수 있게 하거나 - 해시를 쓸 거라면,
다음 작업 커밋에 합치는 것. 해시를 쓰기 위한 전용 커밋은 만들지 않는 것입니다.
공식 문서에서는 CLAUDE.md는 1파일당 200줄 미만을 기준으로 합니다. 길어질수록 컨텍스트(context)를 소모하고, 지시가 잘 지켜지지 않게 되기 때문입니다.
PROGRESS.md의 운영 규칙을 CLAUDE.md에 추가할 때도, 상세 내용은 PROGRESS.md 시작 부분에 두고, CLAUDE.md에는 '먼저 읽고・끝나면 업데이트한다'는 몇 줄만 남깁니다.
- 인계 메모는 '추가'로 운영하면 부풀어 오르고, 오래된 기록과 수정 사항이 섞여 오해의 소지가 생깁니다.
- 정보를 수명에 따라 분리합니다:
현재 → PROGRESS.md / 대장(台帳) → BACKLOG.md / 교훈 → auto memory / 경위 → git - 규칙에는 '쓰지 마라'뿐만 아니라, **이전할 위치와 숫자 상한선(150줄)**을 명시해야 합니다. - 삭제된 내용은 git에 있으므로, 정리 전 참조 방법을 파일에 한 줄 적어두면 안심하고 지울 수 있습니다.
- auto memory는 서브 에이전트가 접근하지 못합니다. 구현 시 지키게 하고 싶은 규칙은 CLAUDE.md에도 작성해야 합니다.
- 향후 과제: BACKLOG.md의 완료 기록도 계속 늘어나고 있습니다(약 84KB). 언젠가는 오래된 완료 기록을 별도의 파일로 분리할 필요가 있어 보입니다.
같은 프로젝트에서 Claude Code를 반나절 자율 운영했을 때의 운영 노하우는 여기에 정리했습니다.
긴 세션 내에서의 컨텍스트 대응(Compaction)에 대해서는 여기 기사도 참고해 주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기