노트 앱이 아니라 컨텍스트 인프라 — LLM 위키와 세컨드 브레인 구축 완전 정리

2026-07-31 · 약 84분
LLM위키Obsidian세컨드브레인제텔카스텐PARARAG에이전트메모리MCP지식관리디지털가든
세컨드 브레인은 "메모를 꾸준히 하는 법"이 아니라 컨텍스트 인프라 설계 문제다. 노트 2,000개를 통째로 물리면 회당 입력 비용만 약 $4지만 MOC 3장으로 라우팅하면 $0.1~0.2 — 40배 차이가 폴더가 아니라 진입점 설계에서 난다. Karpathy의 llm-wiki 패턴(raw/wiki/규약파일 3계층)과 PARA·제텔카스텐이 실제로 무너지는 지점, Obsidian의 2026년 가격·Bases·동기화 함정, 플러그인 경로 vs Claude Code/MCP 경로, ripgrep→하이브리드→GraphRAG의 손익분기, 에이전트가 쓴 노트의 환각이 지식베이스에 고착되는 걸 막는 법, 직군별 볼트 트리, 그리고 30일 구축 플레이북과 실패 6종까지 — 13개 섹션과 65개 Q&A로 정리했다.

LLM 위키란 무엇인가

LLM 위키를 "사람이 읽는 문서 더미"가 아니라 "LLM이 1급 독자이자 필자인 마크다운 지식베이스"로 정의하고, 노션·구글독스와의 근본 차이를 결정론적 검색 가능성에서 찾은 뒤, 사람용 위키·에이전트 컨텍스트 소스·에이전트 기억 저장소라는 세 용도의 요구사항이 어떻게 갈리는지를 실패 모드 중심으로 정리한 섹션입니다.

핵심 요점

  • LLM 위키의 정의는 '3계층(raw/wiki/규약파일) + 3연산(ingest/query/lint)'이며, 핵심은 wiki/ 디렉터리의 소유권이 사람이 아니라 에이전트에게 있다는 소유권 역전이다.
  • 노션·구글독스 대비 근본 차이는 AI 기능이 아니라 결정론적 검색 가능성 — rg/git diff/wikilink는 재현 가능하고 디버깅 가능하지만 벤더 랭킹과 블록 API는 그렇지 않다.
  • 지금 가능해진 이유 네 가지: 1M 컨텍스트(Opus 5/Sonnet 5, 40만 단어 볼트 전체 로드 시 약 2.5~3달러·캐싱 시 1/10), 로컬 파일 접근, MCP 2026-07-28 리비전과 1만+ 서버, 파일 기반 에이전트 메모리(memory_20250818)와 AGENTS.md(6만+ 저장소).
  • 사람용 위키·에이전트 컨텍스트 소스·에이전트 기억 저장소는 파일 크기·명명·frontmatter·쓰기 권한 요구사항이 정면으로 갈리므로 같은 파일을 공유시키면 안 되고, 에이전트 기억을 컨텍스트 소스로 자동 승격해서도 안 된다.
  • 실패 모드가 먼저다: 주장 노후화, 모순 누적(2~3주마다 30~45분 lint 필요), [[wikilink]]의 의미 부재, 동시 쓰기 레이스 — frontmatter의 confidence/supersedes 필드로 기계적 점검 가능하게 만들어야 한다.
  • 볼트를 노트 앱이 아니라 컨텍스트 인프라로 보면 성공 지표가 '노트 개수'가 아니라 '다음 세션에서 다시 설명하지 않아도 되는 비율'로 바뀐다.

LLM 위키란 무엇인가

한 줄 정의: LLM 위키는 사람이 읽을 것을 전제로 쓰인 문서 더미가 아니라, LLM이 1급 독자이자 1급 필자인 마크다운 지식베이스다. Karpathy가 2026년 4월 공개한 llm-wiki gist가 이 패턴에 이름을 붙였고, 구조는 뜻밖에 단순하다 — 3계층(불변 원본 raw/, LLM이 소유하는 wiki/, 규약을 담은 CLAUDE.md/AGENTS.md)과 3연산(ingest / query / lint).

llm-wiki/
├── CLAUDE.md      # 스키마·명명규칙·워크플로 (에이전트가 매 세션 읽음)
├── index.md       # 전 페이지 1줄 요약 카탈로그, ingest마다 갱신
├── log.md         # append-only. `## [2026-07-31] ingest | 문서제목`
├── raw/           # 사람이 넣는 원본. LLM은 읽기만, 수정 금지
└── wiki/          # LLM이 소유. entity/concept 페이지 + 상호참조

핵심 역전은 소유권이다. raw/는 사람이, wiki/는 에이전트가 소유한다. 소스 하나를 ingest하면 10~15개 페이지가 함께 갱신되는 것이 정상 동작이다.

먼저, 부러지는 지점

장점보다 실패 모드를 먼저 봐야 한다. 커뮤니티 재구현 보고에서 반복되는 것들:

  • 주장의 노후화(staleness). "현재 가격은 X"가 6개월 뒤에도 그대로 남는다. 오래된 파일을 크론으로 지우는 건 해법이 아니다 — 여전히 유효한지 판단하는 에이전트가 필요하다.
  • 모순 누적. 소스 수백 건을 넘기면 append-only ingest가 무너지고 충돌하는 문장이 조용히 공존한다. 2~3주마다 30~45분의 lint(모순 점검·용어 정규화·고아 페이지 정리)를 실제로 돌려야 한다.
  • [[위키링크]]는 의미를 담지 못한다. A가 B를 지지하는지 반박하는지 대체하는지 링크만으로는 알 수 없다. frontmatter에 supersedes:/contradicts: 같은 관계 필드를 직접 만들어야 한다.
  • 동시 쓰기 = 레이스. 파일시스템에 트랜잭션은 없다. 두 에이전트가 같은 페이지를 고치면 마지막 쓰기가 이긴다. 실무 대응은 git 커밋 단위 직렬화이거나 에이전트별 쓰기 디렉터리 분리다.

노션·구글독스와 근본적으로 무엇이 다른가

차이는 "AI 기능 유무"가 아니다. 결정론적 검색 가능성이다.

노션 / 구글독스 / Confluence 마크다운 볼트
접근 API·OAuth·레이트리밋 open() / rg
검색 벤더의 블랙박스 랭킹 rg -l "term" --glob '*.md' — 같은 입력, 같은 결과
변경 추적 벤더 버전 히스토리 git diff, 라인 단위
링크 내부 URL(깨짐) [[wikilink]] — 텍스트로 파싱 가능
에이전트 쓰기 블록 API 왕복 Edit 툴 문자열 치환 1회

에이전트에게 중요한 건 아래 두 줄이다. 노션에서 "이 문단만 고쳐"를 시키려면 블록 트리를 순회해야 하지만, 마크다운은 old_string → new_string 한 번이다. 그리고 grep은 결정론적이라 실패를 디버깅할 수 있다 — 임베딩 검색이 문서를 놓쳤을 때는 왜 놓쳤는지 알 방법이 없다.

왜 하필 지금인가

네 가지가 동시에 맞물렸다.

  1. 컨텍스트 윈도우. Claude Opus 5 / Sonnet 5 모두 1M 토큰이 기본이다. Karpathy 볼트가 도달했다고 알려진 약 40만 단어(≈50만~55만 토큰)도 통째로 들어간다 — 다만 Opus 5 입력 $5/MTok 기준 한 번 전체를 읽히는 데 약 2.5~3달러다. 프롬프트 캐싱(캐시 읽기 ≈0.1×)이 이걸 30센트대로 낮춘다. 한글은 토큰 효율이 나빠 같은 분량에서 더 든다.
  2. 로컬 파일 접근. Claude Code에서 볼트 폴더를 그냥 열면 끝이다. 인덱싱 파이프라인도 벡터DB도 없다.
  3. MCP. 2026-07-28 리비전이 스펙 사상 최대 개정(stateless 코어, 헤더 라우팅, 캐시 가능한 list 결과, 인가 강화)으로 나왔고 거버넌스는 Linux Foundation Agentic AI Foundation으로 이관됐다. 공개 서버는 1만 개 이상. Obsidian 쪽 선택지는 obsidian-local-rest-api(127.0.0.1:27124) + mcp-obsidian, MCP Tools 플러그인, Vault as MCP 등이다(개별 구현의 최신 스펙 호환성은 확인 필요).
  4. 에이전트 메모리가 곧 파일. Anthropic 메모리 툴(memory_20250818)은 /memories 디렉터리에 대한 view/create/str_replace/insert/delete/rename이 전부다 — 즉 클라이언트가 구현하는 마크다운 CRUD이며 컨텍스트 에디팅과 짝으로 쓴다. 규약 파일도 굳었다: AGENTS.md는 6만 개 이상 저장소가 채택했고 Codex·Cursor·Copilot·Gemini CLI·Zed 등이 네이티브로 읽는다.

세 가지 용도는 같은 파일을 쓰지 않는다

대부분의 볼트가 여기서 망가진다. (a) 사람이 읽는 위키, (b) 에이전트가 읽는 컨텍스트 소스, (c) 에이전트가 쓰는 기억 저장소는 요구사항이 정면으로 갈린다.

(a) 사람용 위키 (b) 에이전트 컨텍스트 (c) 에이전트 기억
최적화 대상 가독성·서사 토큰 효율·청크 경계 쓰기 지연·충돌 회피
파일 크기 길어도 됨 300~800단어로 분할 1주제 1파일
파일명 사람이 읽는 제목 결정론적 slug 타임스탬프+scope
frontmatter 최소 필수(필터 키) 필수(출처·신뢰도)
쓰기 권한 사람 없음(읽기 전용) 에이전트
실패 신호 아무도 안 읽음 검색은 되는데 오답 낡은 기억을 사실로 인용

(b)용 frontmatter 최소 세트:

---
type: concept
scope: fleet/ingest
updated: 2026-07-31
confidence: verified          # verified | reported | assumed
source: raw/2026-07-20-lightsail-deploy.md
supersedes: wiki/deploy-ecs.md
---

confidence는 에이전트가 추측을 사실로 승격시키는 걸 막고, supersedes는 lint가 모순을 기계적으로 찾게 한다. Obsidian Bases(1.9부터 코어 플러그인)를 쓰면 이 frontmatter를 그대로 테이블/카드 뷰로 띄울 수 있고, .base 파일 자체가 filters/formulas/properties/views 키를 가진 평범한 YAML이라 에이전트가 직접 생성·수정할 수 있다.

실무 규칙 하나: (c)를 (b)로 자동 승격시키지 마라. 에이전트 기억은 초안이고, 사람 승인을 거쳐야 컨텍스트 소스가 된다. 그리고 어떤 경우에도 API 키·토큰을 메모리 파일에 쓰지 않는다 — 기억은 이후 모든 세션에 그대로 재생된다.

노트 앱이 아니라 컨텍스트 인프라

판단 기준은 이렇게 잡는다.

  • 도입할 가치가 있나 → 같은 배경 설명을 세 번 이상 프롬프트에 붙여넣었다면 예.
  • 임베딩을 붙일까 → 파일 500개 미만이면 rg + index.md로 충분하다. 넘어가면 Smart Connections(로컬 임베딩, nomic-embed-text/mxbai-embed-large, API 키 불필요)를 grep의 대체가 아니라 보완으로 얹는다.
  • 비용 → Obsidian 코어는 무료, Sync $4/user/월(연납), Publish $8/사이트/월. 상업적 사용 라이선스 조건은 2026년 들어 변경된 정황이 있어 확인 필요.
  • 보안 → 볼트에 웹 클리핑을 넣는 순간 raw/는 신뢰 경계 밖이다. 쓰기 권한을 가진 에이전트에게 미검증 raw/를 통째로 물리면 프롬프트 인젝션 경로가 열린다.

볼트를 "노트 앱"으로 보면 정리 강박만 남는다. 컨텍스트 인프라로 보면 CI가 코드 저장소에 하는 일을 볼트가 프롬프트에 한다고 이해하게 된다. 성공 지표는 노트 개수가 아니라 다음 세션에서 다시 설명하지 않아도 되는 것의 비율이다.

세컨드 브레인 방법론 지형도

PARA·CODE·Zettelkasten·LYT/MOC·Evergreen·Johnny.Decimal·GTD를 "무엇을 잘하고 어디서 무너지는가" 중심으로 정리하고, LLM 시대에 분류의 가치가 떨어지고 연결·맥락의 가치가 오르는 이유, 그럼에도 에이전트의 탐색 경로·토큰 예산·프롬프트 캐시 때문에 구조가 필요한 이유를 실측 수치와 함께 다룬 섹션. 마지막에 방법론 선택 의사결정 기준표를 붙였다.

핵심 요점

  • PARA는 온보딩이 가장 빠르지만 '프로젝트 종료 후 부패'(재사용 가능한 지식이 일회성 산출물과 함께 Archive에 매장)가 구조적 실패모드다. Forte 본인도 2025년 'Hot or Cold' 2분류 단순화 버전을 제시했다. Zettelkasten은 초기 마찰과 완벽주의(Folgezettel 경직, 시스템 최적화가 취미가 됨)로 무너진다.
  • 검색이 공짜가 되면서 '어느 폴더에 넣을까'의 한계효용은 0에 수렴했고, 대신 연결(왜 붙는가)과 맥락(언제·어떤 근거로 쓰였고 지금도 유효한가)의 가치가 올랐다. 핵심 재정의는 분류의 소비자가 사람에서 에이전트로 바뀌었다는 것 — 구조는 이제 에이전트의 탐색 경로와 쓰기 대상 결정을 위해 존재한다.
  • 구조가 여전히 필요한 이유는 토큰 경제로 계산된다: 노트 2,000개 × 400토큰 ≈ 80만 토큰이면 Claude Opus 5($5/MTok) 기준 입력만 회당 약 $4지만, MOC 3장(≈6k)으로 라우팅해 20~40k만 로드하면 회당 $0.1~0.2 — 40배 차이가 폴더가 아닌 진입점 설계에서 난다. AGENTS.md+MOC를 고정 프리픽스로 두면 프롬프트 캐시 읽기는 입력가의 약 0.1배(최소 캐시 길이 Opus 5 512토큰 / Opus 4.8 1024토큰).
  • 폴더는 얇게(depth 1, 7개 이내) 두고 의미는 frontmatter로 표현한다. type/status/confidence/updated는 사람 필터링용이 아니라 '이건 낡았으니 약하게 인용하라'를 기계가 읽게 하는 계약이며, Obsidian Bases(코어, .base YAML)로 그대로 쿼리된다 — 1.9 Table·Cards, 1.10 List·Map. 단 Dataview 인라인 프로퍼티(key:: value) 미지원, 네이티브 캘린더·칸반은 로드맵 단계로 릴리스 시점 확인 필요.
  • 선택 기준: 노트 300개 미만이면 PARA만, 산출물이 목표면 PARA+CODE, 같은 결론을 반복 도출 중이면 Evergreen+MOC(원인은 분류가 아닌 연결 부재), 팀 공유면 Johnny.Decimal은 Areas에만, 에이전트가 매일 읽고 쓰면 MOC+frontmatter 계약+AGENTS.md. GTD는 볼트 밖 별도 도구로 유지한다.
  • 가장 흔한 실패는 방법론 선택 실수가 아니라 동시 도입이다. 하나만 켜고 실패모드를 관측한 뒤 다음 레이어를 얹는다. Johnny.Decimal의 숫자 접두어는 공유 문서에서 반드시 어긋나므로 전면 적용하지 않는다.

세컨드 브레인 방법론 지형도

방법론 소개 글은 넘친다. 여기서는 각 방법이 어디서 무너지는지부터 본다. 볼트가 죽는 건 방법을 몰라서가 아니라, 방법의 실패모드를 모른 채 3개월 뒤에 그걸 밟기 때문이다.

여섯 개의 방법, 그리고 각각의 붕괴 지점

