쌓인 노트를 지식으로 — LLM Wiki와 Graphify
노트가 쌓이기만 하고 연결이 안 보일 때, LLM을 편집자로 쓰는 방법. Karpathy의 LLM Wiki 개념과 Graphify의 그래프 컴파일이 셀포지의 지식 레이어가 되기까지.
- 배경: 노트를 부지런히 쌓아왔는데, 노트 사이의 연결은 사람이 직접 찾아야 했어요. 노트가 많아질수록 이게 점점 비현실적이 되더라고요
- 핵심 인사이트: LLM에게 “편집자” 역할을 맡기면 노트 정리 문제가 풀리는데, 노트가 수백 개로 늘어나면 LLM도 매번 전체를 읽을 수 없어요. 그래프로 한 번 컴파일해두면 이 문제가 사라졌어요
- 이런 분에게: 옵시디언이나 노션에 노트가 수십~수백 개 쌓여 있는데, “이걸 어떻게 활용하지?”라는 고민이 있는 분
노트는 쌓이는데, 연결은 안 보인다
노트를 열심히 쓰시는 분들이라면 이런 경험 한 번쯤 있을 거예요. 옵시디언에 노트가 50개, 100개 쌓여가는데… 그래서 뭐? 하는 순간이요.
셀포지에서도 같은 문제를 만났어요. 이전 편에서 소개한 것처럼, 텔레그램으로 생각을 던지면 자동으로 분류되고 옵시디언에 쌓이는 구조를 만들었거든요. 포착은 잘 되고 있었어요. 아이디어, 회고, 외부 자료 — 매일 몇 개씩 노트가 추가됐어요.
문제는 그다음이었어요. 이 노트들 사이에 어떤 연결이 있는지, 어떤 패턴이 반복되는지를 알고 싶은데, 그걸 사람이 직접 하려면 노트를 하나하나 다시 열어보고, 머릿속에서 연결을 만들어야 했어요. 노트가 10개일 때는 가능했지만, 30개가 넘어가면서 솔직히 엄두가 안 나더라고요.
비유하자면, 책을 열심히 사서 서재에 꽂아두긴 하는데, 어떤 책과 어떤 책이 관련 있는지 정리해주는 사람이 없는 상태예요. 서재가 작을 때는 기억으로 커버가 되는데, 서재가 커질수록 무슨 책이 어디 있었는지도 까먹게 되잖아요.
그래서 이런 생각을 하게 됐어요. 자동으로 노트를 돌아다니면서, 연결과 패턴을 찾아주는 존재가 있으면 좋겠다. 사서 같은 존재요. 매일 밤 서재를 정리하고, “이 책과 저 책이 같은 이야기를 하고 있어요”라고 알려주는.
구체적으로 말하면, 매일 새로운 캡처가 Self/Raw/와 External/Raw/에 쌓이는데, 이 노트들 간의 관계를 추출하고 연결하는 작업을 사람이 수동으로 하는 건 비현실적이었어요. 옵시디언의 [[링크]]를 직접 걸어주는 것도 한 방법이지만, 그건 결국 노트를 쓸 때마다 기존 노트를 기억하고 있어야 가능한 거잖아요.
필요한 건 두 가지였어요:
- 노트 사이의 관계를 자동으로 추출하는 것
- 추출한 관계를 기반으로 읽을 수 있는 형태의 위키를 만들어주는 것
Karpathy의 LLM Wiki를 만나다
이 문제를 고민하던 중에 Andrej Karpathy가 공유한 “LLM Wiki” 아이디어를 발견했어요.
카파시의 아이디어는 단순해요. 노트 정리를 AI한테 맡기자는 거예요. 근데 단순히 “정리해줘”가 아니라, 역할을 명확하게 나눈 게 핵심이에요.
세 층으로 나뉘어요:
- Raw (원본) — 사람이 쓴다, AI가 읽는다
- Wiki (정리본) — AI가 쓴다, 사람이 읽는다
- Schema (규칙) — 둘이 같이 만든다
사람은 원본을 쌓기만 해요. AI는 그 원본을 읽고 위키백과 같은 정리본을 만들어요. 사람은 위키를 읽으면 되고요.
여기서 재미있는 비유가 있어요. AI의 역할이 “작가”가 아니라 **“편집자”이자 “사서”**라는 거예요. 새로운 걸 만들어내는 게 아니라, 이미 있는 것을 정리하고 연결하고 유지보수하는 거죠. 실제로 셀포지에서도 이 원칙을 그대로 가져왔어요. CLAUDE.md에 이렇게 적었거든요:
AI는 해석하지 않는다, 드러낸다 — 연결과 패턴을 표면화할 뿐, 의미 부여는 사용자의 몫.
AI가 “당신은 이런 사람이에요”라고 해석하는 게 아니라, “이런 주제가 반복되고 있어요”라고 사실만 드러내는 거예요. 거기서 뭘 읽어낼지는 내가 결정하고요.
Karpathy의 LLM Wiki 패턴을 리서치하면서 핵심으로 뽑은 세 가지가 있어요.
소유권의 비대칭 분리 (3-Tier Model)
| 계층 | 쓰는 주체 | 읽는 주체 | 변경 규칙 |
|---|---|---|---|
| Raw Sources | 사람 | LLM | 추가만 (불변) |
| Wiki | LLM | 사람 | 매 수집마다 갱신 |
| Schema | 협업 | 협업 | 점진적 진화 |
이 “교차 구조”가 핵심이에요. Raw는 사람이 쓰고 LLM이 읽고, Wiki는 LLM이 쓰고 사람이 읽어요. 이렇게 하면 원본이 오염되지 않아요. LLM이 Raw를 수정하는 일은 절대 없으니까요.
셀포지에서는 vault-note-guard.sh 훅으로 이 불변성을 강제하고 있어요. 에이전트가 Raw 파일을 수정하려고 하면 차단돼요.
Write-heavy, Read-cheap
비용 구조가 RAG와 정반대예요:
- RAG: 질문할 때마다 벡터 검색 + 조각 조합 (읽기가 비쌈)
- LLM Wiki: 노트를 수집할 때 위키를 갱신 (쓰기가 비쌈, 읽기는 저렴)
한 번 컴파일해두면 질문할 때는 이미 정리된 위키를 읽기만 하면 돼요. 이 구조 덕분에 자주 질문하는 것에 대한 부담이 줄어들어요.
Fan-out Ingest
소스 하나가 추가되면 10~15개 위키 페이지가 영향을 받아요. 요약 페이지, 개념 페이지, 비교 분석 등이 동시에 갱신되는 구조예요. 이걸 셀포지에서는 wiki-schema.md의 Ingest 프로토콜 9단계로 구현했어요.

