C.W.K.
Stream
Lesson 02 of 04 · published

레지스트리가 그 '한 곳'

~12 min · registry, manifest, idempotent, content-hash

Level 0불 꺼진 심지
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"모으기는 폴더가 아냐. 목록이야 — 그리고 그 목록이 트릭 전부야."

manifest 가 지도야

흩어진 네 글이 전부 찾아지는 '한 곳' 은 디렉토리가 아냐 — 작고, git 으로 추적되는 manifest 야. 각 항목이 코퍼스를 선언해: id, 파일이 이미 사는 root, 어느 파일이 카운트되는지 정하는 glob, 쓸 chunking profile. 그게 다야. manifest 는 주소를 쥐지 내용을 쥐지 않아. 10년 치 '모인' 코퍼스 전체를 한 페이지에 인쇄될 파일 하나로 읽을 수 있어.

순회

등록은 가리키고, 수집은 순회해. 코퍼스의 선언된 root 와 glob 이 주어지면, 엔진은 매칭되는 모든 파일을 발견하고, 읽고, 바이트를 doc_sha256 으로 해시하고, 텍스트를 chunk 하고, 그 chunk 를 인덱스에 써. 문서 자체의 id 는 코퍼스와 경로에서 content-addressed 라, 같은 파일은 항상 같은 슬롯에 내려앉아. 아무것도 제자리 밖으로 복사 안 돼. 순회는 mover 가 아니라 reader 야.

Idempotent 재수집 — 이걸 살 만하게 만드는 저렴함

재수집은 계속 돌려도 안전해, idempotent 하니까. 엔진은 각 파일을 해시해서 지난번 색인한 것과 비교해. 안 바뀐 해시? 건너뛰어 — 문자 그대로 할 게 없어. 바뀐 해시? 그 문서의 전체 chunk 세트를 하나의 원자적 트랜잭션으로 교체해: 옛 chunk 전부 삭제, 새 chunk 전부 삽입, 반쯤-패치된 중간 상태는 절대 없이. 이래서 '코퍼스를 신선하게 유지' 가 거의 공짜야: 실제로 바뀐 것만 일을 해.

인덱스 변형의 최소 단위는 문서 통째야. 문서의 chunk 를 조각조각 패치하지 마. 파일의 한 바이트가 바뀌면, 그 chunk 를 전부 날리고 함께 재구축해. 원자적 문서-통째 교체는 인덱스가 부분 업데이트 상태에 걸리지 않게 해 — 쿼리는 옛 문서를 보거나 새 문서를 보지, 둘의 프랑켄슈타인은 절대 안 봐.

가용성은 그냥 필드야

기계마다 다른 파일을 쥐어 — 랩탑은 일부만, 어떤 워크스테이션은 전부. 그 현실엔 특별한 배관이 필요 없어. manifest 항목의 필드야. 등록기는 선언된 root 가 현재 기계에 없는 코퍼스를 그냥 건너뛰고 있는 걸 색인해. 전부 가진 기계가 canonical 인덱스가 되고, 나머지는 할 수 있는 걸 색인해. 지도는 네가 선 곳에서 영토가 어떻게 보이는지 알아.

Code

해시, 비교, 건너뛰거나-재구축 — idempotent 순회·python
import hashlib
from pathlib import Path

def reindex(corpus) -> dict:
    stats = {"unchanged": 0, "reindexed": 0}
    for path in discover(corpus.roots, corpus.include_globs, corpus.exclude_globs):
        raw = Path(path).read_bytes()
        doc_sha = hashlib.sha256(raw).hexdigest()

        if doc_sha == last_indexed_sha(corpus.id, path):
            stats["unchanged"] += 1          # same bytes — nothing to do
            continue

        # Changed (or new): replace the WHOLE chunk set atomically.
        with transaction():
            delete_chunks(corpus.id, path)
            for seq, ch in enumerate(chunk(raw.decode("utf-8"), corpus.profile)):
                insert_chunk(corpus.id, path, seq, ch)
        stats["reindexed"] += 1
    return stats  # cheap to run on every save — only real changes cost work

External links

Exercise

네 글을 위한 manifest 를 종이에 써봐. 그게 사는 각 곳마다 id, root 경로, 어느 파일이 카운트되는지의 glob(예: *.md 만, 초안 제외) 을 줘. 전체가 얼마나 작은지 봐. 그다음 물어: 파일 저장할 때마다 이 위에 색인기를 다시 돌린다면, 뭐가 그걸 계속 돌릴 만큼 저렴하게 만들까?
Hint
답은 content 해시야: '안 바뀜' 을 파일 다시 읽고 다시 처리하지 않고 감지할 수 있으면, 둘 바뀐 천 개 문서 재색인이 천 개가 아니라 둘의 일만 들어.

Progress

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

댓글 0

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

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