방법 핵심 명제 잘 하는 것 무너지는 지점
PARA (Tiago Forte) 주제가 아니라 실행 가능성으로 자른다 (Projects/Areas/Resources/Archives) 온보딩 30분. 프로젝트 종료 = 폴더 이동 한 번 프로젝트 종료 후 부패. 프로젝트가 끝나면 그 안의 지식도 Archive로 함께 매장된다 — 재사용 가능한 원자 지식과 일회성 산출물이 같은 폴더에 묻힌다. Areas가 20개를 넘으면 P/A 경계도 무너진다. Forte 본인이 2025년 "Hot or Cold"(활성/그 외 2분류) 단순화 버전을 내놨을 정도
CODE (Capture–Organize–Distill–Express) PARA의 동사형 워크플로 Distill(점진적 요약)·Express(산출)가 "쌓기만 하는" 습관을 깬다 Capture만 남고 Distill/Express가 증발한다. 수집가의 오류(collector's fallacy)의 정확한 서식지
Zettelkasten (Luhmann) 원자 노트 + 고유 ID + 명시적 연결 노트 간 충돌에서 새 생각이 나온다. ID가 rename/move를 견딘다 초기 마찰과 완벽주의. Folgezettel(가지형 번호)은 규모가 커지면 경직된다. 루만도 하루 5장. "시스템 최적화"가 취미가 되고 노트는 안 는다
LYT / MOC (Nick Milo) 폴더 대신 MOC(Map of Content) 허브 노트로 묶는다 노트를 옮기지 않고 여러 맥락에 동시 소속시킨다. 폴더는 얇게 유지 방치된 MOC는 링크 무덤이 된다. "언제 MOC를 만들지"의 기준이 없어 조기 생성 → 텅 빈 허브 양산
Evergreen notes (Andy Matuschak) 노트는 시간에 걸쳐 진화·축적된다. 원칙: atomic / concept-oriented / densely linked / "note titles are like APIs" / 계층 분류보다 연상적 연결 제목이 API라는 규율 하나가 검색·인용·재사용을 다 살린다 규율 요구가 가장 높다. 대부분 강하게 시작해 바쁜 주에 capture 모드로 회귀
Johnny.Decimal 최대 10 Area × 10 Category × 100 ID의 주소 체계 12.03 같은 불변 주소. 검색 없이 "어디 있는지" 안다 숫자 접두어 자체가 마찰. 공유 문서에서는 남이 안 지켜 반드시 어긋난다. 볼트 전체 적용은 과잉
GTD (David Allen) 다음 행동(next action) 관리 실행 시스템 지식 시스템이 아니다. GTD는 "다음에 뭘 할지", PARA는 "그걸 하는 데 필요한 걸 어디서 찾을지". Forte의 권고도 병행이다. 볼트에 GTD를 욱여넣으면 태스크 앱을 나쁘게 재구현하게 된다

실무 조합은 대체로 PARA(폴더) + Evergreen(노트 단위) + MOC(진입점) 이고, Johnny.Decimal은 Areas에만 부분 차용한다.

LLM이 실제로 바꾼 것

검색이 사실상 공짜가 됐다. ripgrep은 5,000개 노트를 밀리초에 훑고, 임베딩은 "그 VSLAM 세션 만료 얘기"를 폴더 위치와 무관하게 찾는다. 그래서 "이 노트를 어느 폴더에 넣을까"의 한계효용은 0에 수렴한다. 대신 값이 오르는 건 둘이다.

  • 연결 — 어떤 노트가 어떤 노트와 왜 붙는지. LLM은 검색을 대신해 주지만 당신의 인과 판단은 못 만든다.
  • 맥락 — 언제·어떤 근거로 쓰였고 지금도 유효한지. 낡은 노트를 확신에 차서 인용하는 에이전트는 없는 것만 못하다.

핵심 재정의는 이것이다. 분류의 소비자가 사람에서 에이전트로 바뀌었다. 사람이 찾으려고 만들던 구조를, 이제는 에이전트가 탐색 경로를 정하고 어디에 쓸지 판단하려고 읽는다.

그래도 구조가 필요한 이유 — 탐색 경로와 토큰 예산

  1. 탐색 경로. 에이전트는 먼저 트리를 읽고 어디를 팔지 정한다. 평평한 5,000개 볼트에서 grep은 순위 없는 매치로 컨텍스트를 홍수처럼 채운다. MOC는 사람용 목차가 아니라 에이전트용 라우팅 테이블이다.
  2. 토큰 예산. Claude Opus 5는 1M 컨텍스트지만 다 넣는 건 공짜가 아니다. 노트 2,000개 × 평균 400토큰 ≈ 80만 토큰 = 입력만 회당 약 $4(Opus 5 $5/MTok 기준). MOC 3장(≈6k)으로 라우팅해 실제 로드를 20~40k로 줄이면 회당 $0.1~0.2. 40배 차이가 폴더 구조가 아니라 진입점 설계에서 난다.
  3. 프롬프트 캐시. AGENTS.md + 상위 MOC를 바이트 단위로 고정된 프리픽스로 두면 캐시 읽기는 입력가의 약 0.1배. 최소 캐시 길이가 Opus 5는 512토큰(Opus 4.8은 1024)이라 짧은 인덱스도 캐싱된다. 반대로 프리픽스에 updated: {{date}} 같은 걸 넣으면 매 요청 캐시가 깨진다.
  4. 쓰기 대상 결정. 에이전트가 노트를 쓰기까지 하면 "어디에 쓸지"가 규칙으로 존재해야 한다. 규율이 없으면 볼트는 6주 만에 중복 노트로 오염된다.

실무 골격 — 폴더는 얇게, 의미는 frontmatter로:

vault/
├── 00-inbox/       # 주 1회 0으로 비운다. 아니면 이 폴더가 곧 볼트가 된다
├── 10-projects/    # 종료일 있음 → 종료 시 폴더째 90-archive
├── 20-areas/       # 종료일 없음. 최대 10개 (Johnny.Decimal 규율만 차용)
├── 30-notes/       # 원자 노트. depth 1 고정, 분류는 frontmatter로
├── 40-maps/        # MOC = 사람과 에이전트의 공통 진입점
├── 90-archive/
└── AGENTS.md       # 에이전트용 볼트 지도: 먼저 읽을 곳 / 쓰지 말 곳
---
id: 20260731-1420-vslam-session-lease   # 불변. rename/move를 견딘다
title: VSLAM 세션 리스 만료가 맵 병합을 막는 이유   # 제목은 API — 열지 않고 판단 가능해야
type: evergreen        # evergreen | source | moc | decision | log
status: growing        # seed | growing | stable | deprecated
area: fleet-platform
projects: [mobio-session-management]
confidence: medium     # 에이전트가 인용 강도를 조절할 근거
updated: 2026-07-31
---

type/status/confidence를 넣는 이유는 사람이 필터링하려는 게 아니라 "이건 낡았으니 약하게 인용하라"를 기계가 읽을 수 있게 주기 위해서다. Obsidian Bases(코어 플러그인, .base YAML)로 이 frontmatter를 그대로 테이블/카드로 쿼리할 수 있다 — 1.9에서 Table·Cards, 1.10에서 List·Map(Map은 Maps 플러그인 필요). 단 Dataview의 인라인 프로퍼티(key:: value)는 지원하지 않으니 전면 이관 전 확인이 필요하고, 캘린더·칸반 네이티브 뷰는 공식 로드맵에 올라와 있으나 릴리스 시점은 확인 필요(현재는 커뮤니티 Kanban Bases View로 대체).

선택 기준표

상황 채택 이유 / 첫 액션
노트 300개 미만, "지금 뭘 하지"가 문제 PARA만 30분 세팅, 구조 논쟁 금지. 10-projects/부터
산출물(글·문서·제안서)이 목표 PARA + CODE Distill/Express를 캘린더에 고정. 안 하면 Capture만 남는다
같은 결론을 6개월마다 다시 도출 중 Evergreen + MOC 원인은 분류가 아니라 연결 부재. 노트 30개에 제목-as-API부터
연구·집필처럼 아이디어 충돌이 자산 Zettelkasten ID는 타임스탬프로. Folgezettel 번호 체계는 건너뛴다
팀·조직 공유 볼트 PARA + Johnny.Decimal(Areas만) 남이 지킬 규칙은 10개까지만. 전면 적용은 반드시 어긋난다
에이전트가 볼트를 매일 읽고 쓴다 MOC + frontmatter 계약 + AGENTS.md 폴더보다 진입점·스키마가 비용을 결정한다
"다음에 뭘 하지"가 진짜 문제 GTD(별도 도구) 볼트에 태스크 시스템을 재구현하지 말 것

가장 흔한 실패는 방법론 선택 실수가 아니라 동시 도입이다. 하나만 켜고, 실패모드를 관측하고, 그때 다음 레이어를 얹는다.

Obsidian 심층 — 왜 로컬 마크다운인가

Obsidian이 LLM 시대의 지식베이스로 유리한 이유는 "노트 앱"이라서가 아니라 볼트가 그냥 폴더이고 노트가 그냥 파일이기 때문이며, 이 섹션은 .obsidian 구조·frontmatter·Bases/Dataview·가격·동기화 충돌·대용량 한계를 실제 수치와 함께 짚고, 에이전트 연동(obsidian-skills, Obsidian CLI, Local REST API MCP)의 함정까지 정리한다.

핵심 요점

  • 볼트=폴더·노트=파일이라는 단순함이 LLM 유리함의 전부다: grep·git·Read/Edit가 어댑터 없이 동작하고, 청킹 경계가 이미 사람이 만든 의미 단위다. 대신 `.obsidian/workspace.json`은 반드시 gitignore.
  • 구조는 태그가 아니라 frontmatter(properties)에 넣어라. Bases의 `.base` 파일은 YAML이라 에이전트가 직접 쓸 수 있다는 점에서 Dataview(DQL/dataviewjs) 대비 결정적 이점이지만, 인라인 필드·임의 JS는 여전히 Dataview 영역이고 1.9.2 함수 문법 파괴 전례가 있다.
  • 가격(2026-07): 앱 무료(2025-02-20부터 상업용 라이선스 의무 폐지, Commercial $50/user/yr는 후원), Sync $4/mo 연납(볼트1·1GB·히스토리 1개월), Sync Plus는 볼트10·10GB(최대100GB)·12개월, Publish $8/site/mo 연납.
  • 동기화가 최대 파손 지점: 두 엔진 병행 금지(iCloud+Sync는 무한 루프·중복본), obsidian-git 모바일은 isomorphic-git이라 SSH·rebase·submodule 불가에 메모리 크래시. 에이전트 관점의 실제 피해는 `(conflicted copy).md`가 grep에 잡혀 낡은 사실을 컨텍스트에 주입하는 것 — 충돌 파일 패턴은 검색에서 제외.
  • 못 하는 것을 먼저 인정하라: CRDT 동시편집 없음(파일 동기화), 스키마 강제·참조 무결성 없음(`status: Open` 오타가 조용히 쿼리에서 누락 → 볼트 lint를 CI로), 수만 파일에서 인덱싱·그래프·Dataview 재계산 저하(모바일 특히).
  • 에이전트 연동 3경로 — kepano/obsidian-skills(볼트 루트 `.claude/`), 공식 Obsidian CLI(1.12.4 정식), Local REST API 내장 MCP(127.0.0.1:27123/mcp/). 단 볼트를 통째로 붓지 말 것: 한글 1,000자 ≈ 700~1,000토큰이라 노트 500개면 40~60만 토큰, frontmatter 필터→grep→상위 5~10개 전문 로드가 정석.

Obsidian 심층 — 왜 로컬 마크다운인가

볼트는 앱이 아니라 폴더다

Obsidian의 유일하게 중요한 설계 결정은 이것이다: 볼트 = 로컬 디렉터리, 노트 = .md 파일, 앱 설정 = 볼트 안의 .obsidian/ 하위 JSON. DB도, 프로프라이어터리 컨테이너도 없다. 그래서 rg, git, Claude Code의 Read/Edit가 아무 어댑터 없이 동작한다.

mobio-wiki/
├── .obsidian/            # 설정 = 데이터가 아님. git 취급 주의
│   ├── app.json  appearance.json  hotkeys.json
│   ├── community-plugins.json
│   ├── workspace.json    # ← 열린 탭/패널 상태. 커밋하면 매 세션 diff 노이즈
│   └── plugins/dataview/…
├── .claude/skills/       # 에이전트 스킬을 볼트 안에 둔다
├── 10-projects/  20-areas/  30-refs/  90-daily/
└── _attachments/

.gitignore에 최소한 .obsidian/workspace.json, .obsidian/workspace-mobile.json, .trash/는 넣는다. 반대로 .obsidian/plugins/를 통째로 커밋할지는 취향이 아니라 정책 문제다 — 커밋하면 팀 전체가 같은 플러그인 버전을 쓰지만, 플러그인 업데이트마다 수백 KB diff가 생겨 에이전트의 git log 판독을 오염시킨다.

주의할 트레이드오프: 포맷은 열려 있지만 앱은 오픈소스가 아니다. Markdown과 .canvas(JSON Canvas 1.0, MIT 스펙)는 누구나 구현 가능하지만 Obsidian 본체는 클로즈드 소스 무료 소프트웨어다. 락인은 데이터가 아니라 플러그인 생태계에 걸린다.

링크·프로퍼티·쿼리: 구조를 파일 안에 넣는다

  • [[위키링크]] — 파일명 기반 참조. 파일을 옮기거나 리네임하면 Obsidian이 링크를 갱신하지만, 에이전트가 CLI로 mv 하면 갱신되지 않는다. 이게 인간/에이전트 혼용 볼트의 1번 파손 경로다. 에이전트에게는 "링크 갱신은 Obsidian CLI나 앱 안에서" 규칙을 CLAUDE.md에 박아둬야 한다.
  • 백링크 / 아웃고잉 링크 / 그래프뷰 — 백링크는 실무 가치가 크지만, 그래프뷰는 솔직히 데모용이다. 노트 3,000개를 넘어가면 털뭉치가 되어 판단 근거가 되지 못한다.
  • frontmatter(Properties) — 태그보다 이쪽에 투자하라. 에이전트가 파싱할 수 있는 유일한 구조다.
---
type: incident
project: mobio-blog
status: open          # open | mitigated | closed
severity: p1
owner: srcho
created: 2026-07-31
tags: [og-image, cloudflare-pages]
related: ["[[blog 배포 구조]]", "[[og-public 재빌드 절차]]"]
---
  • 쿼리 — Dataview(DQL + dataviewjs 임의 JS 탈출구)가 오래 표준이었고, 후속작 Datacore는 아직 진행 중이다. 2025년 Bases가 코어 플러그인으로 들어오면서(1.9에 테이블·카드, 1.10에 리스트·맵 뷰와 Bases API 추가) frontmatter를 컬럼으로 쓰는 네이티브 DB 뷰가 생겼다. .base 파일은 YAML이라 에이전트가 직접 작성할 수 있다 — Dataview 대비 결정적 이점. 다만 인라인 필드(key:: value)나 임의 JS 렌더링은 Bases가 대체하지 못하며, 1.9.2에서 함수 문법이 크게 깨진 전례가 있으니 버전 고정 없이 대량 마이그레이션은 하지 말 것.
  • 자동화 — Templater(JS 템플릿), QuickAdd(캡처 매크로)는 여전히 유효하지만, 에이전트가 있으면 역할이 바뀐다. Templater는 결정적 스캐폴딩(frontmatter 스키마 강제)에, 생성·요약·연결은 에이전트에 맡기는 분업이 실패가 적다.

가격·라이선스 (2026-07 기준)

항목 가격 비고
앱 본체 무료 2025-02-20부터 상업용 라이선스 의무 폐지. Commercial $50/user/yr는 후원 성격으로 존속
Sync Standard $4/mo(연납) / $5(월납) 원격 볼트 1개, 스토리지 1GB, 버전 히스토리 1개월
Sync Plus 상위 티어 볼트 10개, 10GB(최대 100GB 증설), 히스토리 12개월
Publish $8/site/mo(연납) / $10(월납) 사이트 단위 과금
Catalyst $25 1회 얼리 액세스(초기 Bases·CLI가 여기 먼저 나왔다)

교육·비영리 40% 할인. 커뮤니티 플러그인 규모는 집계 기준에 따라 편차가 크다 — 공식 디렉터리 기준 수천 개, obsidianstats 집계로는 플러그인 6,000여 개·테마 650여 개(정확한 현시점 수치는 확인 필요).

동기화: 여기서 대부분 망가진다

방식 충돌 처리 실패 모드
Obsidian Sync 파일 단위 병합 + 버전 히스토리 유료, 계정 단위 스토리지
iCloud Drive 없음 → 중복본 생성 오프라인 편집·대용량 첨부에서 조용한 데이터 손실 신고 다수
Git (obsidian-git) 진짜 3-way merge 모바일은 isomorphic-git → SSH 불가, rebase·submodule 불가, 대형 repo에서 클론/풀 중 크래시
Syncthing 파일 단위, .sync-conflict-* 파일 모바일(특히 iOS) 백그라운드 제약

절대 규칙 하나: 두 동기화 엔진을 같은 볼트에 동시에 붙이지 말 것. iCloud + Obsidian Sync 병행은 서로의 쓰기를 되받아 무한 루프와 중복 충돌 파일을 만든다. 에이전트 관점의 진짜 위험은 여기서 나온다 — ... (conflicted copy).md, .sync-conflict-*.md가 볼트에 남으면 grep 검색이 그걸 정본으로 물어와 오래된 사실을 컨텍스트에 주입한다. 충돌 파일 패턴은 반드시 에이전트 검색에서 제외하라.

못 하는 것

  • 실시간 협업이 없다. Sync에 공유 볼트가 있지만 CRDT 기반 동시 편집이 아니라 파일 동기화다. 같은 문단을 둘이 동시에 고치는 워크플로는 Google Docs/Notion 쪽이 맞다.
  • DB가 아니다. 스키마 강제·참조 무결성·트랜잭션이 없다. status: open을 status: Open으로 쓴 노트는 조용히 쿼리에서 빠진다 → 값 검증은 CI(볼트 lint 스크립트)로 밖에서 걸어야 한다.
  • 대용량에서 느려진다. 수만 파일 볼트에서 초기 인덱싱, 그래프, Dataview 재계산이 눈에 띄게 무거워지고 모바일은 더 심하다(구체 임계값은 하드웨어·플러그인 의존, 수치는 확인 필요).

LLM 관점에서 유리한 이유 — 그리고 컨텍스트 예산

파일=문서라 청킹 경계가 이미 사람이 만든 의미 단위다. git이 있어 에이전트의 편집을 롤백·감사할 수 있고, rg 'status: open' -l 한 줄이면 토큰 0으로 후보를 좁힌다. RAG 인덱스를 새로 짓지 않아도 되는 게 핵심이다.

연동 경로는 2026년 기준 세 가지: ① Obsidian CEO(kepano)가 낸 obsidian-skills(obsidian-markdown / obsidian-bases / json-canvas / obsidian-cli / defuddle, GitHub 4만 스타대) — 볼트 루트 .claude/에 넣으면 Claude Code가 위키링크·callout·.base 문법을 지어내지 않는다. ② Obsidian CLI(1.12.4에서 정식, 실행 중인 앱의 리모컨 역할). ③ Local REST API 플러그인의 내장 MCP 서버(claude mcp add --transport http obsidian http://127.0.0.1:27123/mcp/ …).

함정은 컨텍스트 산수다. 한글 1,000자 노트가 대략 700~1,000토큰이라 볼트 500개면 40~60만 토큰 — 최신 Opus/Sonnet의 확장 컨텍스트에 "물리적으로" 들어가도 읽히지 않고 비용만 든다. 실무 규칙은 "볼트를 붓지 말고 볼트를 검색하게 하라": frontmatter 필터 → grep → 상위 5~10개 노트만 전문 로드. MOC(지도 노트)와 요약 계층을 두는 이유도 취향이 아니라 토큰 예산이다.

도구 지형 비교 — 무엇을 고를 것인가

에이전트 시대의 노트 도구 선택은 "에이전트가 파일시스템으로 직접 닿는가"라는 단일 축으로 갈리며, 개인 브레인은 로컬 마크다운 볼트(Obsidian)가, 팀 운영 DB는 Notion/Tana가 이긴다는 트레이드오프 중심 비교 섹션.

핵심 요점

  • 선택의 진짜 축은 기능이 아니라 접근 경로다 — 로컬 마크다운은 grep이 공짜지만, Notion 공식 MCP는 사용자당 ~180 req/min·검색 ~30/min에 페이지 단위 fetch만 가능해 에이전트 루프가 금방 막힌다.
  • 볼트를 통째로 컨텍스트에 넣는다는 발상은 틀렸다 — 노트 2,000개면 대략 200만 토큰 규모라 Opus/Sonnet 1M 컨텍스트에도 안 들어간다. 항상 검색 후 부분 로드.
  • 가격 실측(2026): Obsidian 앱 무료 + Sync $4/user·mo + Publish $8/site·mo(상업 라이선스 $50/user·yr은 FAQ상 의무 아님), Notion Business $20/user·mo에 AI 포함 + 에이전트 크레딧 $10/1,000 별도, Tana Plus $8/mo, Roam $15/mo, Reflect $10/mo, Mem Pro $12/mo.
  • Obsidian이 이기는 건 개인 브레인 한정 — 이유는 grep 원가·git diff 리뷰 가능성·벤더 소멸 리스크 셋뿐이다. 동시편집·권한감사·relation/rollup 운영 DB·비개발자 접근은 Notion/Tana가 명백히 낫다.
  • 락인은 export 버튼 유무가 아니라 '본문 밖에 있는 것'의 양이다 — Notion DB 뷰/rollup/수식, Tana supertag·Command Node, Obsidian의 Dataview·`.base`, Logseq `((block-uuid))`는 전부 이전 시 죽는다. Notion→Obsidian은 UUID 파일명 때문에 반드시 공식 Importer 플러그인 사용.
  • 실전 배치는 팀=Notion, 개인 브레인=로컬 볼트, 단방향 동기화. 볼트에 `git init` + `90-agent/` 생성물 격리 폴더 + frontmatter `confidence: verified|draft|rumor` 필드로 에이전트의 추측 되먹임을 차단.

도구 지형 비교 — 무엇을 고를 것인가

결정을 지배하는 단 하나의 축

기능 비교표부터 보면 길을 잃는다. 에이전트를 매일 쓰는 사람에게 실질적 분기점은 하나다: 에이전트가 파일시스템으로 직접 닿는가, API를 통과해야 하는가.

볼트가 로컬 마크다운이면 Claude Code를 볼트 디렉토리에서 그냥 띄우면 끝이다. MCP 서버도, OAuth도, 레이트리밋도 없다. Grep으로 300개 노트를 훑고 필요한 12개만 읽는 데 드는 비용은 사실상 0이다. SaaS DB면 매 접근이 네트워크 왕복이고, Notion 공식 원격 MCP(mcp.notion.com)는 사용자당 평균 180 req/min, 검색은 약 30/min으로 묶여 있다. 에이전트 루프 몇 번이면 벽에 닿는다. 페이지 단위 fetch/replace만 가능하고 블록 단위 REST는 노출되지 않으며 파일·이미지 접근도 없다.

여기서 흔한 오해 하나. "컨텍스트가 1M이니 볼트 통째로 넣으면 되지 않나?" — 노트 2,000개 × 평균 700단어면 대략 140만 단어, 200만 토큰 규모다. Opus/Sonnet의 1M 컨텍스트에도 안 들어가고, 들어가도 비싸고 정확도가 떨어진다. 정답은 항상 검색 후 부분 로드이며, 그 검색이 ripgrep이냐 벤더 API냐가 운영비를 가른다.

축별 비교

도구 데이터 소유 구조화 에이전트 접근 팀 협업 락인 탈출 가격(2026)
Obsidian 로컬 .md 파일 문서형 + Bases(코어 플러그인, .base) 파일 직접 / Local REST API / MCP 플러그인 약함(Git·Sync로 우회) 거의 0 앱 무료, Sync $4/user·mo, Publish $8/site·mo, 상업 라이선스 $50/user·yr(FAQ상 의무 아님)
Logseq OG=파일, DB=SQLite 블록형 CLI·파일(OG) 약함 OG는 낮음, DB는 미지수 무료
Notion SaaS DB DB형 최강 공식 원격 MCP(제한적) 최강 높음 Business $20/user·mo(연간), AI 포함. 커스텀 에이전트 크레딧 $10/1,000 별도
Roam SaaS 블록형 빈약 약함 높음 $15/mo (Believer $500/5년)
Tana SaaS supertag 스키마 Input API + 데스크톱 MCP 중간 높음 — JSON/md는 나오지만 supertag·Command Node·뷰는 이전 불가 Plus $8/mo, Pro $10/mo
Capacities / Anytype 클라우드 객체 / 로컬퍼스트 E2EE 객체형 빈약 약함 중~높음(relation 손실) Capacities ~$8.33/mo, Anytype Builder ~$99/yr
Bear / Craft 로컬+동기화 문서형 Bear 2.8 CLI+MCP, TextBundle 무손실 왕복 없음 낮음(Apple 생태계 한정) ~$3~5/mo대
Apple Notes iCloud 문서형 벌크 export 없음(노트당 PDF) 없음 사실상 불가 무료
Joplin 로컬 .md + E2EE 동기화 문서형 파일·플러그인 약함 낮음 무료

AI 네이티브 계열은 성격이 다르다. NotebookLM은 저장소가 아니라 읽기 전용 리서치 표면이다(무료 100노트북×50소스, Pro는 Google AI Pro $19.99/mo에 포함되어 상한 확대, 소스당 50만 단어/200MB). 볼트를 여기에 넣지 말고, 볼트에서 뽑아 던지는 용도로 써라. Reflect($10/mo, 무료 없음, E2EE)와 Mem(무료 25노트/월, Pro $12/mo)은 완성도는 높지만 파일 소유권을 포기한다. Khoj는 오픈소스·셀프호스트이고 Obsidian 플러그인이 있어 대체재가 아니라 볼트 위에 얹는 검색 계층으로 쓰는 게 맞다. Saner.ai는 공개 정보가 얕다 — 도입 전 export 포맷 직접 확인 필요.

"Notion에 다 있는데 왜 Obsidian?" — 정직한 답

정직하게 말하면 개인 브레인 한정으로만 Obsidian이 이긴다. 이유는 세 가지뿐이다.

  1. 에이전트 접근 원가. grep은 공짜고 API는 아니다.
  2. git. 볼트를 git init 하는 순간 에이전트가 쓴 모든 문장이 diff로 리뷰 가능해진다. Notion 페이지 히스토리로는 "어제 에이전트가 뭘 바꿨나"를 코드리뷰처럼 볼 수 없다.
  3. 소멸 리스크. 회사가 망해도 폴더는 남는다.

반대로 Notion/Tana가 명백히 나은 경우도 분명하다. 다인 동시편집, 권한/감사, relation·rollup이 진짜로 필요한 운영 DB(고객·계약·채용 파이프라인), 그리고 비개발자 동료가 매일 들어와야 하는 문서. Obsidian은 이 넷 전부에서 진다. Tana는 "구조를 강제해야 산출물이 나오는" 미팅노트·CRM류에서 supertag가 실질적 우위를 준다 — 단 탈출 비용을 계약금이라 생각하고 지불해야 한다.

하이브리드 실전 조합

권장 배치는 팀=Notion, 개인 브레인=볼트, 단방향 동기화다. 양방향은 반드시 깨진다.

~/brain/
├─ CLAUDE.md          # 에이전트 규약: frontmatter 스키마, 금지 폴더, 인용 규칙
├─ 00-inbox/
├─ 10-projects/       # 1프로젝트 1노트
├─ 30-refs/
├─ 40-daily/2026-07-31.md
├─ 90-agent/          # 에이전트 생성물 격리 — 사람 노트와 절대 섞지 않음
└─ Projects.base      # Bases 뷰(뷰 설정만 저장, 데이터는 md에 그대로)
---
type: project
status: active          # active | paused | shipped
owner: srcho
tags: [fleet, mcp]
updated: 2026-07-31
source: notion://page/8f2a...
confidence: verified    # verified | draft | rumor
---

confidence 한 줄이 실전에서 가장 값싸게 효과가 크다 — CLAUDE.md에 "rumor는 인용 금지"를 박아두면 에이전트가 자기 추측을 사실로 되먹이는 사고가 크게 줄어든다.

함정과 마이그레이션 현실

  • Notion → Obsidian: 모든 파일명에 32자 UUID가 붙고 내부 링크가 그 경로로 재작성된다. 반드시 공식 Importer 플러그인을 써라(UUID 제거 + 링크 변환). DB 뷰·rollup·수식·relation은 오지 않는다.
  • Obsidian 내부 락인: Dataview 쿼리와 .base는 마크다운 본문 밖의 설정이다. 노트는 살아도 뷰는 죽는다.
  • Logseq: OG(파일)는 유지보수 모드로 전환되었고 DB(SQLite)가 본류다. 2026년 상반기에 DB↔마크다운 왕복이 시작됐지만 성숙도는 미지수 — 신규 채택이라면 보류를 권한다. ((block-uuid)) 참조는 타 도구로 옮기면 전멸한다.
  • 에이전트 쓰기 권한: 주기 전에 git init + 일 1회 자동 커밋부터. 격리 폴더 없이 쓰기를 허용하면 3주 뒤 사람 노트와 생성물을 구분할 수 없게 된다.

볼트에 LLM 붙이기 — 플러그인과 에이전트

Obsidian 플러그인 경로(Smart Connections·Copilot·Text Generator·Khoj·Ollama)와 볼트를 그냥 디렉토리로 다루는 에이전트 경로(Claude Code·filesystem/obsidian MCP)를 비용·프라이버시·품질 3축으로 비교하고, 재인덱싱·임베딩 비용·자동 편집 사고 같은 실패모드와 방어책(git·드라이런·승인 게이트·쓰기 영역 분리)을 구체 수치와 명령어로 정리한 섹션.

핵심 요점

  • 플러그인은 읽기·탐색, 에이전트는 쓰기·리팩터링. Claude Code/MCP가 대개 더 나은 이유는 임의 도구 사용·다중 파일 편집·git 롤백 세 가지뿐이다.
  • 가격(2026-07): Copilot Free $0(BYOK)/Plus $14.99월·$139.99년/셀프호스트 $349.99, Smart Connections Pro $30월·$299년, Claude Code Pro $20·Max $100/$200, Opus 5 $5/$25 per MTok.
  • 임베딩 API 비용은 무시할 수준($0.02/1M tok, 5만 청크 재임베딩 ≈ $0.30) — 진짜 비용은 재인덱싱 시간과 8k~10k 노트대의 검색 지연(500ms~1s).
  • 볼트 통째로 컨텍스트에 넣기는 안티패턴: 1,000노트 ≈ 90만 토큰 ≈ 회당 $4.5에 답까지 나빠진다. grep으로 좁히고 5~10개만 읽혀라.
  • 자동 편집 실패모드는 위키링크 평탄화·frontmatter YAML 재직렬화로 인한 Bases/Dataview 파손·원본 삭제. 방어는 git 전제 + 드라이런 + 쓰기 영역 분리(00-inbox만 허용) + CLAUDE.md 인젝션 차단.
  • Obsidian Bases는 데이터를 frontmatter에 그대로 두고 .base에는 뷰 설정만 저장하므로, 에이전트가 frontmatter 규칙만 지키면 감사 대시보드가 공짜로 따라온다.

볼트에 LLM 붙이기 — 플러그인과 에이전트

붙이는 방법은 두 갈래다. 볼트 안에서 끝내는 길(Obsidian 플러그인)과 볼트를 그냥 마크다운 디렉토리로 취급하는 길(Claude Code·MCP). 결론부터: 읽기·탐색은 플러그인이 편하고, 쓰기·정리·리팩터링은 에이전트가 압도적이다. 그리고 사고가 나는 쪽은 언제나 후자다.

경로 A — Obsidian 플러그인

플러그인 하는 일 인덱싱 비용 (2026-07 기준) 걸리는 지점
Smart Connections 열어둔 노트와 의미상 가까운 노트를 사이드바에 상시 노출 로컬 임베딩 내장(무설정), Ollama의 nomic-embed-text·mxbai-embed-large도 연결 가능 Core 무료 / Pro $30/월·$299/년 8,000~10,000노트대에서 검색 지연 500ms~1s 보고. Pro의 핵심 판매 포인트가 "1000+ 노트 성능 인덱스"라는 게 곧 한계의 자백이다
Copilot for Obsidian 챗 + Vault QA(볼트 RAG) 로컬 데이터스토어에 인덱스 저장 Free = BYOK $0(가입 불필요) / Plus $14.99/월, 연 $139.99(=$11.67/월) / Self-host 평생 $349.99 Free에서는 에이전트·PDF·다국어 검색 제외. Vault QA 답변 품질은 청킹에 좌우되고, 긴 회의록에서 근거 문단을 자주 놓친다
Text Generator 템플릿 기반 생성(데일리 프롬프트, 회의록 확장) 없음(검색 아님) 무료·오픈소스 대화형이 아니라 템플릿 엔진. 노트별 frontmatter로 모델을 따로 지정할 수 있는 게 진짜 강점
Khoj 로컬 시맨틱 검색 + 챗, 자체 호스팅 서버가 볼트를 동기화해 인덱싱 AGPL-3.0, 셀프호스트 무료(클라우드는 별도 구독) 별도 서버 프로세스가 필요. 로컬 모델을 돌리려면 16GB+ RAM에 GPU 권장 — 노트북 하나로 끝나지 않는다

완전 로컬 구성 레시피. Ollama를 띄우고(ollama serve → http://localhost:11434), 임베딩 모델(ollama pull nomic-embed-text)과 생성 모델을 각각 받은 뒤, Copilot 설정에서 OpenAI 호환 엔드포인트(http://localhost:11434/v1)로 커스텀 모델을 등록한다. Smart Connections는 임베딩 모델만 Ollama로 돌려도 된다. API 과금 0, 볼트 밖으로 나가는 바이트 0. 대가는 응답 품질이다 — 로컬 14B급으로 "이 결정의 근거가 된 회의록 3건을 찾아 반박 논지를 정리해줘"를 시켜보면 격차가 즉시 드러난다.

경로 B — 볼트를 디렉토리로 두고 에이전트에 맡기기

볼트는 결국 .md 파일이 든 폴더다. 그러니 코딩 에이전트를 그냥 그 폴더에서 실행하면 된다.

cd ~/Documents/MyVault && claude
# 또는 다른 클라이언트에서 MCP로 붙이기
claude mcp add vault -- npx -y @modelcontextprotocol/server-filesystem ~/Documents/MyVault

Obsidian 전용 MCP도 있다. uvx mcp-obsidian(MarkusPfundstein)은 Local REST API 커뮤니티 플러그인 + Obsidian 실행 상태를 요구하는 대신 헤딩·블록 단위 원자적 패치와 Obsidian 인덱서 기반 전문 검색을 준다. obsidian-mcp-server(cyanheads)는 태그·frontmatter 편집 등 14개 툴, @bitbonsai/mcpvault는 플러그인 없이 raw .md를 다루며 frontmatter 원형을 보존한다. (일부 커뮤니티 MCP는 과거 심볼릭 링크 경로 탈출 이슈가 보고된 적이 있으니 버전 확인 필요.)

왜 대개 이쪽이 낫나. 세 가지가 전부다. (1) 임의 도구 — rg, git log, pandoc, 파이썬 스크립트를 그 자리에서 쓴다. 플러그인은 벡터 검색 하나에 갇혀 있다. (2) 다중 파일 편집 — "이 프로젝트 노트 12개에서 죽은 링크를 고치고 상태 frontmatter를 통일해줘"는 플러그인이 구조적으로 못 하는 일이다. (3) git — 커밋 단위 롤백이 되는 순간 자동 편집의 위험도가 다른 등급으로 내려간다. 여기에 CLAUDE.md가 매 세션 시스템 프롬프트로 주입되므로, 파일 배치·링크·분할 규칙을 문서로 못 박아둘 수 있다.

MyVault/
├── .git/
├── CLAUDE.md                  # 배치·링크·분할 규칙 (매 세션 주입)
├── .claude/
│   ├── settings.json          # 쓰기 권한 allow/deny
│   └── commands/weekly-review.md
├── 00-inbox/                  # 에이전트 생성 허용 구역
├── 10-notes/                  # 사람만 수정
├── 20-projects/
└── 90-archive/
---
title: MCP 서버 인증 설계
type: note
status: draft
tags: [mcp, auth]
ai_managed: false        # true인 문서만 본문 자동 수정 허용
ai_last_touched: 2026-07-31
source: meeting/2026-07-29
---

Obsidian Bases(코어 플러그인)는 데이터를 별도 DB가 아니라 노트의 frontmatter 프로퍼티에 그대로 두고 .base 파일에는 뷰 설정만 저장한다. 즉 에이전트가 frontmatter만 규칙대로 쓰면 표·카드 뷰가 공짜로 따라온다. ai_managed: true인 노트만 필터링하는 Base 하나면 감사 대시보드가 된다.

비용·프라이버시·품질 트레이드오프

로컬(Ollama) 플러그인 + API 키 에이전트 구독
과금 GPU 전기값 임베딩은 사실상 공짜(text-embedding-3-small $0.02/1M tok — 5만 청크 전량 재임베딩이 약 $0.30), 진짜 비용은 챗 토큰 Claude Code Pro $20/월, Max $100/$200 (5시간 롤링 창 + 주간 캡)
프라이버시 완전 격리 질의된 청크만 전송 읽은 파일 내용이 전송됨
품질 요약·태깅은 쓸 만, 다단계 추론은 약함 중간 최상 (Opus 5 $5/$25 per MTok, 1M 컨텍스트)

함정

"볼트를 통째로 컨텍스트에 넣기"의 유혹. 1,000노트 × 평균 900토큰이면 약 90만 토큰이다. 1M 컨텍스트에 들어가긴 하지만 입력만 회당 약 $4.5, 게다가 답은 더 나빠진다. grep/glob으로 후보를 좁히고 5~10개만 읽히는 쪽이 싸고 정확하다.

인덱스 재구축. 청킹 로직이나 임베딩 모델이 바뀌면 전량 재계산이다. 금전 비용보다 시간·배터리가 문제고, 모바일에서는 사실상 재인덱싱을 포기해야 한다. 임베딩 모델을 바꾸는 결정은 되돌리기 어렵다고 보고 처음에 정하라.

자동 편집이 노트를 망치는 실제 패턴. ① "정리해줘" 한 번에 [[위키링크]]가 일반 텍스트로 평탄화 → 그래프 붕괴. ② YAML frontmatter 재직렬화로 따옴표·날짜 형식이 바뀌어 Bases 뷰와 Dataview 쿼리가 조용히 깨짐. ③ 중복 제거하면서 원본을 지우고 요약본만 남김. ④ 다른 세션이 미커밋 변경을 덮어씀.

방어는 네 겹으로 쌓는다. (1) git이 전제조건 — 볼트가 git 저장소가 아니면 에이전트를 붙이지 마라. 세션 시작 시 git status clean 확인, 종료 시 커밋. (2) 드라이런 — "패치만 출력하고 파일은 건드리지 마"를 기본 워크플로로. (3) 승인 게이트 — .claude/settings.json에서 10-notes/** 쓰기를 deny하고, 에이전트는 00-inbox/에만 생성하게 한다. 승격은 사람이 한다. (4) 프롬프트 인젝션 경로 차단 — 웹 클리핑을 볼트에 쌓고 에이전트에게 읽히는 순간 그 텍스트는 지시문이 될 수 있다. CLAUDE.md에는 특히 출처 불명 내용을 절대 붙여넣지 않는다.

내 노트 위에 검색·RAG 구축하기

개인 규모 마크다운 볼트에서 ripgrep·파일명 규칙 → 하이브리드(BM25+임베딩) → 재랭킹 → 그래프 순으로 검색 스택을 단계적으로 올리는 실전 가이드. 2026년 1M 토큰 컨텍스트 기준으로 "언제 RAG가 과잉인가"의 손익분기, 청킹·임베딩 비용·벡터 저장소 비교, 20문항 골든셋 recall 측정 절차, 임베딩 단독 사용 시 고유명사·코드·숫자 검색이 무너지는 실패 모드를 구체 수치와 명령어로 정리했다.

핵심 요점

  • 수백~수천 노트 규모에서는 ripgrep + 파일명/frontmatter 규칙만으로 recall@10 0.7~0.8이 나온다 — 벡터 DB는 1단계가 아니라 2~3단계다
  • 2026년 손익분기: 볼트 전체가 20만~30만 토큰(약 500~800노트) 미만이면 RAG가 과잉이고, 그 이상이면 '검색으로 5만~20만 토큰까지 좁힌 뒤 롱컨텍스트로 추론'하는 하이브리드가 기본형이다
  • 임베딩만 쓰면 에러코드·API 키 프리픽스·커밋 해시·IP·코드 심볼 검색이 조용히 무너진다 — exact-ish 쿼리는 반드시 BM25/ripgrep 경로가 살아 있어야 한다
  • 개인 규모 최적 스택은 SQLite 파일 하나(FTS5 BM25 + sqlite-vec + RRF). 단 sqlite-vec는 아직 pre-v1(0.1.10-alpha)이라 breaking change 대비 재인덱싱 스크립트가 필수다
  • 임베딩 초기 인덱싱 비용은 논점이 아니다(5,000노트 = $0~0.39). 진짜 비용은 재인덱싱 운영과 모델 교체 시 전량 재계산 락인이므로 로컬 모델(EmbeddingGemma 308M, nomic-embed-text)로 시작하는 게 합리적이다
  • 골든셋 20문항 절차: 실제 던진 질문 수집 → must_hit 노트 경로 손으로 지정 → recall@10/@50 베이스라인 → 한 번에 하나씩 변경. recall@50이 안 오르는 변경은 재랭킹으로도 못 고친다
  • GraphRAG/LightRAG는 마지막 수단 — 개인 볼트에는 이미 [[위키링크]] 그래프가 있고, 검색 결과에서 1~2홉 확장하면 효과 대부분이 나온다

내 노트 위에 검색·RAG 구축하기

결론부터. 수백~수천 노트 규모에서 벡터 DB는 1단계가 아니라 2~3단계다. 2026년에 이 판단이 바뀐 이유는 컨텍스트 윈도우다. Claude Opus 5와 Sonnet 5는 모두 1M 토큰 창을 기본으로 쓰고, 입력 가격은 각각 $5 / $3 per MTok, 프롬프트 캐시 읽기는 약 0.1배다(Opus 5는 캐시 최소 길이가 512토큰으로 내려갔다). 검색 스택을 세우기 전에, 내 볼트가 이미 "그냥 넣으면 되는" 크기인지부터 계산해야 한다.

0단계: ripgrep + 파일명·frontmatter 규칙 (대부분 여기서 끝난다)

vault/
├─ MEMORY.md                    # 200줄 미만, 포인터만 — 항상 컨텍스트에 넣는 지도
├─ 10-projects/2026-07-31-mgmt-api-service-keys.md
├─ 20-areas/auth/
├─ 30-refs/
├─ 90-daily/2026-07-31.md
└─ .obsidian/
---
title: mgmt-api 서비스 키(mk_) 발급 절차
type: reference          # reference | decision | incident | daily
project: mobio-fleet
tags: [auth, mgmt-api]
aliases: ["mk_ 키", "service api key"]
created: 2026-07-18
updated: 2026-07-31
status: verified         # draft | verified | stale
---
rg -t md -il "service.?key" 10-projects/ | head -40     # 파일명 먼저, 본문은 나중에
rg -t md -n -C3 'mk_[A-Za-z0-9]{8,}'                    # 정확 토큰 — 임베딩이 절대 못 잡는 것
rg -t md -o '\[\[[^]]+\]\]' 30-refs/auth.md             # 위키링크로 1홉 확장 = 가난한 자의 GraphRAG
rg -t md --files-with-matches 'status: stale'           # frontmatter를 인덱스처럼

이게 "검색 스택"이다. Claude Code·Codex류 에이전트는 이 경로를 이미 갖고 있고, 에이전트 메모리도 대체로 벡터 DB가 아니라 MEMORY.md 인덱스 + grep 조합으로 도는 것으로 알려져 있다(유출 아키텍처 분석 기반, 1차 출처 확인 필요). Karpathy가 2026년 4월 공개해 화제가 된 "LLM wiki" 패턴(raw/ + wiki/ + index.md) 역시 임베딩 없이 마크다운과 컨텍스트만으로 돌아간다. MCP로 붙이려면 kp-ripgrep-mcp, notes-mcp처럼 ripgrep을 감싸고 frontmatter·위키링크를 구조화해주는 서버가 가장 저항이 적다.

"전부 넣기"의 손익분기: 노트 3,000개 × 평균 500단어 ≈ 200만 토큰 → 1M 창에도 안 들어간다. 하지만 rg가 40개 파일로 줄이면 6만 토큰 남짓, Opus 5 입력 기준 $0.30이고 캐시를 걸면 반복 질의는 사실상 공짜다. 볼트 전체가 20만~30만 토큰(대략 500~800노트) 미만이고 질문이 횡단적(요약·대조·추세 추적)이라면 RAG는 리콜만 깎아먹는다. 반대로 컨텍스트를 무한정 채우는 것도 안 된다 — 관련 정보가 창 중간에 묻히면 정확도가 눈에 띄게 떨어진다는 보고가 반복적으로 나온다("context rot"; 낙폭 수치는 벤치마크마다 편차가 커서 단정할 수 없다). 2026년의 실무 기본형은 검색으로 5만~20만 토큰까지 좁힌 뒤 롱컨텍스트로 추론하는 하이브리드다.

1단계: 하이브리드(BM25 + 임베딩)

rg가 무너지는 지점은 딱 하나, 어휘 불일치다. "와이파이 끊김"이라고 적어놓고 "네트워크 단절"로 검색할 때. 이때만 임베딩을 추가한다.

가장 저항 적은 스택은 SQLite 파일 하나: FTS5(BM25) + sqlite-vec(벡터 KNN) + RRF(Reciprocal Rank Fusion) 융합을 순수 SQL로. 1만~5만 청크 규모에서 수십 ms대 응답이 보고된다.

저장소 강점 함정
sqlite-vec 파일 1개, 무의존, FTS5와 같은 DB에 → RRF가 SQL 한 방 아직 pre-v1(0.1.10-alpha 대). SQL API·저장 포맷 breaking change 예고됨 → 재인덱싱 스크립트를 반드시 갖출 것
LanceDB 디스크 기반 IVF-PQ, RAM보다 큰 데이터 OK, 인제스트 빠름 개인 볼트(수만 청크)엔 과잉. 근사 검색이라 recall 손실
Chroma API가 제일 쉬움, 프로토타입 최속 인메모리 성향 — 100만 벡터 근처에서 메모리 압박

청킹은 단순하게. 노트 자체가 자연 청크다. 5,000자 넘는 노트만 ## 헤딩 단위로 자르고, 각 청크 앞에 파일경로 + title + tags + 헤딩 경로를 프리픽스로 붙인다(오버랩보다 이게 효과가 크다). 코드블록과 표는 절대 자르지 말 것 — 잘린 코드 청크는 임베딩 공간에서 의미를 잃는다.

임베딩 모델·비용. 노트 5,000개 × 600토큰 = 300만 토큰 인덱싱 기준:

모델 단가(1M 토큰) 5,000노트 초기 인덱싱
EmbeddingGemma 308M (로컬, 768d, 양자화 시 <200MB RAM) $0 $0
nomic-embed-text (Ollama, 768d) $0 $0
OpenAI text-embedding-3-small / voyage-4-lite ~$0.02 ~$0.06
OpenAI text-embedding-3-large ~$0.13 ~$0.39

즉 초기 인덱싱 비용은 논점이 아니다. 진짜 비용은 (a) 노트가 바뀔 때마다 도는 재인덱싱 운영과 (b) 모델 교체 시 전량 재계산이라는 락인이다. 개인 볼트는 로컬 모델로 시작하는 게 합리적이다 — Obsidian 쪽이라면 Smart Connections(로컬 임베딩 기본)나 Copilot + Ollama 조합이 가장 마찰이 적고, 어휘 검색은 Omnisearch가 채운다. 구조화된 조회는 임베딩이 아니라 Bases 코어 플러그인(.base 파일 + frontmatter 프로퍼티)으로 푸는 게 맞다.

2단계: 재랭킹

하이브리드로 50~100건을 뽑고 cross-encoder로 8~15건으로 줄인다. Cohere/Voyage의 rerank API나 로컬 bge-reranker를 쓰고, 개인 규모라면 Haiku 4.5($1/MTok 입력)로 LLM 재랭킹을 돌려도 비용이 무의미하다. 다만 recall@50이 낮으면 재랭킹은 아무것도 못 고친다. 순서 문제일 때만 손대라.

3단계: 그래프(GraphRAG / LightRAG)

마지막이고, 대개 불필요하다. MS GraphRAG는 1M 토큰 인덱싱에 $20~40, LightRAG는 ~$0.50 수준으로 알려져 있다(비용은 모델·구현에 따라 크게 흔들린다). 개인 볼트에는 이미 [[위키링크]]라는 사람이 만든 그래프가 있다 — 검색 결과에서 링크를 1~2홉 확장하는 것만으로 효과의 대부분이 나온다. "이 결정에 영향 준 것들을 다 모아줘" 같은 다중홉 질문이 반복적으로 실패할 때만 그래프를 검토하라.

실패 모드: 임베딩만 쓰면 무너지는 것들

이게 이 섹션에서 가장 중요한 문단이다. dense 임베딩은 희귀 토큰의 표현을 학습하지 못했다. 학습 중 거의 본 적 없는 문자열이기 때문이다. 구체적으로 깨지는 것:

  • 에러 코드·식별자: ERR_CONN_RST, mk_/ik_ 같은 키 프리픽스, 커밋 해시 a07fa9a
  • 고유명사: 사람 이름, 사내 코드네임, 벤더명
  • 숫자·IP·가격: 3.208.170.159, PERSON_FY_PX 515→371, "$5/MTok"
  • 코드 심볼: SafewayFollowMixer, --profile homepage

임베딩 검색은 의미적으로 인접하지만 그 토큰이 없는 문서를 자신 있게 돌려준다 — 조용히 틀린다는 게 최악이다. 따라서 규칙: exact-ish 쿼리는 항상 BM25/ripgrep 경로가 살아 있어야 한다. 쿼리에 대문자 스네이크, 숫자, 백틱, 하이픈 결합 토큰이 있으면 어휘 경로 가중치를 올리거나 아예 rg로만 처리하는 라우팅을 두는 게 실전에서 가장 효과가 크다.

검색 품질 평가: 내 질문 20개 골든셋

측정 없이 스택을 올리면 매번 "느낌상 좋아진 것 같다"로 끝난다. 절차:

  1. 실제로 던졌던 질문 20개를 수집한다(에이전트 로그·검색 히스토리에서 긁어라. 지어내면 안 된다). 정확 토큰형 6개, 개념형 8개, 다중홉 6개로 섞는다.
  2. 각 질문에 대해 "이게 안 나오면 실패"인 노트 파일 경로 1~3개를 손으로 적는다. 이게 골든셋의 전부다 — golden.jsonl에 {"q": "...", "must_hit": ["10-projects/....md"]}.
  3. 현재 스택(=rg)으로 top-10을 뽑아 recall@10 = must_hit이 하나라도 top-10에 든 질문 비율을 잰다. 이게 베이스라인이다.
  4. 변경은 한 번에 하나씩(임베딩 추가 → 재랭킹 추가 → 청킹 변경). 매번 recall@10과 recall@50을 다시 잰다.
  5. recall@50이 안 오르면 그 변경은 무의미하다(재랭킹으로 못 고친다). recall@50은 높은데 recall@10이 낮으면 그때가 재랭킹을 넣을 시점이다.
  6. 20문항은 통계적으로 얇다 — 한 문항이 5%p다. 스택을 프로덕션처럼 굴릴 거면 30~50문항으로 늘려라. 다만 0문항보다 20문항이 압도적으로 낫다.

실무 경험칙: 잘 정리된 파일명·frontmatter만으로 rg recall@10이 0.7~0.8에 도달하는 볼트가 많다. 거기서 하이브리드가 0.85~0.9로 올려주고, 재랭킹은 top-10 순서를 정리해준다. 0.4에서 시작한다면 문제는 검색 스택이 아니라 파일명 규칙이다.

참고 출처

↗ Is RAG Dead? Long Context, Grep, and the End of the Mandatory Vector DB↗ Long Context vs RAG: When 1M Token Windows Replace RAG↗ Context Rot, RAG, and Long Context: How to Architect LLM Systems in 2026↗ Hybrid Search: BM25, Vector & Reranking Reference 2026↗ Sparse Retrieval and BM25: When Lexical Search Wins↗ Building a Hybrid RAG in 200 Lines — SQLite + FTS5 + sqlite-vec + RRF↗ asg017/sqlite-vec — A vector search SQLite extension (pre-v1)↗ Hybrid full-text search and vector search with SQLite — Simon Willison↗ LanceDB vs ChromaDB — Disk-Based Embedded Vector DB vs In-Memory Lightweight Store↗ Introducing EmbeddingGemma: On-Device Embeddings↗ Text Embedding Models 2026: Google vs OpenAI vs Voyage pricing↗ How to Evaluate Retrieval Quality in RAG Pipelines: Precision@k, Recall@k, F1@k↗ A complete guide to RAG evaluation: metrics, testing and best practices — Evidently AI↗ Graph RAG in 2026: Microsoft GraphRAG vs LightRAG vs Neo4j Graphiti — Cost & Architecture↗ boazy/notes-mcp — MCP server with ripgrep-powered search for Obsidian vaults↗ kpetrovsky/kp-ripgrep-mcp — Obsidian-aware ripgrep MCP server↗ Obsidian Bases: The Complete Guide to Database Views (2026)↗ AI plugins Obsidian 2026: comparison of 7 major (Smart Connections, Copilot, Omnisearch)↗ Beyond RAG: How Andrej Karpathy's LLM Wiki Pattern Builds Knowledge That Actually Compounds↗ The Missing Piece Every Obsidian User Needs: Local RAG That Actually Works in 2026

에이전트 메모리와 위키의 결합

"읽는 위키"를 "쓰는 위키"로 바꾸는 실무 설계를 다룬 섹션입니다. 항상-로드/조건-로드/검색-로드 3층 컨텍스트 예산, 볼트를 에이전트 메모리 디렉토리로 직결하는 구성(autoMemoryDirectory·MCP), 파일 1개=사실 1개 frontmatter 규약, 메모리 위생 규칙, 에이전트가 쓴 노트의 환각 고착 방어(스테이징+게이트+git diff), 드리프트 자동감지까지 구체적 수치·명령어·폴더트리와 함께 정리했습니다.

핵심 요점

  • 컨텍스트 예산은 3층(항상/조건/지연)으로 분리: CLAUDE.md 200줄 권장, 오토메모리 MEMORY.md는 첫 200줄 또는 25KB만 로드되고 초과분은 잘림, 스킬 메타데이터는 개당 ~100토큰. @import는 절약이 아니라 정리 수단(전량 launch 로드, 최대 4홉)
  • autoMemoryDirectory 설정으로 에이전트 오토메모리를 Obsidian 볼트 안으로 직결하고, 반대 방향은 MCP(obsidian-mcp-server+Local REST API v4 / basic-memory)로 노출. READ_ONLY 기본 + WRITE_PATHS 단일 폴더 화이트리스트
  • 파일 1개=사실 1개 + frontmatter(status/confidence/source/verified_on/supersedes). 상대날짜 절대 금지, 삭제 대신 superseded 무효화, MEMORY.md는 항목당 한 줄 인덱스
  • 에이전트 노트의 최대 리스크는 환각 고착 — 출처 없는 write 금지, inbox-agent 스테이징 게이트, git diff 일일 리뷰, MCP 경로 제한의 4겹 방어
  • 드리프트는 시간이 아니라 소스 변경이 원인 — frontmatter anchors + CI diff 교집합(또는 Fiberplane drift의 tree-sitter 앵커링)으로 감지하되, 알림 피로를 피해 중요 노트 20~30개에만 적용
  • Obsidian 본체 무료·Sync $4/user/월(연납)·상업 라이선스 $50/user/년이지만 실제 비용은 사람의 검토 게이트 시간이다

에이전트 메모리와 위키의 결합

읽기 전용 위키는 만들기 쉽다. 어려운 건 에이전트가 쓴 다음이다. 쓰기 시작하는 순간 지식베이스는 "정리된 노트 모음"에서 "검증되지 않은 주장이 축적되는 데이터베이스"로 성질이 바뀐다. 이 섹션은 그 전환을 견디는 구조를 다룬다.

컨텍스트 예산: 3층으로 쪼개라

가장 흔한 실패는 볼트 전체를 에이전트에게 물려주는 것이다. 로드 시점 기준으로 세 층을 명시적으로 분리해야 한다.

층 파일 로드 시점 실측 한도 담을 것
항상 CLAUDE.md / AGENTS.md 세션 시작 전량 200줄 권장(≈2~3k 토큰) 빌드·배포 명령, 절대 규칙, 프로젝트 지도
항상(자동) 오토메모리 MEMORY.md 세션 시작 첫 200줄 또는 25KB(먼저 걸리는 쪽) 한 줄 인덱스 + 토픽 파일 링크
조건 .claude/rules/*.md paths: glob 매칭 시 파일당 짧게 특정 디렉토리 규약
지연 스킬 SKILL.md, 토픽 노트 호출·검색 시 메타데이터 ~100토큰/개 런북, 절차, 상세

핵심 수치 세 가지: (1) CLAUDE.md는 @경로 import를 써도 launch 시점에 전량 펼쳐져 로드된다 — 분할은 정리용이지 절약이 아니다(최대 4홉). (2) 스킬은 name/description만 상주하므로 20개를 등록해도 2k 토큰 내외, 활성화된 스킬 본문 하나보다 싸다. (3) MEMORY.md는 한도를 넘으면 넘친 부분이 조용히 잘린다. 실제로 뭐가 로드됐는지는 /context로 확인하고, 비대해진 CLAUDE.md는 /doctor의 트림 제안을 돌려라. 사람용 메모는 블록 레벨 HTML 주석(<!-- -->)에 넣으면 컨텍스트에 안 들어가서 토큰 0이다.

권장 목표: 항상-로드 총합 5k 토큰 이하. 넘으면 "지시 희석(context rot)"으로 규칙 준수율이 떨어진다.

볼트를 메모리 디렉토리로 직결

Claude Code 오토메모리는 기본적으로 ~/.claude/projects/<project>/memory/에 쓴다. 이걸 볼트 안으로 돌리면 에이전트 메모리와 세컨드 브레인이 같은 파일이 된다.

// .claude/settings.json
{ "autoMemoryDirectory": "~/vault/10-agent-memory" }

(프로젝트 스코프로 설정하면 워크스페이스 신뢰 다이얼로그 승인 후에만 적용된다.)

반대 방향 — 사람이 쓴 노트를 에이전트 도구로 노출 — 은 MCP다. 두 계열이 있다.

  • REST API 계열: obsidian-mcp-server(cyanheads) + Obsidian Local REST API 플러그인 v4+. npx -y obsidian-mcp-server@latest. 14개 툴(get/list/write/append/patch/frontmatter/tags…). Obsidian이 떠 있어야 한다.
  • 파일시스템 계열: basic-memory, lstpsche/obsidian-mcp 등. Obsidian 없이 마크다운을 직접 읽고 SQLite로 색인. 앱 미실행 상태에서도 동작.

보안 스위치를 반드시 쓸 것: OBSIDIAN_READ_ONLY=true를 기본으로 두고, 쓰기는 OBSIDIAN_WRITE_PATHS로 단 하나의 폴더에만 허용한다.

vault/
├── AGENTS.md                # ln -s AGENTS.md CLAUDE.md (Windows는 @AGENTS.md import)
├── .claude/rules/deploy.md  # frontmatter: paths: ["services/**"]
├── facts/                   # 파일 1개 = 사실 1개 (사람 검토 완료)
├── runbooks/                # 절차 = 스킬 본문의 원본
├── inbox-agent/             # ← 에이전트 쓰기 전용. 여기만 WRITE_PATHS
└── archive/

파일 1개 = 사실 1개, 그리고 frontmatter

한 노트에 사실 여러 개를 담으면 무효화가 불가능해진다("이 문단만 낡음"을 표현할 방법이 없다). 원자 단위로 쪼개고 상태를 frontmatter에 박는다.

---
type: fact
scope: mobio-device-gateway
status: current              # current | superseded | disputed
confidence: agent-claimed    # agent-claimed | verified
source: "deploy.sh:42 / 2026-07-28 배포 로그"
verified_by: srcho
verified_on: 2026-07-28
modified: 2026-07-30T11:02:00+09:00
supersedes: "[[deploy-via-ecs-cd]]"
---
백엔드 마이크로서비스는 Lightsail에 수동 배포한다. develop 푸시만으로는 반영되지 않는다.

메모리 위생 4규칙:

  1. 상대날짜 금지. "지난주", "최근", "곧" → 전부 절대날짜(2026-07-28). 상대 표현은 6개월 뒤 읽는 에이전트에게 거짓말이 된다. Claude Code 2.1.214+는 frontmatter가 있는 메모리 파일에 modified ISO8601을 자동 기록하므로, 그 필드를 신선도 판정에 쓴다.
  2. 삭제보다 무효화. 틀린 사실은 지우지 말고 status: superseded + supersedes 링크. 왜 틀렸는지가 다음 세션의 학습 재료다.
  3. 중복은 병합, 인덱스는 한 줄. MEMORY.md는 항목당 1줄 + 링크만. 상세는 토픽 파일로 내린다.
  4. 주기 스윕. Obsidian Bases(코어 플러그인, 1.9 테이블/카드·1.10 리스트/맵 — 정확한 버전은 릴리스 노트 확인)로 status: current AND modified < 90일 뷰를 만들어 월 1회 훑는다. Dataview 없이 프론트매터가 그대로 컬럼이 되고, 표에서 값을 고치면 노트에 역기록된다.

에이전트가 쓴 노트는 기본적으로 신뢰하지 마라

가장 위험한 실패모드는 환각 고착(hallucination internalization) 이다. 에이전트가 추측으로 쓴 문장이 지식베이스에 들어가면, 다음 세션은 그걸 검증된 사실로 읽고 그 위에 또 쓴다. 보안 연구에서는 메모리 포이즈닝의 결과를 의미 드리프트·절차 드리프트·환각 내재화 세 패턴으로 정리한다. 개인 볼트라고 안전하지 않다 — 공격자가 없어도 자기 자신이 오염원이다.

방어는 네 겹으로:

  • 출처 없는 사실은 저장 금지. source에 파일:라인, 커밋 SHA, 로그 타임스탬프, URL 중 하나가 없으면 write를 거부하도록 CLAUDE.md에 규칙을 박는다.
  • 스테이징 게이트. 에이전트 쓰기는 inbox-agent/로만. confidence: verified 승격은 사람만 한다.
  • git diff 리뷰. 볼트를 git으로 관리하고(Obsidian Git 플러그인 또는 그냥 cron git commit), 하루 한 번 git diff --stat로 "에이전트가 뭘 바꿨나"를 본다. 이게 사실상 유일하게 확장 가능한 감사 수단이다.
  • 경로 제한. MCP는 read-only 기본 + 쓰기 폴더 화이트리스트. Anthropic 메모리 툴 문서도 경로 traversal 검증과 만료 정책을 구현자 책임으로 명시한다.

드리프트 자동감지

위키가 낡는 건 시간이 아니라 소스 변경 때문이다. 앵커를 걸어 CI에서 잡는다.

  • Fiberplane drift 같은 도구는 마크다운 스펙을 tree-sitter AST 지문으로 소스에 앵커링하고, 앵커된 코드가 바뀌면 drift check가 CI를 실패시킨다(스펙 갱신 후 drift link로 재바인딩).
  • 가난한 버전: 노트 frontmatter에 anchors: ["deploy.sh", "src/api/handlers/"]를 두고, GitHub Actions에서 git diff --name-only ∩ anchors를 계산해 이슈를 연다. 여기에 anthropics/claude-code-action@v1을 붙이면 갱신 PR까지 자동 생성할 수 있다.
  • 함정: 알림 피로. 앵커는 "이 노트가 틀리면 사고가 나는" 20~30개에만 건다. 전 노트에 걸면 3주 안에 아무도 안 본다.

비용과 한계

Obsidian 본체는 무료, Sync는 연납 $4/사용자/월, 상업용 라이선스는 $50/사용자/년(2026년 기준 사실상 선택 — 최신 약관 확인 필요). git으로 동기화하면 Sync는 불필요하다. 진짜 비용은 도구가 아니라 검토 게이트를 지키는 사람의 시간이고, 그 게이트를 포기하는 순간 위키는 에이전트의 확신에 찬 헛소리를 영구 보존하는 장치가 된다.

수집 → 소화 → 산출 파이프라인

인박스 단일 진입점부터 웹 클리퍼·하이라이트·음성·회의록·슬랙·코드 세션 로그까지 7개 입력 경로를 각각의 자동 요약 프롬프트·frontmatter 게이트와 함께 설계하고, 소화되지 않은 캡처가 산출로 새어나가지 못하게 막는 파이프라인을 다룬다. 특히 LLM 요약이 만드는 '인지 부채'를 근거로 사람이 반드시 손으로 써야 하는 최소 지점(claim 한 문장·제목·링크 결정)을 명시하고, 인박스를 무덤으로 만들지 않는 주간 리듬과 강제 배수구를 제시한다.

핵심 요점

  • 소화되지 않은 캡처가 산출로 새어나가지 못하게 막는 단일 게이트를 frontmatter `claim` 필드로 구현한다 — 사람이 한 문장을 직접 쓰지 않으면 원자 노트로 승격 불가
  • 입력 경로 7종(웹 클리퍼·Readwise·음성·회의록·슬랙·코드 세션·손 메모)은 장점이 아니라 실패 모드로 평가한다: Interpreter의 전체 HTML 컨텍스트, Ollama 2048 토큰 절단, 하이라이트 벽돌, 전사본 노이즈, 회의록 벤더 락인
  • "요약해줘" 대신 나중의 검색·판단에 필요한 필드를 생성시키고, 원문에 없으면 '없음'을 강제하며 매끄러운 산문을 금지한다 — 다듬어진 문장이 이해했다는 착각을 만든다
  • MIT Media Lab의 인지 부채 연구(arXiv 2506.08872)를 근거로 경계선을 긋는다: 입력 처리(추출·변환·중복 탐지·링크 후보)는 전부 자동화, 출력(제목·claim·링크 결정)은 절대 자동화 금지
  • 인박스 WIP 상한 50개 + 30일 자동 아카이브 배수구, 그리고 순서가 고정된 45분 주간 리뷰(원문을 다시 열기 전에 claim부터 타이핑 = 인출 연습)
  • 에이전트 MCP 쓰기 권한은 00-inbox/와 10-sources/로만 제한 — 20-notes/에 모델이 직접 쓰기 시작하면 볼트는 두뇌가 아니라 출력 캐시가 된다

수집 → 소화 → 산출 파이프라인

수집은 이미 자동화됐고 산출은 여전히 수동이다. 볼트가 죽는 지점은 그 사이의 소화(digest) 다. 그러니 파이프라인의 목표를 "많이 모으기"로 잡으면 반드시 실패한다. 목표는 소화되지 않은 캡처가 산출로 새어나가지 못하게 막는 게이트를 세우는 것이다.

3단계를 폴더와 frontmatter로 물리적으로 분리한다

vault/
├─ 00-inbox/     # 진입점 단 하나. 원본 그대로, 편집 금지
├─ 10-sources/   # 소화된 출처 노트 (1 출처 = 1 파일)
├─ 20-notes/     # 원자 노트 (1 주장 = 1 파일)
├─ 30-outputs/   # 글·제안서·PR 설명·발표
└─ _archive/     # 30일 넘게 raw 인 캡처의 강제 배수구
---
type: source
status: raw            # raw → digested → atomized
captured: 2026-07-31
via: web-clipper       # web-clipper|readwise|voice|meeting|chat|cc-session
url: https://...
digest_by: claude-opus # 기계 요약임을 표시(사람 문장과 섞이면 신뢰가 무너진다)
claim: ""              # 🔴 사람만 채운다. 비어 있으면 20-notes 승격 금지
---

claim이 이 시스템의 유일한 강제 게이트다. Obsidian Bases(1.9+ 코어 플러그인, .base 파일로 테이블/카드/리스트 뷰)로 status == "raw" AND captured < now-7d 필터 뷰 하나만 만들어 두면 주간 리뷰 화면이 공짜로 생긴다. 다만 Bases의 뷰 종류·롤업은 아직 제한적이라 복잡한 집계는 Dataview나 스크립트 몫으로 남는다.

입력 경로 7종 — 자동화 지점보다 실패 모드를 먼저 보라

경로 자동화 지점 도구·비용 실패 모드
웹 클리핑 Web Clipper Interpreter 템플릿에 {{"프롬프트"}} 삽입 무료, 모델은 BYO 키(Claude/Ollama 등) 기본 컨텍스트가 페이지 HTML 전체 → 토큰 낭비·환각. {{selector:article}}로 좁혀라. Ollama는 기본 컨텍스트 2048 토큰이라 긴 글에서 조용히 잘린다
하이라이트 Readwise → Obsidian 자동 동기화 Readwise $9.99/월(연납, $119.88/년), Reader 없는 Lite는 $5.59/월 하이라이트 100개가 노트 1개로 쏟아짐 = 읽지 않은 벽돌. 출처당 하이라이트 상한(예: 12개)을 스스로 걸어라
음성 메모 로컬 Whisper 전사 → 요약 whisper.cpp large-v3-turbo(약 6GB, v3 대비 ~5배 빠르고 WER 차이 평균 0.4%p 수준), MacWhisper €59 평생 / Superwhisper 무료~$8.49월·$249.99 평생 전사본을 그대로 볼트에 넣으면 검색 노이즈만 늘어난다. 전사 원문은 볼트 밖 ~/voice-raw/에, 링크만 노트에
회의록 Granola 등 자동 노트 → md 내보내기 Granola Business $14/인·월, Enterprise $35 공식 Obsidian 내보내기 경로는 없는 것으로 보인다(서드파티 스크립트 의존, 확인 필요). 벤더 락인 + 동의 없는 녹음 리스크
이메일·슬랙 MCP 커넥터로 스레드 읽기 → 결정만 추출 Slack/Gmail MCP 전체 스레드 저장은 유출 표면만 키운다. 저장 단위는 스레드가 아니라 결정과 그 근거
코드 세션 /export 또는 ~/.claude/projects/*.jsonl → md cc2md, claude-code-log 등 OSS 원본 JSONL은 수십만 토큰. 세션당 "무엇을 배웠나" 5줄만 남기고 나머지는 버려라
손 메모 데일리 노트 인박스 섹션 코어 플러그인 유일하게 자동화하면 안 되는 경로

요약을 시키지 말고 인터페이스를 시켜라

"요약해줘"는 최악의 프롬프트다. 읽을 필요가 없어 보이는 덩어리를 만들어 놓고 실제로는 아무도 안 읽는다. 대신 나중의 내가 검색·판단할 때 필요한 필드를 생성시킨다.

웹 클리퍼 템플릿(Interpreter):

{{"이 글에서 저자가 방어하는 반직관적 주장 1개를 한 문장으로.
그 주장에 대한 가장 강한 반례를 본문에서 찾아 인용(원문 그대로)+위치.
본문에 없으면 '반례 없음'이라고만 써라. 요약·배경설명 금지."}}

음성 메모(전사본 → Claude Sonnet, 저렴하고 충분):

전사본에서 (1) 결정, (2) 미결 질문, (3) 액션(담당·기한)만 뽑아라.
말한 그대로의 표현을 유지하고 매끄럽게 다듬지 마라.
세 범주 중 비어 있는 것은 "없음"으로 남겨라. 새 정보를 추가하지 마라.

코드 세션 로그(Opus급이 값어치를 하는 유일한 지점 — 인과 추론이 필요하다):

이 세션 로그에서 "시도 → 실패 → 원인 → 수정" 체인만 추출하라.
성공한 작업은 무시하고 막힌 지점만. 각 체인은 4줄 이내.
로그에 근거가 없는 추론은 [추정] 태그를 붙여라.

세 프롬프트의 공통 규칙: 원문에 없으면 "없음"을 출력하게 강제하고, 매끄러운 산문을 금지한다. 다듬어진 문장은 이해했다는 착각을 만든다.

원자 노트 쪼개기 — LLM에게 시킬 것과 절대 안 시킬 것

원자 노트의 기준은 길이가 아니다. "이 노트를 반박하려면 무엇을 보여야 하는가"에 답이 하나로 나오면 원자다. 답이 둘 이상이면 쪼갠다.

  • 시켜도 되는 것: 후보 분할 지점 제안, 기존 노트와의 중복 탐지(10-sources/와 20-notes/를 grep·임베딩으로), 링크 후보 나열, 용어 정의 추출, 형식 변환·번역.
  • 절대 안 시킬 것: 노트 제목, claim 한 문장, 링크를 실제로 걸지 말지의 결정. 이 셋이 인출 연습 그 자체다.

에이전트에게는 이렇게 시킨다: "10-sources/x.md를 분리 가능한 주장 후보 3~7개로 나누되 각 후보는 제목 없이 본문만 써라. 제목 자리에는 TODO: 만 남겨라." 제목 빈칸이 사람의 인출 트리거가 된다.

🔴 균형: 어디까지 맡기면 이해가 사라지는가

MIT Media Lab의 Your Brain on ChatGPT(arXiv 2506.08872, 54명·4세션)에서 LLM 그룹은 EEG 연결성이 가장 약했고, 직후에 자기가 쓴 글을 정확히 인용하지 못했으며, 소유감도 가장 낮았다. LLM→Brain 전환군은 알파·베타 연결성이 낮은 상태가 남았다 — 저자들이 말하는 "인지 부채"다. 에세이 과제·소규모 표본이라 일반화는 조심해야 하지만, 방향은 실무 감각과 일치한다.

실행 가능한 경계선은 하나다. 입력 처리는 전부 자동화해도 되고, 출력 한 문장은 절대 자동화하면 안 된다. 추출·변환·연결 후보 제시는 기계, 판단·명명·연결 결정은 사람. 하루에 사람이 손으로 써야 하는 최소량은 claim 필드 3개(약 60자×3)면 충분하다. 이 최소량조차 못 지키면 그날 캡처는 애초에 하지 말아야 할 것이었다.

인박스가 무덤이 되지 않게 — 주간 리듬

배수구 없는 인박스는 100% 무덤이 된다. WIP 상한 50개를 걸고, 넘으면 새 캡처를 막는 대신 오래된 것을 자동 아카이브한다.

# 30일 넘은 raw 캡처를 무조건 _archive/ 로 (삭제 아님, 검색은 됨)
find 00-inbox -name '*.md' -mtime +30 -exec mv {} _archive/ \;

주간 리뷰 45분, 순서 고정:

  1. (5분) Bases 뷰에서 status: raw 개수 확인. 증가 추세면 캡처 경로 하나를 끈다 — 늘리지 말고.
  2. (20분) 오래된 순 위에서 8개. 각각 claim 한 문장 직접 타이핑. 원문을 다시 열지 말고 먼저 써 본다(인출 연습). 안 써지면 그 캡처는 이해 못 한 것이니 _archive/행.
  3. (10분) claim이 채워진 것만 에이전트에 넘겨 원자 분할 + 중복 탐지. 제목은 사람이 붙인다.
  4. (5분) 20-notes/에서 이번 주 새 노트 2개를 골라 기존 노트와 링크 1개씩. 링크 못 걸면 고아 노트로 남겨라 — 억지 링크가 그래프를 망친다.
  5. (5분) 30-outputs/에 다음 주 산출물 1개의 제목만 적는다. 산출 없는 주가 3주 연속이면 파이프라인 전체를 멈춘다.

에이전트를 붙이려면 Local REST API 플러그인(127.0.0.1:27124)+MCP 서버가 표준 경로지만, 쓰기 권한은 00-inbox/와 10-sources/로만 제한하라. 20-notes/에 에이전트가 직접 쓰기 시작하면 볼트는 그 순간부터 당신의 두뇌가 아니라 모델의 출력 캐시다.

구조·메타데이터 설계 — LLM이 읽기 좋은 위키

Claude Code 같은 에이전트는 볼트를 Glob→Grep→Read 순으로 읽으므로, 폴더는 수명주기·태그는 상태·링크는 의미로 축을 분리하고 frontmatter를 8필드 이하로 고정하는 것이 탐색 비용과 스키마 드리프트를 동시에 줄인다. 자기완결적 제목·TL;DR·MOC·ASCII 파일명 같은 작성 규약과, 4단계 폴더·태그 폭발·이미지 전용 정보 같은 안티패턴의 실패 모드를 구체적으로 정리했다.

핵심 요점

  • 폴더=수명주기(inbox/projects/refs/incidents/archive), 태그=변하는 상태만, 링크=의미. 세 축에 같은 정보를 중복 인코딩하면 필터가 서로를 무효화한다. 폴더 깊이는 3단계까지.
  • frontmatter는 type/status/created/updated/source/tags/aliases/confidence 8필드에서 멈춘다. Obsidian 속성 타입은 6종뿐이라 타입이 섞이면 Bases 필터가 에러 없이 노트를 조용히 누락시키고, 필드가 늘수록 에이전트의 미기입률이 곱으로 커진다.
  • confidence(verified/reported/assumed)는 에이전트 자가생성 내용과 사람이 검증한 내용을 분리해 위키가 자기 환각을 재인용하는 것을 막는 최소 안전장치다.
  • 파일명은 ASCII kebab-case + 날짜 접두(2026-07-31-mqtt-cred-rotation.md), 한글 제목은 aliases로. macOS NFD 정규화 때문에 한글 파일명은 rg 검색이 조용히 0건을 뱉는다.
  • MOC의 가치는 정리가 아니라 탐색 홉 절감(grep 5~6회 → index.md 1회). 링크마다 '왜 여는지' 한 줄을 붙여야 실효가 있다. Google Cloud OKF(2026-06, v0.1)도 required=type 하나 + index.md/log.md 예약으로 같은 결론.
  • 1M 컨텍스트 시대에도 실사용 회수율은 400K 부근부터 저하(Opus 4.6 MRCR v2 76%)—'다 넣기'는 여전히 실패 전략이므로 구조 설계가 남는다.

구조·메타데이터 설계 — LLM이 읽기 좋은 위키

세 축을 섞지 마라: 폴더=수명주기, 태그=상태, 링크=의미

에이전트가 볼트를 읽는 방식은 사람과 다르다. Claude Code는 벡터 검색이 아니라 Glob → Grep → Read 순서로 접근한다. 즉 경로는 필터, frontmatter는 술어, 위키링크는 홉(hop) 이다. 같은 정보를 세 축에 중복 인코딩하면 필터가 서로를 무효화한다.

실무 규칙은 단순하다.

  • 폴더 = 수명주기. 주제가 아니라 "이 파일이 아직 살아있는가"로 나눈다.
  • 태그 = 상태/횡단 축. #blocked, #needs-review처럼 바뀌는 것만. 주제 태그(#ai, #robotics)는 폴더·링크와 3중 중복이므로 버린다.
  • 링크 = 의미. [[MQTT 크리덴셜 로테이션]] 처럼 관계는 링크로만 표현한다.
vault/
├── index.md            # 루트 MOC (에이전트 진입점)
├── inbox/              # 미분류. 에이전트 write 기본 경로, 7일 내 이동
├── projects/<slug>/    # 살아있는 것 (status 필드가 있는 문서)
├── refs/               # 잘 안 변하는 것 (런북·아키텍처·용어)
├── incidents/          # 날짜가 정체성인 것
└── archive/            # 죽은 것 (에이전트 기본 검색 제외)

깊이는 vault/projects/<slug>/note.md = 3단계까지. 4단계 이상은 금지한다 — 사람이 못 외우는 경로는 에이전트도 glob 패턴을 잘못 만든다. 폴더를 주제로 나눈 순간 "이 노트는 fleet인가 security인가" 분류 회의가 시작되고, 그 회의는 매번 진다.

frontmatter는 8필드에서 멈춘다

---
type: decision          # note | decision | runbook | incident | ref (5종 고정)
status: active          # draft | active | superseded
created: 2026-07-14
updated: 2026-07-31
source: https://github.com/org/repo/pull/142
tags: [mqtt, rotation]
aliases: [MQTT 크리덴셜 로테이션, mqtt cred rotation]
confidence: verified    # verified | reported | assumed
---

필드를 적게 유지해야 하는 이유는 미학이 아니라 드리프트 비용이다.

  • Obsidian 속성 타입은 Text / List / Number / Checkbox / Date / Date & time 6종뿐이고 tags·aliases·cssclasses는 예약어다(단수형 tag/alias/cssclass는 폐기됨). 한 필드에 문자열과 리스트가 섞이면 Bases 필터가 에러 없이 조용히 그 노트를 누락시킨다. 필드가 늘수록 이 확률이 곱으로 커진다.
  • 에이전트에게 12필드 스키마를 주면 6개는 채우고 6개는 빼먹는다. 빠진 필드는 "false"가 아니라 "unknown"인데, 쿼리는 그걸 구분 못 한다.
  • confidence는 이 중 가장 저평가된 필드다. 에이전트가 자기 추론으로 채운 문서와 사람이 로그로 확인한 문서를 구분하지 못하면, 위키는 몇 주 안에 자기가 만든 환각을 근거로 재인용한다. confidence: assumed인 노트만 주기적으로 훑는 것이 유지보수 루틴의 핵심이다.

updated 자동화는 Templater 또는 Linter 플러그인의 타임스탬프 갱신 옵션으로 강제한다. 손으로 갱신하는 필드는 3주 안에 거짓말이 된다. 대량 정비는 Frontmatter Operator 플러그인(LLM으로 누락 필드 생성 + 스냅샷 언두)이나 rg -l 'type: decision' --glob '*.md' 후 스크립트가 현실적이다. 뷰가 필요하면 Dataview 대신 코어 플러그인 Bases(1.9+, Table/Cards, 1.10에서 List/Map 추가)를 쓴다 — .base 파일에는 필터·컬럼 설정만 저장되고 데이터는 계속 마크다운에 남는다.

참고로 2026년 6월 Google Cloud가 발표한 OKF(Open Knowledge Format) 도 같은 결론에 도달했다 — 필수 필드는 type 하나, 나머지(title/description/tags/timestamp)는 선택, 예약 파일명은 index.md(탐색)과 log.md(변경 이력). 스펙 v0.1 단계라 채택 여부는 지켜봐야 하지만, "최소 스키마 + 링크 그래프"라는 방향은 확인 사살에 가깝다.

파일명이 첫 번째 검색 인덱스다

파일명은 grep 히트 시 에이전트가 본문을 읽기 전에 보는 유일한 신호다.

  • 2026-07-31-mqtt-cred-rotation-dual-write.md (O) — 날짜 접두는 정렬·중복방지, 뒤는 자기완결 서술.
  • 회의록.md, note-3.md, 2026-07-31.md (X)
  • 한글 파일명은 가독성은 좋지만 macOS의 NFD 정규화 때문에 rg '로테이션'이 조용히 0건을 뱉는 사고가 난다. 파일명은 ASCII kebab-case, 한글 제목은 aliases에 넣는 것이 안전하다. aliases는 사람 검색과 위키링크 자동완성을 동시에 살린다.

MOC·인덱스 노트: 홉 수를 줄이는 장치

MOC의 가치는 정리정돈이 아니라 탐색 홉 절감이다. 볼트 20개 파일을 grep으로 훑으면 5~6회 툴 호출이지만, 잘 만든 index.md 하나면 1회다. 단, 링크만 나열한 MOC는 목차일 뿐이다. 링크 옆에 한 줄의 "왜" 를 붙여야 에이전트가 열지 말지 판단한다.

## Fleet 데이터 평면
- [[device-gateway 개요]] — 로봇→서버 진입점. MQTT/WS 이중화 이유가 여기 있음
- [[mqtt-cred-rotation]] — ⚠️ 진행 중. 로봇 ~40대가 아직 구 크레덴셜 사용

LLM 친화 본문 7규칙

  1. 자기완결적 제목: ## 배경 (X) → ## 왜 MQTT 크레덴셜을 이중 발급했나 (O). 청크 단위로 잘렸을 때 제목만으로 맥락이 서야 한다.
  2. 맨 앞 TL;DR 3줄: 에이전트가 파일 head만 읽고 계속 읽을지 결정한다.
  3. 헤딩은 H2/H3까지만. H4 이하는 청킹에서 부모 맥락을 잃는다.
  4. 표 대신 리스트: 3열 이하·순수 대조는 표, 셀에 문장이 들어가면 리스트. 마크다운 표는 셀에 줄바꿈이 못 들어가서 정보를 압축하다 왜곡된다.
  5. 코드블록에 언어 태그 필수(```bash, ```yaml). 태그 없는 블록은 산문으로 오독되어 명령어가 그대로 재생성된다.
  6. 대명사 금지, 고유명사·날짜 반복: "그 서비스", "지난주" (X) → "mobio-device-gateway", "2026-07-14" (O).
  7. 파일 하나 1,500토큰 내외. 길면 쪼개고 MOC로 묶는다.

안티패턴과 실패 모드

안티패턴 실제로 터지는 방식
4단계 이상 폴더 에이전트가 glob 패턴을 틀려 "정보 없음"으로 답함
태그 폭발(200개+) 1회짜리 태그가 롱테일을 이뤄 태그 필터 자체가 무의미해짐
제목 없는 데일리노트 덤프 검색은 되는데 무엇에 관한 글인지 판단 불가 → 전문 로드 → 컨텍스트 낭비
이미지에만 있는 정보 아키텍처 다이어그램 PNG는 grep 대상이 아님. Mermaid 코드블록으로
관계를 폴더로 표현 노트가 두 프로젝트에 속하는 순간 복제본이 생기고 둘이 갈라짐

비용과 컨텍스트 예산

도구 비용은 낮다 — Obsidian 앱 자체는 무료, Sync $4/user/월(연간), Publish $8/사이트/월(연간)이고, 상업용 유료 라이선스($50/user/년) 의무는 2026년 초 폐지되어 자율 후원으로 바뀐 것으로 보인다(공식 확인 필요). 진짜 예산은 컨텍스트다. Opus/Sonnet 계열이 1M 토큰 창을 지원하고 Opus 4.6이 MRCR v2(1M 구간 8-니들)에서 76%를 기록했지만, 실사용 보고는 400K 부근부터 회수율 저하를 말한다. "다 넣으면 된다"는 전략은 여전히 틀렸고, 그래서 구조·메타데이터 설계가 남는다.

개인을 넘어 — 팀·조직 위키

개인 마크다운 볼트를 팀·조직 지식베이스로 확장할 때 깨지는 지점(오너십·신선도·권한)과 그 처방을 frontmatter 규약, CI 드리프트 게이트, 런북/ADR 구조, 접근 티어링, 내부 RAG 기대치 관리, git vs Confluence/Notion 트레이드오프로 정리한 섹션입니다. 벤더 홍보 수치보다 실패모드와 운영 한계를 앞세웠습니다.

핵심 요점

  • 개인 볼트가 팀에서 깨지는 지점은 링크 의미의 분화, 낡음 판정자의 부재, 읽기/쓰기 비대칭 세 가지 — 처방은 frontmatter를 태그가 아니라 owner·review_every·source_of_truth·code_paths를 담은 '계약'으로 쓰는 것
  • 코드↔문서 드리프트는 CODEOWNERS·경로 기반 필수 리뷰라는 결정론적 게이트를 1차로 두고, anthropics/claude-code-action@v1 같은 LLM 판정을 2차로 얹는다. LLM 레그는 프롬프트 인젝션(PR 제목·경로가 사용자 제어), 런 간 메모리 없음, false negative, 회당 $0.5~2 비용이라는 한계를 먼저 인정해야 한다
  • 접근 티어링은 frontmatter 태그가 아니라 디렉터리로 물리 분리해야 통한다. MCP를 붙이는 순간 볼트 루트가 곧 에이전트 읽기 범위이므로, restricted 자산은 마운트 루트 밖 별도 저장소에 두는 것만이 실제 통제다
  • 내부 RAG 봇 기대치는 벤더의 '95~98% 정확'이 아니라 containment 40~65% 벤치마크 기준으로 잡고, 출처 경로+last_reviewed 노출·stale 문서 인덱스 제외·실패 로그를 문서 백로그로 환류하는 루프를 붙인다
  • git 위키 vs Confluence/Notion은 좌석 비용(0 vs 약 $5~12 vs $10~20)보다 '비개발자 기여'와 '권한 세분화'가 실제 갈림길이다. 코드 종속 문서는 repo, 비종속 문서는 SaaS로 나누되 한 주제를 두 곳에 두지 않는다
  • 위키 무덤 처방: 진입점 1개, 파일명에 서비스명+증상(grep 우선), 중복은 병합 대신 superseded-by 리다이렉트, 오너에게 삭제 권한 명시, 방치 문서는 archive/로 인덱스 제외
  • 에이전트 지시문(CLAUDE.md·.claude/rules/)과 사람용 위키 문서를 분리하라 — 전자는 런타임 컨텍스트로 적재되어 비용·지시 준수도에 직접 영향을 준다(200줄 초과 시 준수도 저하, import도 launch 시 함께 로드)

개인을 넘어 — 팀·조직 위키

혼자서는 되던 것이 정확히 어디서 깨지는가

개인 볼트는 "암묵지는 내 머릿속에 있고, 노트는 그 인덱스일 뿐"이라는 전제로 굴러간다. 팀에 들어가면 그 전제가 세 지점에서 동시에 무너진다.

  • 링크의 의미가 갈라진다. [[캘리브레이션]]은 나에게는 하나지만, 임베디드 담당자·백엔드 담당자·PM에게는 서로 다른 세 개다. 개인 볼트의 위키링크는 조직에서 가장 먼저 부패한다.
  • 낡음의 판정자가 사라진다. 혼자면 "내가 안 건드린 지 오래 = 낡음"이 성립하지만, 20명이 읽고 1명이 고치는 문서에서는 아무도 판정을 못 한다. 내부 위키 실패는 랜덤이 아니라 content decay라는 예측 가능한 패턴이다 — 낡은 문서가 정확한 문서와 검색 결과에서 구분되지 않는 상태.
  • "모두의 책임 = 아무의 책임". HN의 사내 위키 스레드에서 반복되는 진단이 이거다. 문서를 가장 잘 쓸 사람이 문서에 가장 관심 없는 사람이다.

frontmatter를 계약서로 쓴다

태그가 아니라 계약으로 취급해야 자동화가 걸린다.

---
owner: "@srcho"           # 반드시 개인 1명. 팀 이름 = 아무도 아님
reviewers: ["@jaewon"]
tier: internal            # public | internal | confidential | restricted
review_every: 90d
last_reviewed: 2026-07-14
source_of_truth: code     # 코드와 문서가 충돌하면 무엇이 이기는가
code_paths:
  - services/ingest/api/routes/adapt_logs.py
status: active            # draft | active | deprecated | superseded-by
---

Obsidian이라면 이 위에 Bases(1.9에서 코어 플러그인으로 도입, .base 파일 또는 코드블록)로 "review_every 만료 문서", "owner 미지정 문서" 뷰를 만든다. 1.10에서 group by·컬럼 요약(Average/Latest/Empty 등)·List/Map 뷰가 붙어 별도 서버 없이 관리 대시보드가 된다. 단 Bases는 조회일 뿐 강제가 아니다. 강제는 CI에서 한다.

코드↔문서 드리프트: 결정론적 게이트가 1차, LLM은 2차

1차는 LLM이 아니다. CODEOWNERS로 docs/ 소유를 명시하고, 특정 소스 경로가 바뀐 PR에 문서 리뷰어를 필수 소환하거나 PR 템플릿의 "Documentation Impact" 섹션이 비면 머지를 막는다. 값싸고 결정론적이다.

2차로 LLM 판정을 얹는다. anthropics/claude-code-action@v1을 pull_request: closed(merged)에 걸어 diff와 문서를 비교하고, 드리프트가 있으면 docs/update-from-pr-* 브랜치로 후속 PR을 연다. 도입 전에 함정 세 개를 먼저 인정해야 한다.

  1. 프롬프트 인젝션 — PR 제목·본문·파일 경로는 사용자 제어 문자열이다. XML 델리미터로 감싸고 OWNER/MEMBER/COLLABORATOR로 실행을 제한한다.
  2. 런 간 메모리 없음 — 매 실행이 백지다. "지난번에 이건 갱신 불필요로 판정했다"를 기억하지 못하니 같은 노이즈가 반복된다.
  3. false negative — diff에 명시되지 않은 아키텍처 변화는 놓친다. 비용은 코드베이스 크기에 따라 회당 대략 $0.5~2 수준으로 보고된다.

런북과 ADR — 팀 위키가 실제로 값을 하는 두 곳

docs/runbooks/<서비스>-<증상>.md 한 파일에 결정 트리 + 복붙 가능한 커맨드를 첫 화면에 둔다. 산문 설명은 그 아래로 내린다. 새벽 3시에 읽히는 문서에 서론은 사치다.

ADR은 docs/adr/NNNN-*.md에 MADR 템플릿으로 시작하고, 필요해지면 adr-tools(bash 스캐폴딩)나 Log4Brains(마크다운 → 검색 가능한 정적 사이트)를 붙인다. 배포 경로가 서비스마다 다른 조직이라면 "왜 이 서비스만 develop 배포인가"를 ADR 없이 매번 재발굴하게 된다.

에이전트 관점에서도 이 둘이 컨텍스트 효율이 가장 좋다. 앞부분(런북 헤더·용어·불변 규칙)을 고정하면 prompt caching이 걸려 재읽기 비용이 크게 떨어진다.

접근 등급: 태그가 아니라 디렉터리로 자른다

public / internal / confidential / restricted 4티어가 사실상 표준이다. 핵심은 티어를 frontmatter 태그가 아니라 물리 경로로 표현하는 것.

vault/
  10-public/
  20-internal/
  30-confidential/
  99-restricted/     # 볼트 밖 별도 저장소 + .gitignore

MCP를 붙이는 순간(coddingtonbear의 Local REST API 플러그인 + MarkusPfundstein/mcp-obsidian, 또는 WebSocket 기반 obsidian-claude-code-mcp) 볼트 루트 = 에이전트의 읽기 범위가 된다. search/get_file_contents는 티어 태그를 존중하지 않는다. 정말 넘기면 안 되는 것(자격증명, 고객 PII, 미공개 M&A, 계약 원문)은 애초에 마운트 루트 밖에 둬야 통제된다. "AI 도구에 넣지 마세요"는 정책이지 통제가 아니다.

내부 RAG 봇: 숫자부터 정직하게

벤더 자료의 "도메인 질문 95~98% 정확"은 자기 보고 수치다. 운영에서 볼 지표는 오히려 containment rate 40~65%(2025 Gartner 인용 벤치마크)에 가깝다 — 셋 중 하나 이상은 사람에게 간다는 뜻이다. 이 기대치를 먼저 공지하지 않으면 봇은 두 달 안에 조롱거리가 된다.

실무 규칙 셋:

  • 답변에 **출처 파일 경로 + last_reviewed**를 반드시 노출. 근거를 못 대면 "모름"을 출력.
  • review_every 만료 문서는 인덱스에서 제외하거나 경고 배지.
  • 봇의 실패 로그가 곧 문서 백로그다. 국내 사례로 인시던트 14건에 대해 "에이전트를 일부러 실패시키고 부족한 지식을 전문가가 메우는" 사이클을 돌려 지식 신뢰도 1.5 → 4.4(5점 만점), 사이클당 5~6건 신규 지식이 발굴됐다는 보고가 있다(단일 사례라 일반화는 주의).

git 위키 vs Confluence/Notion

git + 마크다운 Confluence Notion
좌석 비용 사실상 0 (Obsidian은 2025-02 이후 상업용 무료, $50/user/yr는 선택 후원) Standard 약 $5.4~6.4, Premium 약 $10.4~12.3 /user/월 Plus $10, Business $20 /member/월(연납, AI·엔터프라이즈 검색 포함)
코드 인접성 PR 하나에 코드+문서 분리 분리
권한 세분화 repo 단위(약함) 페이지 단위 페이지/DB 단위
비개발자 기여 낮음 — 진짜 병목은 여기 높음 가장 높음

가격은 2026년 공개 리스트 요약이라 실제 견적·할인은 확인 필요. 현실적 분할은 코드에 종속된 것(런북·ADR·API·아키텍처)은 repo 안 git, 종속되지 않은 것(온보딩 체크리스트, 인사 정책, 회의록)은 Notion/Confluence. 지켜야 할 규칙은 하나뿐 — 한 주제를 두 곳에 두지 않는다.

"위키 무덤" 처방전

  • 아무도 안 읽음 → 진입점 하나. 00-index.md에 상위 10개 링크를 "무엇을 하려는가" 기준으로. 목차 트리는 진입점이 아니다.
  • 검색이 안 됨 → 파일명에 서비스명+증상(ingest-adapt-logs-502.md). 벡터 검색 이전에 rg 한 방이 통해야 한다.
  • 중복 문서 → 병합하지 말고 한쪽에 status: superseded-by: <경로>를 박고 리다이렉트. 병합은 안 끝난다.
  • 삭제 공포 → 오너에게 삭제 권한을 명시적으로 준다. 지울 사람이 없어서 쌓인다.
  • 반년 방치 → archive/로 이동하고 검색·RAG 인덱스에서 제외.

마지막으로 에이전트 시대의 추가 규칙 하나. 에이전트용 지시문과 사람용 문서를 섞지 마라. CLAUDE.md와 .claude/rules/는 런타임에 컨텍스트로 적재되어 비용과 지시 준수도에 직접 영향을 준다(200줄을 넘으면 준수도가 떨어지고, @import로 쪼개도 launch 시점에 함께 로드되므로 컨텍스트는 줄지 않는다). 사람이 읽을 산문은 위키에, 에이전트가 지킬 규칙은 경로 스코프 룰로 분리하는 것이 두 독자 모두에게 이득이다.

볼트를 밖으로 — 디지털 가든과 발행

볼트를 정적 사이트로 발행할 때의 도구 선택(Obsidian Publish $8~10/site/월 vs Quartz v5·Digital Garden 플러그인·mkdocs-material/VitePress/Starlight), frontmatter `visibility` 한 필드로 공개/비공개를 게이트하는 파이프라인, 그리고 사전 생성 Q&A를 인라인해 런타임 API 비용을 0으로 만드는 "오프라인 AI 코치" 구조를 다룬 위키 섹션. 장점 나열 대신 자산 강제 emit·백링크 누수·robots 색인 등 실패모드를 앞세워 서술.

핵심 요점

  • Quartz v5 기본 설정은 `remove-draft`만 켜져 있고 `explicit-publish`는 꺼져 있다 — 즉 아무 설정도 안 하면 볼트 전체가 발행된다. 개인 볼트는 이 기본값을 반드시 뒤집어야 한다.
  • 비마크다운 파일(이미지·PDF)은 publish/draft 필터와 무관하게 빌드 산출물에 그대로 포함된다. `ignorePatterns`와 `.gitignore` 양쪽에 넣지 않으면 첨부 폴더가 통째로 공개된다.
  • 공개 노트가 비공개 노트를 `[[위키링크]]`로 참조하면 본문은 안 나가지만 **제목은 나간다**(Quartz는 404 링크, Digital Garden 플러그인은 깨진 링크로 렌더). 발행 파이프라인에 백링크 누수 스캔을 게이트로 넣어야 한다.
  • 가격 비교: Obsidian Publish는 $8/사이트/월(연납)·$10(월납), Quartz·Digital Garden 플러그인·mkdocs 계열은 무료. GitHub Pages는 사이트 1GB·월 100GB 소프트 대역폭, Cloudflare Pages 무료는 월 500빌드·파일 2만 개 상한이라 첨부 많은 볼트는 파일 수에서 먼저 막힌다.
  • frontmatter `visibility: private|members|public` 한 필드를 기본값 private로 두고, rsync 스테이징 → gitleaks → 백링크 스캔 3단 게이트로 발행을 자동화한다. 폴더 이동은 백링크를 깨고 플러그인 UI 체크박스는 스크립트에서 읽을 수 없다.
  • 오프라인 AI 코치는 빌드 타임에 섹션별 Q&A를 생성해 JSON으로 인라인하고 런타임에는 클라이언트 키워드 매칭만 한다 — API 키 0·서버 0·트래픽 비례 과금 0. 대신 사전 생성 질문 밖은 답할 수 없으므로 폴백 문구와 섹션별 lazy fetch가 필수다.

볼트를 밖으로 — 디지털 가든과 발행

발행은 백업의 연장이 아니라 공격면(attack surface) 확장이다. 노트 3천 개짜리 볼트에서 200개만 공개하기로 했다면, 나머지 2800개가 새지 않는다는 걸 증명해야 하는 쪽은 당신이다. 이 섹션은 도구 비교보다 "무엇이 새는가"를 먼저 다룬다.

도구 선택: 4개 축으로 자른다

Obsidian Publish Quartz v5 Digital Garden 플러그인 mkdocs-material / VitePress / Starlight
비용 $8/사이트/월(연납), $10(월납) $0 (호스팅 비용만) $0 $0
위키링크·백링크·그래프 기본 제공 기본 제공 기본 제공 remark-wiki-link 등 직접 배선 필요
발행 게이트 앱에서 노트 선택 publish: / draft: 프론트매터 dg-publish: true 빌드 스크립트 직접 작성
락인 높음(호스팅 종속) 낮음(마크다운 그대로) 낮음(GitHub repo 경유) 낮음

의사결정 기준은 단순하다. 위키링크·백링크·그래프가 콘텐츠의 본질이면 Publish/Quartz/Digital Garden, 문서 사이트(사이드바·버전·검색)가 본질이면 mkdocs-material·Starlight. Starlight는 Astro 아일랜드 기반이라 프레임워크 중립이고 JS를 기본 0으로 내보내며, VitePress는 Vue 네이티브지만 사이드바가 자동 생성되지 않아 파일 추가마다 config를 손대야 한다. Digital Garden 플러그인은 "방치됐다"는 오해가 많은데 2026-07-30에도 v2.83.1이 릴리스됐다 — 다만 파생 프로젝트(Quartz Syncer, Enveloppe)가 늘어난 만큼 원본 고집할 이유는 없다.

Quartz는 v4(TypeScript quartz.config.ts)에서 **v5(YAML quartz.config.yaml + @quartz-community/* 플러그인)**로 넘어갔다. 기존 v4 설정은 그대로 안 넘어가니 이전 계획을 잡아야 한다.

npx quartz create
npx quartz plugin install --from-config
npx quartz build --serve

visibility 한 필드로 티어링

에이전트와 사람이 같이 쓰는 볼트라면 "발행 여부"를 노트 안에 두는 게 유일하게 확장되는 방식이다. 폴더 이동은 백링크를 깨고, 플러그인 UI 체크박스는 스크립트에서 못 읽는다.

---
visibility: private        # private(기본) | members | public
status: budding            # seedling | budding | evergreen
epistemic: "실측 2건, 일반화 근거 약함"
updated: 2026-07-31
coach_qa: true             # 오프라인 코치 Q&A 생성 대상
---

핵심은 **기본값이 private**이라는 것. Quartz 기본 설정은 정확히 반대다 — @quartz-community/remove-draft가 켜져 있고(draft: true만 제외), @quartz-community/explicit-publish는 꺼져 있다. 즉 아무것도 안 하면 전부 발행된다. 개인 볼트에서는 이 둘을 뒤집어라.

# quartz.config.yaml
ignorePatterns: [90-private, templates, .obsidian]
plugins:
  - source: "@quartz-community/explicit-publish"
    enabled: true          # publish: true 인 것만 통과

Obsidian Bases(코어 플러그인)로 .base 뷰를 하나 만들어 visibility == "public" and updated < 90일 전 필터를 걸면 "공개했는데 방치된 노트" 큐가 공짜로 생긴다.

새는 곳은 정확히 세 군데

  1. 비마크다운 자산은 필터를 통과한다. Quartz 문서가 명시한다 — 이미지·PDF 등 모든 비마크다운 파일은 필터와 무관하게 빌드 산출물에 포함되어 공개된다. attachments/에 계약서 PDF나 스크린샷(사내 대시보드, API 키가 찍힌 터미널)이 있으면 그대로 나간다. ignorePatterns와 .gitignore 양쪽에 넣어야 한다.
  2. 백링크가 비공개 노트를 폭로한다. 공개 노트가 [[2026 인수 협상 메모]]를 참조하면, Digital Garden 플러그인은 깨진 링크로 렌더하고(이슈 #609에서 아직 논쟁 중) Quartz는 404 링크를 남긴다 — 본문은 안 나가지만 제목은 나간다. 제목만으로 충분히 사고가 나는 조직이 있다.
  3. robots/색인. noindex 메타는 크롤러 제안일 뿐 접근 제어가 아니다. 진짜 비공개 티어가 필요하면 Cloudflare Access(Zero Trust)로 Pages 프로젝트 앞을 막고 이메일 OTP 정책을 거는 편이 _worker.js 자작 게이트보다 안전하다. 그리고 한 번 색인된 URL은 되돌릴 수 없다 — 재빌드해도 OG 이미지·캐시된 스냅샷은 남는다.

발행 파이프라인은 사람 눈이 아니라 게이트로 막는다.

# 1) 공개 대상만 스테이징
rg -l '^visibility:\s*public$' 10-notes -g '*.md' \
  | rsync -a --files-from=- . build/content/
# 2) 비밀값 스캔 (gitleaks: pre-commit용 밀리초 단위, MIT)
gitleaks dir build/content --redact --exit-code 1
# 3) 백링크 누수: 공개 문서가 참조하는데 스테이징에 없는 노트
rg -o '\[\[([^\]|#]+)' -r '$1' build/content | sort -u \
  | while read -r n; do [ -f "build/content/$n.md" ] || echo "LEAK-REF: $n"; done

CI에는 TruffleHog(800종 이상, AWS 키면 실제로 API를 때려 유효성까지 검증)를 추가로 물린다.

배포는 GitHub Pages(사이트 1GB, 월 100GB 소프트 대역폭)나 Cloudflare Pages(무료 월 500빌드, 파일 2만 개·유료 10만, 단일 파일 25MiB). 노트 수천 개 + 첨부가 있으면 Pages 무료의 2만 파일 상한에 먼저 걸린다.

가든 vs 블로그: 실무적 차이는 "수정 로그"

디지털 가든 철학(Maggie Appleton)의 핵심은 시간순이 아니라 위상(topography), 완성이 아니라 성장, 그리고 인식론적 상태(epistemic status)의 명시다. 🌱seedling / 🌿budding / 🌳evergreen 3단계는 장식이 아니라 독자에게 "이건 아직 믿지 마라"를 전달하는 계약이다. 블로그는 발행 시점이 진실의 시점이지만, 가든은 updated가 진실의 시점이다 — 그래서 가든에서 날짜를 숨기는 건 최악의 선택이다. 낡은 노트를 지우지 말고 상단에 "2026-03 이후 미검증"을 박아라.

오프라인 AI 코치: 런타임 비용 0의 구조

발행물에 챗봇을 붙이는 가장 흔한 실수는 브라우저에서 LLM API를 호출하는 것이다 — 키가 노출되거나 프록시 서버가 생기고, 트래픽에 비례해 과금된다. 정적 대안은 빌드 타임에 Q&A를 미리 생성해 페이지에 인라인하는 것이다.

  • 빌드: 섹션별로 예상 질문 6~10개를 뽑아 답변까지 생성 → qa/<section>.json
  • 런타임: 질문 입력 → 클라이언트에서 키워드/BM25 매칭 → 저장된 답변 표시. API 호출 0, 키 0, 서버 0
  • 생성 비용: Claude Code 등 구독 에이전트로 로컬 생성하면 API 과금은 0이다. API로 돌린다면 섹션 40개 × 8쌍 = 320쌍 기준 입력 ~1.3M·출력 ~160K 토큰이고, Sonnet 5($3/$15 per MTok)에 Batch API 50% 할인을 적용하면 1회 수 달러 수준이다. 컨텍스트가 반복되므로 프롬프트 캐싱(읽기 ~0.1배)도 같이 걸어라.
  • 한계: 사전 생성 질문 밖은 못 답한다. 320쌍 × 600자면 원문 ~190KB(gzip ~45KB)라 전역 인라인은 무겁다 — 섹션별 분할 + lazy fetch, 그리고 미스 시 "이 질문은 준비되지 않았습니다 + 관련 섹션 링크" 폴백을 반드시 둔다. 미스 질의 로깅은 정적 사이트에서 불가능하니, 필요하면 Workers 엔드포인트 하나만 따로 둔다.

발행 전 체크리스트

  • [ ] explicit-publish 켜짐 / 기본값 private 확인
  • [ ] attachments/가 ignore + gitignore 양쪽에 있음
  • [ ] gitleaks 게이트 통과, CI에 TruffleHog
  • [ ] 백링크 누수 스캔 0건
  • [ ] 재빌드 후 비로그인 브라우저로 OG 이미지·/sitemap.xml·/404 직접 확인 (grep 0건은 증거가 아니다)

적용 예시 카탈로그 — 직군별 실제 구성

직군별(엔지니어·창업자/PM·연구자·크리에이터·학생·전문직) 마크다운 볼트 구성을 폴더 트리·frontmatter·자동화 2종·실제 도구명·함정 중심으로 정리한 위키 섹션. 공통 원칙은 "폴더 구조 = 에이전트 읽기 범위(scope) 통제"이며, 각 직군마다 실패모드를 먼저 제시했다.

핵심 요점

  • 폴더 구조는 정리 취향이 아니라 에이전트 읽기 범위(scope) 통제 장치 — 1M 컨텍스트라도 볼트 전체 주입은 비용·정확도 양쪽에서 손해이며, 경로 인덱스 상주 + 본문 지연 로드가 정답이다.
  • 엔지니어: AGENTS.md(툴 중립)와 CLAUDE.md(참조만, 5k 토큰 이하) 분리 + 런북 frontmatter에 last_verified/verify_cmd를 두고 주간 크론으로 dry-run 검증. last_verified 없는 런북은 부채.
  • 창업자/PM: 의사결정 노트에 known_at_decision과 reversal_signal 두 필드를 강제하고, 인터뷰는 LLM 요약이 아니라 축어 인용을 정본으로 보존. 경쟁사 노트는 source_url+fetched_at 없으면 머지 금지.
  • 연구자: Zotero+Better BibTeX citekey를 파일명으로 고정하고 Zotero MCP는 read-only로 붙인 뒤, 인용 조작 방지는 프롬프트가 아니라 CI의 미해결 참조 빌드 실패로 처리.
  • 학생: LLM 대량 카드 생성이 최악의 패턴 — 신규 20장/일 상한을 걸고 에이전트는 카드 생성이 아니라 '설명 못한 지점 찾기'에 쓴다. Obsidian→Anki는 사실상 단방향이라 Anki 쪽 수정은 덮일 수 있음.
  • 컨설턴트/변호사: 폴더가 아니라 볼트=프로세스 분리 + 매터별 .claude/settings.json deny 규칙. 익명화 승격에는 사람 승인 게이트 필수이고, 데이터 격리는 프롬프트가 아닌 계약/플랜 수준 문제.

적용 예시 카탈로그 — 직군별 실제 구성

먼저 공통 실패모드부터. 폴더 구조는 정리 취향이 아니라 에이전트의 읽기 범위(scope)를 정하는 접근제어 장치다. Opus 5·Sonnet 5가 1M 컨텍스트라고 볼트 전체를 던지는 순간, 노트 300개(평균 1.5k 토큰)만으로 45만 토큰이 매 턴 흐르고(Opus 5 입력 $5/1M) needle 정확도는 오히려 떨어진다. 실제로 작동하는 구성은 전부 경로 인덱스만 상주 + 본문은 지연 로드(progressive disclosure) 형태다. 안정 프리픽스(에이전트 지시 파일 + 인덱스)는 프롬프트 캐시에 태워야 하며, Opus 5 기준 캐시 최소 프리픽스는 512토큰이다.

1. 소프트웨어 엔지니어 — 코드베이스 위키·런북·인시던트

repo/
├── AGENTS.md                 # 툴 중립(60k+ OSS 채택), 공통 규약
├── CLAUDE.md                 # 툴 전용. 본문 대신 @docs/... 참조만
└── docs/
    ├── adr/ADR-0007-event-bus.md
    ├── runbooks/rb-payment-timeout.md
    └── incidents/2026-07-12-lightsail-oom.md
---
type: runbook
service: payment-api
last_verified: 2026-07-12
verify_cmd: "kubectl -n pay rollout status deploy/api"
---

자동화 2종: (a) 세션 종료 훅 또는 /incident-postmortem 스킬로 인시던트 노트를 자동 초안화(타임라인은 커밋·로그에서 기계 추출, 원인 서술만 사람). (b) 주간 크론이 last_verified가 90일 지난 런북만 골라 verify_cmd를 dry-run — 통과하면 날짜 갱신, 실패하면 이슈 생성.
함정: CLAUDE.md 비대화. 5k 토큰을 넘기면 매 턴 과금되면서 지시 희석이 시작된다. 그리고 런북은 코드보다 빨리 늙는다 — last_verified 없는 런북은 문서가 아니라 부채다.

2. 창업자/PM — 리서치 허브·인터뷰·의사결정 로그

vault/
├── research/interviews/2026-07-18-acme-ops-lead.md
├── decisions/DEC-014-per-device-pricing.md
├── competitors/linear/2026-Q3.md
└── _bases/interviews.base      # Obsidian Bases: 표/카드 뷰

의사결정 노트에 반드시 넣을 두 필드: known_at_decision(당시 알던 것)과 reversal_signal(틀렸다는 걸 알려줄 지표). 분기마다 에이전트가 reversal_signal 발화 여부만 점검하면 의사결정 로그가 회고 자산이 된다.
도구: 미팅 노트 도구(Granola/Fathom류)에서 md 내보내기 → research/에 적재, Bases(1.9 표·카드, 1.10 리스트·맵)로 인터뷰 DB화.
함정: LLM 요약이 원문을 대체하는 순간 6개월 뒤 재분석이 불가능해진다. 요약은 파생물, 축어 인용(quotes_verbatim)이 정본. 경쟁사 추적을 에이전트에 맡기면 존재하지 않는 기능이 섞여 들어오니 source_url + fetched_at 없는 줄은 머지 금지.

3. 연구자/대학원생 — Zotero 연동·인용 관리

vault/literature/@vaswani2017attention.md   # 파일명 = BBT citekey
vault/reviews/RQ1-vla-generalization.md
vault/zotero/library.bib                    # BBT auto-export

스택: Zotero + Better BibTeX(citekey 안정화) → Obsidian Zotero Integration 또는 ZotLit(주석·하이라이트 임포트) → Zotero MCP(54yyyu/zotero-mcp, ZotPilot 등)로 Claude가 라이브러리를 직접 시맨틱 검색.
자동화: (a) BBT 자동 내보내기 .bib을 Pandoc/Quarto가 그대로 소비 → citekey 하나로 노트-원고-서지 일치. (b) 에이전트 규칙을 "라이브러리에 실재하는 citekey만 사용"으로 고정하고, CI에서 미해결 참조가 있으면 빌드 실패시킨다.
함정: 인용 조작은 프롬프트로 못 막는다. MCP는 read-only로 붙이고 검증은 빌드 파이프라인에서. 하이라이트 재임포트는 append-only로 — 덮어쓰기 설정이면 직접 쓴 주석이 조용히 사라진다.

4. 콘텐츠 크리에이터 — 소재 은행 → 발행

vault/
├── 00-bank/     # 1차 소재: 스크린샷, 로그, 실패담 조각
├── 10-drafts/  20-review/  30-published/

status: idea|draft|review|published, source_ids: [bank/2026-07-02-deploy-fail].
자동화: QuickAdd 매크로 + Templater로 캡처 1키; status: published 전이 시 Obsidian Git 커밋 → 정적 사이트(Cloudflare Pages/Workers) 배포. 칸반 플러그인 대신 Bases 뷰로 충분하다.
함정: 은행과 생성물을 물리적으로 분리하지 않으면 다음 초안이 자기 AI 초안을 재료로 삼아 평균으로 수렴한다. source_ids가 비어 있는 초안은 발행 금지 규칙을 두는 편이 낫다.

5. 학생 — SRS·Anki 연동

vault/courses/cs231n/lec07-cnn.md
vault/flashcards/            # 이 폴더만 싱크 대상

도구: Obsidian_to_Anki + AnkiConnect(로컬 8765), 폴더=덱 매핑이 필요하면 Yanki, 볼트 안에서 끝내려면 FSRS 계열 플러그인(FSRS-6). Anki 본체는 FSRS가 기본 스케줄러다.
함정: LLM로 카드 500장 뽑는 것이 가장 흔한 실패다. 카드 수는 리텐션을 만들지 않는다 — 신규 하루 20장 상한을 걸고, 에이전트는 카드 생성이 아니라 내 노트에서 내가 설명하지 못한 지점 찾기에 쓴다. 동기화는 사실상 Obsidian→Anki 단방향이라 Anki에서 고친 내용은 다음 싱크에 덮일 수 있다.

6. 컨설턴트/변호사 — 매터 격리

핵심은 폴더가 아니라 볼트(=프로세스) 분리다. 한 볼트를 여는 순간 검색과 에이전트 컨텍스트가 매터 경계를 넘는다.

~/vaults/firm-shared/   # 방법론·템플릿·익명화 사례
~/vaults/client-acme/   # 별도 볼트, 별도 세션, 별도 설정

매터별 .claude/settings.json에 deny: Read(../**)를 두고 MCP 서버도 매터 단위로만 붙인다. 매터 종료 시에는 익명화 승격 파이프라인(고유명사·금액 치환 → firm-shared/cases/)을 돌리되 사람 승인 게이트를 반드시 둔다. 요약본에도 식별정보는 남는다.
함정: 학습 제외·데이터 격리는 프롬프트가 아니라 계약·플랜 수준의 문제다(제로 리텐션 여부 확인 필요). 국내 변호사-의뢰인 비밀유지권의 2026년 개정 상태는 로펌 법무팀 확인이 필요한 영역이다.

비용·전제 (2026년 기준, 확인 필요 항목 포함)

항목 값
Obsidian 앱 무료, 볼트 수 무제한
Sync 약 $4/사용자·월(연납)
Publish 약 $8/사이트·월(연납)
상용 라이선스 $50/사용자·년 → 2026-02 이후 선택적이라는 보도, 확인 필요
Obsidian 공식 CLI 1.12(2026-02) 도입 보도, 100+ 명령. 자기 버전에서 --help로 확인

30일 구축 플레이북과 함정

아무것도 없는 상태에서 30일 안에 사람과 AI 에이전트가 같이 읽고 쓰는 마크다운 볼트를 세우는 주차별 플레이북을 폴더트리·frontmatter·명령어·실제 가격(Obsidian Sync $4/월, Claude Code Pro $20/월)과 함께 정리했다. 핵심은 기능 추가가 아니라 실패 6종(수집 강박·툴 호핑·과설계·플러그인 비대·죽은 노트·AI 위임)의 조기 경보 신호와 처방이며, 완주 기준은 "골든셋 20문항 중 16문항 통과"라는 측정 가능한 한 줄이다.

핵심 요점

  • 30일 완주 기준을 기능이 아니라 측정치로 고정한다 — 골든셋 20문항 중 16문항 통과, 캡처 3초·2키, 커밋 30회 이상. 여기 기여하지 않는 작업은 이번 달에 하지 않는다.
  • 1주차 플러그인 3개 상한(Obsidian Git·Templater·코어 Daily notes), 폴더 6개 고정, 2주차 캡처 경로는 정확히 2개(QuickAdd 매크로 + 터미널 alias). 원자 노트 제목은 명사가 아니라 주장문으로 쓴다.
  • frontmatter의 status/confidence는 사람용 장식이 아니라 에이전트 가드레일 — CLAUDE.md에 "confidence: low는 인용 금지"를 넣어 미완성 지식이 자신 있는 헛소리로 재생산되는 걸 막는다.
  • 4주차 에이전트 연결은 MCP보다 `cd ~/vault && claude`(Read/Grep/Glob)를 먼저 시도. MCP는 백링크·태그 그래프 인지가 필요할 때만 값을 하고 Obsidian 상주를 요구한다. CLAUDE.md는 200줄 이내, 볼트 통째 주입 금지.
  • 비용 현실: Obsidian 무료(상업용도 커머셜 라이선스 필수 아님) + Claude Code Pro $20 = 월 $20, Sync 추가 시 $24, Max 5x면 $104. 보안은 .private/ 분리 + gitleaks pre-commit, 이미 유출됐으면 로테이트 먼저 → filter-repo 나중.
  • 실패 6종 각각에 임계값 있는 조기 경보를 붙였다(인박스 30개, 폴더 3단계, 볼트 열기 3초, updated 90일 초과 60%, AI 생성 40%). ⑥ AI 위임은 가장 늦게·조용히 오며 방어선은 결론 문장을 직접 쓰는 습관과 골든셋 점수뿐이다.

30일 구축 플레이북과 함정

완주 기준부터 정하고 시작한다

30일 뒤 "그럴듯한 볼트"가 아니라 측정 가능한 세 가지가 있어야 한다. ① 검색 골든셋 20문항 중 16문항 이상을 에이전트가 볼트만 보고 맞힌다. ② 캡처에서 노트 생성까지 3초·2키 이내. ③ git log --oneline | wc -l이 30 이상(즉, 실제로 매일 뭔가 커밋됐다). 이 세 줄에 기여하지 않는 작업은 이번 달에 하지 않는다.

1주차 — 뼈대만. 플러그인 3개 상한

vault/
├── 00-inbox/     # 미분류. 하드캡 30개
├── 10-notes/     # 원자 노트. 폴더 중첩 금지(flat)
├── 20-daily/     # 2026-07-31.md
├── 30-refs/      # 원문 클리핑·인용
├── 90-moc/       # Map of Content
├── .private/     # .gitignore 대상
└── CLAUDE.md
cd ~/vault && git init && printf '.obsidian/workspace*\n.private/\n.trash/\n' > .gitignore
git add -A && git commit -m "vault: init"

플러그인은 Obsidian Git, Templater, 그리고 코어 Daily notes까지. Bases(1.9부터 코어 플러그인, 테이블/카드 뷰. List·Map 레이아웃이 추가된 정확한 버전은 확인 필요)는 3주차에 켠다. Dataview·Omnisearch·QuickAdd는 아직 아니다 — 1주차의 목적은 습관이지 기능이 아니다.

2주차 — 캡처 경로 2개 + 원자 노트 20개

캡처는 정확히 2개만 자동화한다. 3개째부터는 어디로 넣을지 고민하느라 캡처가 느려진다.

  1. 볼트 안: QuickAdd 매크로 + Templater. 단축키 하나 → 프롬프트 한 줄 → 00-inbox/에 타임스탬프 노트 생성.
  2. 볼트 밖: 터미널 원라이너를 alias로. note() { f=~/vault/00-inbox/$(date +%Y%m%d%H%M).md; printf -- "---\ntype: capture\ncreated: %s\n---\n\n%s\n" "$(date -Iseconds)" "$*" > "$f"; }

원자 노트 20개는 "20개를 쓰자"가 아니라 이미 아는 것 20개를 꺼내는 작업이다. 제목을 명사가 아니라 주장문으로 쓴다. VSLAM.md(❌) → VSLAM 루프클로저 실패는 대부분 조도 변화다.md(⭕). 주장문 제목은 나중에 검색·링크·에이전트 인용에서 전부 유리하다.

3주차 — frontmatter·MOC·골든셋

스키마를 지금 고정한다. 필드는 7개를 넘기지 않는다.

---
id: 20260731-vslam-drift
type: note          # note | ref | moc | daily | capture
status: seed        # seed | grown | stable
tags: [robotics/vslam, incident]
source: "[[30-refs/2026-07-mapping-postmortem]]"
confidence: medium  # low | medium | high — 에이전트가 인용 전 확인할 신호
updated: 2026-07-31
---

confidence와 status는 사람용 장식이 아니라 에이전트용 가드레일이다. CLAUDE.md에 "confidence: low는 근거로 인용하지 말고 사용자에게 확인을 요청하라"를 한 줄 넣으면, 볼트의 미완성 부분이 자신 있는 헛소리로 재생산되는 걸 막는다.

MOC는 주제당 1개, 총 5개 이하. 그리고 골든셋 20문항을 90-moc/eval.md에 표로 만든다. 앞으로 이 위키의 유일한 성적표다.

# 질문 정답 노트 통과
1 트롤리 조향이 핑퐁 칠 때 첫 확인 항목은? [[10-notes/조향-핑퐁-진단순서]] ✅

4주차 — 에이전트 연결

가장 먼저 시도할 것은 MCP가 아니라 **cd ~/vault && claude**다. Read/Grep/Glob만으로 대부분의 질의가 해결되고, 서버도 Obsidian 실행도 필요 없다. MCP 서버(예: Local REST API 플러그인을 요구하는 mcp-obsidian 계열)는 백링크·태그 그래프 인지가 필요할 때 — "고아 노트 전부 찾아줘"를 툴 호출 한 번으로 끝낼 때 — 값을 한다. 대신 Obsidian이 떠 있어야 하고, 이 생태계는 유동적이라 서버 선택은 착수 시점에 다시 확인하는 편이 낫다.

CLAUDE.md는 세션마다 전량 로드되므로 200줄 이내로 유지한다. 담을 것: 폴더 규약, frontmatter 스키마, "새 노트는 00-inbox/가 아니라 10-notes/에 주장문 제목으로", "삭제하지 말고 status만 낮춰라". 담지 말 것: 볼트 내용 요약(그건 Grep이 한다). Claude Code가 AGENTS.md를 네이티브로 읽지 않는 시점이라면 ln -s AGENTS.md CLAUDE.md로 겸용한다. 컨텍스트는 1M 토큰이지만 볼트를 통째로 밀어넣지 말 것 — 5~15개 노트만 읽게 하는 쪽이 싸고 정확하다. 한국어 토큰 환산은 추정하지 말고 count_tokens로 실측한다.

자동 갱신은 하나면 충분하다. 매주 금요일 claude -p "00-inbox를 비우고, 고아 노트를 90-moc에 편입 제안하고, eval.md 20문항을 실행해 실패 문항만 보고해줘"를 cron/launchd에 건다.

유지 리듬과 비용

  • 주간 30분: 인박스 0, 골든셋 5문항 스팟체크, 고아 노트 3개 처리, git log 확인.
  • 월간 60분: 골든셋 20문항 전체 재실행 → 실패 문항을 노트 보강 과제로, 플러그인 감사, gitleaks detect 전체 히스토리 스캔.
구성 월 비용
Obsidian(무료) + 로컬 git + GitHub 프라이빗 + Claude Code Pro $20 ($17 연납)
위 + Obsidian Sync(E2E 암호화, 버전 히스토리) $24 (Sync $4 연납 / $5 월납)
헤비 사용(Max 5x) $104 (Max 20x는 $200)
공개 발행이 필요하면 Publish +$8/사이트 (월납 $10)

Obsidian은 상업적 사용에도 커머셜 라이선스가 필수가 아니다(연 $50는 선택적 후원). 스크립트로 API를 병행한다면 Opus 5 기준 $5/$25 per MTok을 별도 계상한다.

프라이버시·보안 체크리스트

  • 민감정보 분리: 자격증명·인사·계약은 .private/(gitignore) 또는 아예 별도 볼트. Claude Code settings.json의 permissions.deny에 Read(./.private/**)를 명시한다.
  • git 히스토리 유출: gitleaks pre-commit 훅을 1주차에 건다. 이미 커밋된 비밀은 먼저 로테이트하고, 그 다음 git filter-repo/BFG로 히스토리 재작성 후 force-push. 순서를 바꾸면 의미가 없다.
  • 클라우드 전송 범위: 에이전트가 읽은 파일만 나간다. --add-dir로 홈 디렉터리를 붙이는 습관이 사고의 90%다.
  • 플러그인은 샌드박스 없는 임의 코드다. 커뮤니티 플러그인 설치는 곧 신뢰 결정이다.
  • Publish는 공개 웹이다. 볼트 전체 발행 금지, 발행 대상은 화이트리스트로.

🔴 흔한 실패 6가지 — 신호와 처방

실패 조기 경보 신호 처방
① 수집 강박 인박스 30개 초과, 2주 넘은 항목 존재 인박스 하드캡 30개. 초과하면 신규 캡처 금지하고 먼저 비운다. 7일 지난 항목은 읽지 말고 삭제 — "언젠가 읽을 것"은 자산이 아니라 부채다
② 툴 호핑 30일 안에 Logseq/Tana/Notion 비교글을 또 읽고 있다 이관은 골든셋 정확도가 두 달 연속 하락할 때만. 마크다운+git이면 이관 비용은 항상 낮으니 지금 옮길 이유가 없다
③ 과설계된 분류체계 폴더 깊이 3단계 초과, 노트 쓰는 시간보다 템플릿 고치는 시간이 길다 폴더 6개 고정, 나머지는 태그·frontmatter·Bases 뷰. PARA/Zettelkasten을 원본 그대로 이식하지 말고 필드 3개만 빌려온다
④ 플러그인 40개 볼트 열기 3초 초과, 업데이트마다 뭔가 깨진다 분기 1회 감사 — 30일간 안 쓴 것 제거. 신규 설치는 "이게 없으면 어떤 워크플로가 죽는가"에 한 문장으로 답할 수 있을 때만
⑤ 한 번도 다시 안 읽는 노트 updated가 90일 초과인 노트가 60% 이상, 백링크 0 비율 상승 주간 리뷰에서 고아 노트 3개를 MOC에 편입하거나 삭제. 골든셋에 한 번도 등장하지 않는 영역은 애초에 쓰지 않는다
⑥ AI에 전부 위임 에이전트 요약을 인용하는데 원문 노트를 못 찾는다 / 내 어휘가 아닌 문장이 볼트를 채운다 에이전트는 초안·링크·정리까지, 결론 문장은 사람이. AI 초안은 status: seed 고정, 사람이 손대야 grown으로 승격. author: agent 필드로 비율을 재고 40% 넘으면 경고

⑥이 가장 늦게, 가장 조용히 온다. 볼트는 계속 커지는데 "내가 아는 것"은 줄어드는 구간이 반드시 오며, 그때 남는 유일한 방어선은 결론 문장을 직접 쓰는 습관과 골든셋 점수뿐이다.

이 글은 AI 리서치 파이프라인으로 작성되고 사람이 검수했습니다. 섹션마다 1차 출처를 표기합니다.