“근데 이거, 노트가 많아지면 어떡하지?”
LLM Wiki 개념에 매력을 느끼고 셀포지에 적용하려 했는데, 한 가지 걸리는 게 있었어요.
Wiki Agent가 위키를 갱신하려면 Raw 노트를 읽어야 하잖아요. 근데 노트가 37개일 때는 괜찮았는데, 이게 100개, 300개로 늘어나면? AI가 매번 전체 노트를 처음부터 끝까지 읽어야 하는 거예요. 사서한테 “오늘 새 책 한 권 들어왔으니 서재를 정리해줘”라고 했는데, 매번 서재 전체를 처음부터 읽는 사서라면 좀 곤란하잖아요.
실제로 셀포지에서 실험해봤어요. 37개 노트에 같은 질문을 했을 때:
- 노트 전체를 직접 읽기: ~10,913 토큰 소모
- 나중에 도입한 Graphify 경유: ~2,274 토큰 소모 (4.8배 절감)
37개일 때는 “음, 4.8배면 나쁘지 않네” 정도였어요. 그런데 규모를 추정해보니 이야기가 달라지더라고요:
| 노트 수 | 직접 읽기 | Graphify 경유 |
|---|---|---|
| 37개 | ~10,913 토큰 | ~2,274 토큰 |
| 100개 | ~29,500 토큰 | ~3,000 토큰 |
| 300개 | ~88,500 토큰 | ~4,000 토큰 |
| 500개+ | 아예 불가능 | ~5,000 토큰 |

