내가 왜 자신의 backlog.md를 읽는 것을 그만두었는지 (그리고 대신 무엇을 읽는지)
요약
개인 프로젝트 관리 시 마크다운 파일과 같은 정적 문서가 실제 데이터와 불일치하는 '캐시 드리프트' 문제를 다룹니다. 문서가 최신 상태를 유지하지 못하는 원인을 분석하고, 데이터의 신뢰성을 확보하기 위한 시스템적 접근법을 제안합니다.
핵심 포인트
- 정적 문서(backlog.md)는 업데이트 트리거가 없으면 실제 데이터와 불일치하는 캐시가 됨
- 데이터 유도 가능성이 있는 정보는 반드시 갱신 메커니즘(Refresher)을 포함해야 함
- 문서 기반의 요약보다 실제 파일 시스템과 원천 데이터를 직접 확인하는 것이 더 정확함
- 상태 보고서 작성 시 데이터의 성격(Live/Snapshot/Cache)을 명확히 정의할 필요가 있음
내 파일이 나에게 거짓말을 했던 그날 아침
5월 21일 수요일, 세션 시작, 키보드 옆에는 커피가 놓여 있습니다. 나는 에이전트(agent)에게 DEV.to 시리즈가 어떻게 진행되고 있는지 묻습니다. 깔끔하고 명확한 답변이 돌아옵니다. "4개의 기사가 대기 중이며, 발행 준비가 완료되었습니다." 나는 다시 읽어봅니다. 0.5초 정도 불안함이 느껴집니다. 왜냐하면 지난주에 그중 두세 개가 DEV.to에 올라간 것을 본 것 같지만, 그 사이에 잠을 자서 더 이상 확신할 수 없기 때문입니다. 나는 모든 것을 바꿔놓을 질문을 입력합니다. "정말로 발행할 기사가 남아 있는 것이 확실합니까?" 에이전트는 병렬로 DEV.to API를 다시 쿼리하고, scripts/devto/state.json을 열어 두 가지를 대조합니다. 그 네 개의 기사는 이미 2~3일 전에 발행된 상태였습니다.
내가 방금 읽은 것은 환각 (hallucination)이 아니었습니다. 에이전트는 기대했던 대로 정확히 수행했습니다. 즉, articles/backlog.md를 열고, 표를 읽고, 적혀 있는 내용을 그대로 돌려준 것입니다. 그 파일을 업데이트하는 것을 멈춘 것은 바로 나였습니다. sync-backlog.ts는 지난주 푸시 (push) 이후로 실행되지 않았습니다. 마크다운 (markdown) 파일에는 _"대기 중 (stand-by)"_라고 적혀 있었지만, 프로덕션 (production) 환경에서는 "발행됨 (published)" 상태였습니다. 타이피스트 (typist)는 거짓말을 하지 않았습니다. 그녀는 내가 직접 작성했고, 아무것도 유지 관리하지 않고 있음에도 불구하고 내가 권위 있는 정보로 취급했던 파일을 충실히 읽었을 뿐입니다.
요약은 갱신 장치가 없는 캐시 (Cache)와 같다
이것은 지속되는 개인 프로젝트에서 가장 흔히 발생하는 실패 모드입니다. 매일 두 가지 흐름이 생성됩니다. 한쪽에는 커밋 (commit), 배포 (deploy), 데이터베이스 (database)의 행, 상태 전환과 같이 움직이는 실체적인 데이터가 있습니다. 다른 한쪽에는 우리의 방향을 잡기 위해 초안을 작성하는 글들, 즉 backlog.md, 루트 디렉토리의 MEMORY.md, 일요일 밤의 세션 노트, 지난주에 리팩토링 (refactor)한 폴더의 README 등이 있습니다. 이러한 글들은 스프린트 (sprint)를 마무리하는 동작 속에서 빠르게 작성되지만, 파이프라인 (pipeline) 내에서 이를 종료시키는 트리거가 아무것도 없기 때문에 느리게 유지되거나 아예 유지되지 않습니다.
Counterpart Toolkit의 R6는 SQL 컬럼에 대해 _Live / Snapshot / Cache 필수 (mandatory)_라고 명시합니다. 다른 데이터로부터 유도 가능한 모든 컬럼은 생성하는 커밋(commit) 시점에 자신의 카테고리를 선언해야 합니다. 만약 그것이 Cache라면, 리프레셔 (refresher) 메커니즘 (GENERATED ALWAYS AS, SQL 트리거, 계획된 REFRESH가 포함된 materialized view)이 동일한 커밋에 함께 포함되어야 합니다. 카테고리가 선언되지 않으면, 커밋도 없습니다.
backlog.md도 정확히 동일한 논리적 객체입니다. 이것의 값은 state.json과 몇 가지 편집용 상수 (editorial constants)로부터 유도 가능합니다. sync-backlog.ts는 이것의 적용 트리거 (applicative trigger)입니다. 호출이 없다면, Cache는 드리프트 (drift)됩니다.
대신 내가 읽는 것
R2, 요약보다 파일 시스템 (Filesystem over summary),는 5월 15일 이후의 행동 양식을 성문화합니다. 어떤 상태 보고서(status report)를 보기 전에도, 다음 네 가지 셸 명령어를 이 순서대로 실행합니다. 마크다운 (markdown)은 가장 마지막에 오며, 이는 초안 형태의 사고 (draft thinking)로서 존재할 뿐, 결코 소스 (source)로 취급되지 않습니다.
git log --since='7d' --oneline
git status --porcelain
ls docs/adr/ | wc -l
...
결과는 3초 만에 읽힙니다. 만약 잊고 있었던 커밋이나, 기억보다 하나 더 많은 ADR이 발견되는 등 무언가 나를 놀라게 한다면, 나는 backlog.md가 아니라 그곳을 파헤칩니다. 내가 마크다운을 읽을 때는 _"누가, 언제 이것을 업데이트했는가"_라는 암묵적인 질문을 던지며, 만약 15초 이내에 git log를 통해 답이 나오지 않는다면, 나는 그것을 부패한 Cache로 취급합니다.
코다 (Coda)
언제, 어떤 메커니즘에 의해 생성되었는지 말해주지 않는 요약은 아무것도 말해주지 않는 것과 같습니다. 그것이 스크립트든, 트리거든, cron이든, 생성하는 커밋에 리프레셔 (refresher)를 선언하여 관리되는 Cache로 살아가게 하거나, 아니면 그것을 소스로 취급하는 것을 멈추고 다시 초안 (draft)으로 되돌리십시오. R6는 데이터베이스에 대한 규칙을 말합니다. R2는 당신이 스스로에게 쓰는 글들에 대해 동일한 규칙을 말합니다. git log를 보기 전에 backlog.md를 여는 에이전트 (agent)는 나쁜 에이전트가 아닙니다. 상류 (upstream)에서 금지되었어야 할 인간의 행동을 충실히 수행하는 에이전트일 뿐입니다. 5월 21일 아침, 나에게 거짓말을 한 것은 에이전트가 아니라, 전날 밤 노트를 닫지 않았던 바로 나 자신의 타이피스트 (typist)였습니다.
Counterpart Toolkit v0.7, 규칙 R2 — 요약보다 파일 시스템 (Filesystem over summary). v0.4.1의 R1에서 추출되었으며, 독자적인 지위를 부여받아 승격되었습니다. 툴킷의 현재 버전은 github.com/michelfaure/doctrine-counterpart 에 CC-BY-4.0 라이선스로 게시되어 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기