본문 바로가기
C.W.K.
Stream
Lesson 02 of 04 · published

모든 인덱스는 파생 미러

~11 min · derived-mirror, purge-replay, frontmatter, jsonl-echo

Level 0식은 초고
0 XP0/44 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"인덱스가 파일과 어긋나면 틀린 건 인덱스야. 지우고 파일에서 다시 채워. 맞춰보겠다고 patch 하지 말고."

인덱스는 파생이지 절대 master 가 아냐

Rekindle 도 진짜 데이터베이스를 키워. 노트 인덱스와 전문 검색(corpus 쪽은 Lantern 의 몫). 그런데 그중에 진실인 건 하나도 없어. 전부 마크다운 파일의 파생 미러 라서, 내용을 통째로 버리고 디스크에서 다시 지어도 잃는 게 없거든. 이 지위는 나중에 알게 되는 게 아니라 처음부터 정해놓는 거야. 인덱스는 파일이 이미 하고 있는 말을 빠르게 꺼내 쓰는 캐시일 뿐이야.

지우고 다시 채워, diff 해서 patch 하지 말고

이걸 정직하게 지켜주는 게 복구 규칙이야. 인덱스와 파일이 어긋났을 때, 밖에서 파일을 고쳤거나 쓰는 도중에 크래시가 났거나 버그가 있었거나 간에, 답이 '차이를 알아내서 인덱스를 맞춰 patch 하자' 가 되면 안 돼. 파생된 행을 전부 지우고 파일에서 다시 채우는 것이 답이야. 부패가 자라는 자리가 정확히 그 diff 해서 patch 하는 화해 로직이거든. patch 는 하나하나가 무슨 일이 있었는지에 대한 작은 추측이고, 추측은 쌓여. 다시 짓는 데는 추측이 한 톨도 안 들어가고.

// 복구는 언제나 이 모양이야. 화해시키는 일은 없어.
fn rebuild_index(vault: &Path) -> Result<(), Error> {
    purge_index()?;                       // 파생된 행을 전부 버려
    for file in markdown_files(vault) {   // 진실에서 다시 채워
        index_note(&read_to_string(&file)?)?;
    }
    Ok(())
}

cwkPippa 의 규율을 도메인 하나 옆으로 옮겨 온 거야. 거기선 JSONL 로그가 진실이고 SQLite 와 벡터 저장소는 지우고 다시 채워서 만드는 파생 미러지. 여기선 마크다운 파일이 진실이고 모든 인덱스가 미러고. 같은 규칙에 같은 이유야. 권위는 하나, 파생물은 다시 지을 수 있게, 화해 로직은 어디에도 두지 않기.

뜻은 frontmatter 에 살아

이 규칙은 메타데이터까지 이어지는데, 선을 하나 조심해서 그어야 해. 문서가 뜻하는 것, 그러니까 제목과 태그와 날짜는 데이터베이스가 아니라 파일의 frontmatter 에 살아. 태그가 DB 에만 있으면 그 DB 가 두 번째 master 가 돼버려. 잃어버리면 진짜 데이터를 잃는 거니까. 그러면 파일이 정본이라는 주장 자체가 반쪽짜리가 되고. 반면 앱이 노트에 대해 기억하는 것, 그러니까 핀이나 잠금이나 워크플로 레인은 종류가 다른 물건이야. v4 는 그걸 일부러 라이브러리 옆의 작고 성긴 사이드카 파일에 둬(위의 메모가 그 얘기야). 사이드카를 잃어도 문서는 하나도 안 다치고, 앱이 그걸 어떻게 정리해뒀는지만 사라져. 어느 쪽이든 인덱스는 원래 있어야 할 자리에 남아. 파일이 이미 담고 있는 걸 빠르게 보여주는, 버려도 되는 뷰로.

Code

복구는 지우고 다시 채우기. diff 해서 patch 하는 일은 없어·rust
// 인덱스가 디스크와 어긋나면 틀린 건 인덱스야. 다시 지어.
fn rebuild_index(vault: &Path) -> Result<(), Error> {
    purge_index()?;                        // 파생된 행을 전부 버려
    for file in markdown_files(vault) {    // 진실에서 다시 채워
        index_note(&std::fs::read_to_string(&file)?)?;
    }
    Ok(())
}

// reconcile_index() 를 일부러 안 만들었어. diff 도 patch 도,
// '뭐가 바뀌었는지 알아내서 고치기' 도 없어. patch 는 하나하나가 추측이고
// 추측은 부패로 쌓이거든. 다시 짓는 데는 추측이 안 들어가고.
뜻은 파일을 타고 가고, 인덱스는 버려도 돼·markdown
---
title: The Rekindling
tags: [editor, cm6, architecture]
date: 2026-07-16
---

파일이 자기가 뜻하는 걸 지니고 있어. 인덱스를 잃어도 잃는 건 없고
이 파일들에서 다시 지으면 돼. 반면 태그를 쥐고 있는 DB 를 잃으면
진짜 데이터를 잃는 거야. 그게 바로 두 번째 master 라는 뜻이지.
(핀이나 워크플로 레인 같은 앱 전용 상태는 성긴 사이드카에 따로 살아.
그걸 잃으면 정리가 사라질 뿐, 문서는 절대 안 잃어.)

External links

Exercise

캐시나 인덱스를 쓰는 시스템을 하나 떠올려서 다시 짓기 질문을 던져봐. 통째로 지우고 권위 있는 원천에서 데이터 손실 없이 다시 만들 수 있어? 못 하겠으면 정확히 뭘 잃게 되는지 적어봐. 그 목록이 네 '캐시' 가 몰래 소유하고 있던 데이터고, 그것 때문에 그게 두 번째 master 인 거야. 그다음 그 데이터가 원래 어디 있어야 하는지 정해.
Hint
흔한 범인은 캐시 안에 숨은, 사용자가 정한 필드야. 태그, 정렬 순서, '마지막으로 본 시각', 커스텀 라벨 같은 것. 캐시에만 있으면 그건 캐시가 아니야. 하나씩 갈라봐. 문서가 뜻하는 건 권위 있는 산물로, 여기선 frontmatter 로 옮기고, 앱이 그냥 기억하는 건 이름표를 분명히 단 작은 앱 상태 파일로 옮겨. 어느 쪽이든 그래야 인덱스가 진짜로 버려도 되는 물건이 돼.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.