직접 읽기는 노트 수에 비례해서 커지는데, Graphify는 거의 일정해요. 노트가 500개를 넘으면 직접 읽기는 AI의 컨텍스트 윈도우를 초과해서 물리적으로 불가능해져요. Graphify는 5,000 토큰 정도로 유지되고요.
노트가 쌓일수록 가치가 복리로 커지는 구조예요. 지금 당장의 효과보다 미래를 위한 인프라 투자인 셈이죠.
구체적인 실험 조건을 볼게요. Sullivan 볼트의 37개 마크다운 파일에 “AI Native 근육이 왜 에이전트 설계, 콘텐츠 품질, 채용 패러다임 3개 영역을 관통하는가?”라는 질문을 던졌어요.
Method A (Raw 읽기): 37개 파일을 전부 LLM 컨텍스트에 넣고 답변 생성.
Method B (Graphify 쿼리): graph.json에서 관련 노드를 BFS(depth 3)로 탐색, 81개 노드 중 40개 관련 노드 + 44개 엣지만 추출.
결과:
| Raw 전체 읽기 | Graphify 쿼리 | |
|---|---|---|
| 입력 범위 | 37개 파일 전부 | 40개 노드 + 44개 엣지 |
| 총 문자 | 38,196 | 7,960 |
| 추정 토큰 | ~10,913 | ~2,274 |
| 절감률 | 기준 | 79% 절감 (4.8배) |
중요한 포인트는, Graphify 쿼리의 토큰은 코퍼스 전체 크기가 아니라 질문과 관련된 노드 수에 비례한다는 거예요. 그래서 코퍼스가 10배로 커져도 쿼리 비용은 거의 일정해요.
근데 솔직히, 37개 파일 규모에서 4.8배 절감은 “반드시 필요한” 수준은 아니에요. 10,913 토큰이면 Claude가 충분히 한 번에 읽을 수 있는 양이거든요. Graphify의 진짜 가치는 토큰 절감보다 다른 데 있었어요:
-
관계의 사전 추출: Raw를 읽으면 LLM이 매번 “이 파일과 저 파일이 어떻게 관련있지?”를 처음부터 추론해야 해요. Graphify는 관계 타입(
references,conceptually_related_to,semantically_similar_to)과 신뢰도(EXTRACTED/INFERRED)가 이미 태깅되어 있어요. -
반복 쿼리 비용: 같은 노트에 다른 질문을 5번 하면, Raw는 매번 전체 읽기로 ~55,000 토큰. Graphify는 쿼리만 바뀌니까 ~11,000 토큰.
-
스케일 대응: 노트가 500개를 넘으면 Raw 전체 읽기는 컨텍스트 윈도우를 초과해서 물리적으로 불가능해져요.
Graphify가 하는 일
그래서 Graphify가 뭘 하느냐면요. 노트 폴더를 통째로 넣으면, 노트들 사이의 관계를 자동으로 뽑아내서 지식 그래프로 만들어줘요.
핵심은 관계를 뽑을 때 얼마나 확실한지를 같이 표시한다는 거예요:
- EXTRACTED — 노트에 직접 언급돼 있는 관계. “이 글에서 저 개념을 참조했다”처럼 확실한 것
- INFERRED — AI가 추론한 관계. “이 두 노트가 비슷한 문제를 다루고 있다”처럼 합리적이지만 직접 언급은 없는 것. 얼마나 확신하는지 점수도 붙어요
- AMBIGUOUS — 확실하지 않은 것. “관련 있는 것 같은데 검토가 필요하다”
이 구분이 왜 중요하냐면, 나중에 위키를 만들 때 “이건 확실한 연결이야”와 “이건 추측이야”를 구분할 수 있거든요. 추측인 연결을 확실한 것처럼 쓰면 안 되니까요.
그리고 재미있는 기능이 두 개 있어요:
- God Node: 여러 노트에서 계속 등장하는 핵심 개념을 자동으로 찾아줘요. “이 주제가 당신의 생각에서 허브 역할을 하고 있다”는 신호예요
- Surprising Connection: 겉보기에 관련 없어 보이는 노트 사이에서 예상 밖의 연결을 발견해요. 이건 나중에 콘텐츠 소재로도 쓸 수 있어요
Graphify의 파이프라인은 2-pass 구조예요:
Pass 1 — 구조 추출 (결정론적, LLM 불필요) 코드 파일이 있으면 tree-sitter AST로 구조를 정확히 추출해요. import, 함수 호출 같은 관계는 파싱으로 100% 정확하게 뽑을 수 있으니까 LLM을 쓸 이유가 없어요.
Pass 2 — 의미 추출 (LLM 병렬) 마크다운, PDF, 이미지 같은 비정형 파일에서 개념과 관계를 추출해요. Claude 서브에이전트가 파일 묶음별로 병렬 실행돼요.
이 분리가 핵심 설계 판단이에요. 확실한 건 결정론으로, 불확실한 것만 LLM으로. 비용 효율과 신뢰도를 동시에 잡는 구조예요.
관계 신뢰도 분류
모든 엣지에 신뢰도가 태깅돼요:
EXTRACTED (confidence_score: 1.0)
→ 소스에서 직접 발견. import문, 인용, 명시적 참조.
INFERRED (confidence_score: 0.4~0.9)
→ LLM이 추론. 공유 데이터 구조, 간접 의존성.
→ 각 엣지마다 개별 점수. 0.5를 기본값으로 쓰지 않아요.
AMBIGUOUS (confidence_score: 0.1~0.3)
→ 불확실. 검토 필요 플래그.클러스터링
Leiden 커뮤니티 감지로 관련 노드를 묶어요. 임베딩이 아니라 그래프 토폴로지 기반이에요. 노드 간 연결 밀도만으로 클러스터를 찾는 거예요. 벡터 DB 없이 순수하게 연결 구조만으로 “이 개념들이 한 덩어리”라는 걸 파악해요.
산출물
| 파일 | 용도 |
|---|---|
graph.json | 관계 데이터. 기계(Wiki Agent)가 읽어요 |
GRAPH_REPORT.md | 분석 리포트. God Node, Surprising Connection 포함 |
graph.html | 인터랙티브 시각화. 브라우저에서 바로 열어요 |
SHA256 캐시를 쓰기 때문에 한번 추출한 파일은 변경되지 않는 한 재처리하지 않아요. --update 플래그로 변경분만 증분 처리하고요.

Raw에서 Wiki까지, 전체 흐름
이제 전체 그림을 볼게요. 셀포지에서 노트가 지식이 되는 과정이에요.
흐름은 이래요:
노트를 쓴다 (Raw)
↓
Graphify가 관계를 뽑는다 → graph.json
↓
Wiki Agent가 읽을 수 있는 위키를 만든다 → wiki/매일 자정에 이 과정이 자동으로 돌아요. 제가 하루 동안 노트를 쌓으면, 밤사이에 Graphify가 그래프를 갱신하고, Wiki Agent가 위키를 업데이트해요. 아침에 일어나면 어제 쓴 노트가 이미 위키에 반영돼 있는 거예요.
여기서 중요한 건 순서가 고정이라는 거예요. 항상 Raw → Graphify → Wiki Agent 순서로 돌아요. 역순은 없어요.
왜 이 순서가 중요하냐면, Graphify가 “이 노트가 어떤 노트와 관련 있는지”를 먼저 파악해줘야 Wiki Agent가 효율적으로 일할 수 있거든요. 37개 노트 중에서 새로 바뀐 부분과 관련된 5개 노트만 읽으면 되는 거지, 37개를 전부 다시 읽을 필요가 없어요.
그리고 위키가 두 개예요:
- 정체성 위키 (Vault A): 내 생각, 회고, 아이디어에서 만든 위키. “나는 어떤 주제에 관심이 많고, 어떤 패턴으로 사고하는가”를 보여줘요
- 지식 위키 (Vault B): 외부 자료에서 만든 위키. “이 분야에서 무슨 일이 일어나고 있는가”를 정리해줘요
나중에 콘텐츠를 만들 때 정체성 위키가 “각도”를 제공하고, 지식 위키가 “소재”를 제공해요. 이 조합이 시리즈 마지막 편의 주제예요.
디렉토리 구조
{VAULT}/
├── Raw/ # 사람이 쓴다 (불변)
├── wiki/ # Wiki Agent가 쓴다
│ ├── index.md # 네비게이션 허브
│ ├── log.md # append-only 감사 추적
│ ├── signals.md # 콘텐츠 신호 리포트
│ ├── .last_graph_snapshot.json
│ └── articles/
│ └── {page-name}.md # Wikipedia 스타일 페이지
└── graphify-out/ # Graphify 산출물
├── graph.json # 관계 데이터 (기계용)
├── GRAPH_REPORT.md # 분석 리포트 (사람용)
└── cache/ # SHA256 추출 캐시자정 크론의 흐름
매일 00:00에 sullivan-graphify 크론이 실행돼요:
- Vault A 그래프 업데이트:
/graphify {VAULT}/Self/Raw --update --no-viz - Vault B 그래프 업데이트:
/graphify {VAULT}/External/Raw --update --no-viz - graph.json 변경 감지: SHA256 해시를 이전 실행 값과 비교
- 변경된 Vault만 Wiki Agent 실행:
.wiki_enabled게이트 확인 후, 해당 Wiki Agent에 Ingest 프로토콜 수행 요청
변경 감지가 핵심이에요. 둘 다 변경 없으면 Wiki Agent를 아예 호출하지 않아요. 불필요한 토큰 소모를 막는 short-circuit 구조예요.
Graphify 스코핑이 Wiki Agent에 주는 이점
Wiki Agent가 전체 Raw를 다시 읽지 않아도 되는 이유가 여기에 있어요:
graph.json에서 changed_nodes 감지
→ 영향받은 커뮤니티 멤버 ID 계산
→ 해당 멤버의 source_file만 Read
→ affected_articles만 재작성볼트가 30개 파일 이상이면 이 스코핑이 필수예요. wiki-schema.md에도 명시되어 있어요:
볼트 ≥ 30 파일: 반드시 스코프 내로 제한
Graphify와 Wiki Agent의 역할 분리
| Graphify | Wiki Agent | |
|---|---|---|
| 본질 | 구조 컴파일러 (골격) | 서술 합성기 (살) |
| 연산 | 결정론 + 통계 | LLM 호출 |
| 질문 | ”무엇이 무엇과 연결되어 있나" | "왜 연결되었고 무엇을 의미하나” |
| 산출 | graph.json, GRAPH_REPORT.md | wiki/articles/*.md |
Graphify가 뼈대를 세우고, Wiki Agent가 살을 붙이는 거예요. 이 분리 덕분에 각자 잘하는 일에 집중할 수 있어요.
이 구조에서 얻은 것
돌이켜보면, 이 구조를 만들면서 가장 중요했던 판단은 세 가지였어요.
첫째, “겹치는 것 같다”는 프레이밍 문제일 수 있어요. 처음에 LLM Wiki를 도입하려 할 때, 설리반(사고 파트너)과 역할이 겹치는 것 같아 고민했거든요. 둘 다 “입력을 구조화한다”는 점에서요. 근데 자세히 보니 설리반은 실시간으로 사고를 확장하는 역할이고, Wiki는 축적된 노트를 비동기로 종합하는 역할이었어요. 표면적 행위가 같아도 본질이 다르면 레이어가 다른 시스템이에요.
둘째, 원본 패턴의 유스케이스를 확인해야 해요. Karpathy의 LLM Wiki는 연구자가 외부 자료를 정리하는 유스케이스에서 나왔어요. 그래서 “내 생각”과 “외부 자료”를 구분할 필요가 없었죠. 셀포지에서는 이 구분이 핵심이었어요. 남의 아이디어를 쓸 때는 Vault A(내 생각 창고)가 “각도”를, Vault B(외부 자료 창고)가 “소재”를 제공하거든요. 패턴을 빌릴 때는 원본이 풀지 않아도 됐던 문제를 식별하는 게 중요하더라고요.
셋째, 지금 효과가 작아도 인프라는 미리 깔아야 해요. 37개 노트에서 4.8배 절감은 솔직히 “있으면 좋고 없어도 되는” 수준이었어요. 근데 노트가 300개를 넘으면 Graphify 없이는 시스템 자체가 동작하지 않아요. 필요해졌을 때 설치하면 그때부터 그래프를 처음 구축해야 하니까 지연이 생기고요. 복리는 일찍 시작할수록 커지더라고요.
다음 편에서
이 글에서는 노트를 그래프로 컴파일하고, 그 그래프를 기반으로 위키를 만드는 구조까지 이야기했어요. 그런데 위키를 실제로 만드는 Wiki Agent의 이야기는 아직 못 했어요. “관계가 있다”는 걸 아는 것과, 그 관계를 “읽을 수 있는 글”로 만드는 건 다른 문제거든요.
다음 편에서는 Wiki Agent가 어떻게 Wikipedia 스타일의 아티클을 만들고, 위키의 품질을 스스로 점검하고, “이 주제가 익었다”는 시그널을 보내는지 이야기할게요.
이 시리즈의 다른 글
- 노트가 쌓이기만 한다 — Raw의 구조와 한계
- 쌓인 노트를 지식으로 — LLM Wiki와 Graphify
- 관계를 읽을 수 있는 위키로 — Wiki Agent
- 내 생각과 외부 지식이 만나는 순간 — Insight Agent
- 익은 지식이 콘텐츠가 되기까지 — 자산화 파이프라인