태그: 지식관리 LLM RAG 데이터거버넌스 Markdown Obsidian PageIndex 멀티에이전트 데이터분석
흩어진 코드·노트·문서가 수만 개다. 새 도구를 켤 때마다 “그때 그거 어디 있었지”를 반복한다. 나는 이걸 임베딩 파이프라인 없이, 평문 Markdown만으로 LLM이 바로 읽고 검색하는 위키로 컴파일했다. 12년차 데이터 분석가가 자기 PC 한 대를 통째로 “LLM이 읽을 수 있는 지식베이스”로 바꾼 방법론 기록이다.
왜 — 수만 개 파일을 “LLM이 읽는” 상태로
데이터 분석가로 오래 일하면 부산물이 무섭게 쌓인다. 노트북(.ipynb), 스크립트, SQL, 분석 메모, 회의록, 옛 프로젝트의 README가 폴더 수십 군데에 흩어진다. 검색은 파일명·풀텍스트 grep으로 어찌어찌 되지만, 정작 묻고 싶은 건 그게 아니다. “예전에 리텐션 코호트 짤 때 어떤 가정을 썼더라”, “그 크롤러 레이트리밋 어떻게 처리했지” 같은 맥락 질문은 grep으로 안 나온다.
그래서 목표를 이렇게 잡았다. 내 자료 전체를, 새로 띄운 LLM 에이전트가 사전 학습 없이 바로 읽고 답할 수 있는 형태로 만든다. 흔히 떠올리는 답은 “임베딩 떠서 벡터DB에 넣고 RAG”다. 그런데 개인 PC 한 대 규모에서 그 구성은 과했다. 임베딩 서버, 청크 전략, 벡터 인덱스 운영, 재색인 비용 — 유지보수할 인프라가 늘어난다. 그리고 결정적으로, 내가 묻는 질문의 답은 대부분 “문단 하나” 또는 “표 한 개”에 들어 있다. 의미 유사도로 끌어오는 것보다, 잘 정리된 위키를 LLM이 직접 읽고 링크를 타고 들어가는 게 정확했다.
방향을 정한 데는 두 가지 참고가 컸다.
- Karpathy가 말한 패턴 — raw 자료를 LLM이 읽기 좋은 Markdown 위키로 “컴파일”한다는 발상. 원본은 그대로 두고, 그 위에 LLM 친화적 정리 레이어를 한 겹 올린다.
- 무벡터 검색(PageIndex류) 관점 — 임베딩 유사도 대신 문서 구조(트리/목차)와 문단·표 단위로 색인해 LLM이 탐색하게 하는 접근. K-IFRS처럼 정밀 인용이 필요한 도메인일수록, 흐릿한 유사도보다 구조 탐색이 낫다.
여기에 Obsidian 스타일을 입혔다. 모든 노트는 상단에 YAML frontmatter(메타데이터)를, 본문에는 [[wikilink]]로 노트 간 관계를 박는다. 결과적으로 별도 DB 없이 파일 시스템 자체가 그래프가 된다. 사람도 Obsidian으로 열어 그래프 뷰로 보고, LLM도 같은 평문을 읽는다. 포맷이 하나라 둘 다 행복하다.
구조 — 역할로 나눈 폴더 + 진입점 + 변경이력
핵심 설계 원칙은 하나다. 폴더는 “주제”가 아니라 “역할”로 나눈다. 주제로 나누면 한 주제가 여러 폴더에 걸쳐 금방 무너지지만, 역할(원본이냐 / 결정이냐 / 절차냐)은 안정적이다. 레이아웃은 이렇다.
knowledge_vault/
├── index.md # 단일 진입점 — 여기부터 모든 곳으로 링크
├── log.md # 변경 이력 (언제 무엇을 색인/수정했나)
├── sources/ # 원본에 가까운 정리본 (인벤토리·source 문서)
├── topics/ # 큰 주제별 통합 정리
├── concepts/ # 반복해서 쓰는 핵심 개념
├── decisions/ # 결정한 방향과 그 이유 (ADR 성격)
├── workflows/ # 실제 작업 절차 (재현용)
└── templates/ # 새 노트 작성용 양식
운영의 두 축은 index.md와 log.md다.
index.md= 단일 진입점. 새 LLM 세션은 무조건 여기부터 읽는다. “전체 마스터 요약 → 각 영역 인덱스 → 개별 노트”로 내려가는 계층 목차다. 사람으로 치면 위키의 메인 페이지다.log.md= 변경 이력. 언제 어떤 자료를 색인했고 무엇을 고쳤는지 시간순으로 남긴다. “이 볼트가 어느 시점 상태인지”를 LLM과 사람이 모두 신뢰하게 해준다.
노트 한 장의 양식은 frontmatter + 고정 섹션으로 통일한다.
---
id: stable-id # 변하지 않는 식별자 (링크 안정성)
type: topic # source / topic / concept / decision / workflow
title: 문서 제목
status: active # draft / active / archived
created: 2026-06-23
updated: 2026-06-23
tags: [llm-wiki, ...]
related: [] # [[wikilink]]로 연결되는 형제 노트
---
# 제목
## 요약 # 한두 문단 핵심
## 핵심 포인트 # 짧게. 원문 장문 복붙 금지
## 관련 문서 # [[wikilink]]
## 원천 근거 # 근거 파일/위치 (실제 값이 아니라 '어디에 있다')type을 frontmatter에 박아두면 LLM이 “지금 읽는 게 결정 문서인지 절차 문서인지”를 즉시 안다. 같은 내용도 역할에 따라 신뢰 수준과 인용 방식이 달라지기 때문에 이 한 줄이 의외로 크게 작동한다.
수집 방법 — 메타데이터 인벤토리 우선, 그다음 신호만 정독
수만 개 파일을 처음부터 다 정독하는 건 불가능하고 낭비다. 그래서 3단계 깔때기로 좁힌다.
1단계 — 재귀 메타데이터 인벤토리부터
본문을 열기 전에, 먼저 전체 트리를 메타데이터로 한 번 훑는다. 경로·크기·수정일·확장자를 긁어 한 장의 인벤토리(표/TSV)로 만든다. 본문 읽기 0줄로도 “여기 뭐가 얼마나 있는지” 지도가 먼저 나온다. 이게 모든 작업의 기준점이 된다.
# 개념 코드: 재귀 메타데이터 인벤토리
import os, csv
from pathlib import Path
EXCLUDE_DIRS = {".git", "node_modules", "__pycache__", ".venv", ".cache"}
CODE_EXT = {".py", ".ipynb", ".sql", ".md"}
def inventory(root: str) -> list[dict]:
rows = []
for dirpath, dirnames, filenames in os.walk(root):
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
for fn in filenames:
p = Path(dirpath, fn)
try:
st = p.stat()
except OSError:
continue
rows.append({
"path": str(p),
"ext": p.suffix.lower(),
"size": st.st_size,
"mtime": st.st_mtime,
"signal": p.suffix.lower() in CODE_EXT, # 1차 신호 후보
})
return rows2단계 — 신호 vs 보일러플레이트/노이즈 분류
인벤토리가 있으면 무엇을 깊이 읽을지를 데이터로 정한다. 직접 손으로 쓴 코드·노트는 신호다. 반면 의존성·캐시·빌드 산출물·자동 생성된 중복 파일은 보일러플레이트/노이즈라 메타데이터만 남기고 본문은 건너뛴다. 여기서 정한 몇 가지 운영 규칙이 비용과 안전을 동시에 잡아줬다.
- 심층 본문 읽기는 로컬에 실제로 내려와 있는 텍스트(MD·PY·IPYNB·SQL)로 한정. Office·PDF·이미지·압축·실행 파일은 메타데이터 중심으로만 다룬다.
- 클라우드 동기화 폴더의 “온라인 전용(on-demand)” 원본은 강제로 다운로드하지 않는다. 자동 정독이 대량 다운로드를 유발하면 즉시 중단한다. 본문 확인이 0건이어도 “온라인 전용이라 못 읽었다”고 사실대로 기록한다.
- 외장·보조 매체는 드라이브 문자로 추적하지 않는다. 연결할 때마다 문자가 바뀌기 때문에, 위치가 아니라 내용으로 식별한다. 같은 내용의 중복본과 비코드 미디어 더미는 위키에서 제외한다.
3단계 — 신호만 다중 에이전트가 정독해 source 문서 생성, 대용량은 1건으로 요약
신호로 추려진 묶음만 여러 LLM 에이전트가 폴더 단위로 분담해 정독하고, 각 묶음마다 sources/에 정리본 한 장을 남긴다. 한 에이전트가 수만 개를 순차로 읽는 것보다, 범위를 쪼개 병렬로 돌리는 게 빠르고 품질도 안정적이다.
특히 자동 생성물이 대량인 경우(예: 한 분석 프로젝트가 리포트 수백 장을 뱉어낸 경우)는 그걸 노트 수백 장으로 펼치지 않는다. “코퍼스 1건”으로 묶어 요약하고, 손으로 작성한 핵심 문서 몇 개만 따로 정독 대상으로 끌어올린다. 위키는 “전부 보존”이 목적이 아니라 “LLM이 빠르게 답하게”가 목적이라, 신호 대 잡음 비를 의도적으로 끌어올린다.
[전체 트리]
└─(1) 재귀 메타데이터 인벤토리 ──→ inventory.md (지도)
└─(2) 신호/노이즈 분류 ──→ 정독 대상만 선별
└─(3) 멀티 에이전트 정독 ──→ sources/<묶음>.md (정리본)
└─ 대용량 생성물 ──→ 코퍼스 1건으로 요약
거버넌스 — 정리 파이프라인에 “보안 위생” 단계를 내장
오래된 폴더를 정리하다 보면 반드시 마주치는 게 있다. 평문으로 박혀 있는 자격증명과 개인정보다. 옛날 스크립트에 하드코딩된 토큰, 설정 파일에 남은 시크릿, 누군가의 연락처가 든 데이터 — 정리를 하는 사람이라면 누구나 만난다.
여기서 핵심 원칙은 단순하다. 위키에는 실제 값을 절대 복제하지 않는다. “종류만” 표기한다. 즉 발견 사실을 기록하되, 값은 레닥션한다.
- 실제 키/토큰/비밀번호/쿠키/인증서 값은 볼트 어디에도 옮기지 않는다.
- 대신 “이 묶음에 어떤 종류의 비밀이 평문으로 있었다(예: API 키류·OAuth 시크릿류·세션 쿠키류·코드서명 인증서류)“라는 유형 라벨만 남긴다.
- 제3자 개인정보(이름·이메일·연락처·주소)는 유형조차 최소화해서, 노출 위치를 특정할 수 있는 단서를 남기지 않는다.
- 발견과 조치는
log.md와 해당 source 노트의 “자격증명·PII” 절에 기록해, 나중에 원본을 정리(키 회전·삭제)할 때 체크리스트로 쓴다.
이 단계를 “나중에 따로 하는 일”로 두면 반드시 빠진다. 그래서 정독 파이프라인 안에 보안 위생 단계를 내장했다. 에이전트가 본문을 읽다가 시크릿 패턴을 만나면, source 노트에 본문을 옮기는 대신 유형 라벨로 치환하도록 절차에 못 박았다. 정리하는 행위 자체가 동시에 보안 점검이 되게 만드는 것 — 데이터 거버넌스의 기본은 “수집 시점에 분류·레닥션을 강제”하는 것이고, 개인 볼트에도 그대로 적용된다.
면책: 위 원칙은 “내 자료를 안전하게 정리하는 방법론”이며, 구체적 발견 사례나 위치는 공개하지 않는다. 시크릿을 찾았다면 회전·폐기는 원본 쪽에서 처리할 일이지, 위키가 보관할 일이 아니다.
배운 점
무벡터로도 충분했다 — 단, 조건이 있다. 개인 PC 규모에서 임베딩 인프라 없이 평문 위키 + [[wikilink]] + 계층 인덱스만으로 LLM이 충분히 정확하게 답했다. 단 조건이 있다. 진입점(index.md)이 잘 정돈돼 있고, 노트가 문단·표 단위로 작아서 LLM이 한 번에 “정답이 든 조각”에 도달할 수 있어야 한다. 의미 유사도 검색이 빛나는 건 비정형 대규모 코퍼스이고, 잘 구조화된 개인 지식은 탐색이 임베딩을 이긴다.
maker ≠ checker. 정리본을 만든 에이전트와 검증하는 에이전트를 분리하는 게 품질에 결정적이었다. 만든 주체는 자기 요약을 의심하지 않는다. 별도 패스로 “이 source 노트가 인벤토리·원본과 일치하는가, 수치를 지어내지 않았는가, 시크릿이 새지 않았는가”를 다시 본다. 만드는 일과 검수하는 일은 다른 일이다.
메타데이터 인벤토리를 먼저 만들어라. 가장 크게 배운 건 이거다. 본문부터 읽으려 들면 길을 잃는다. 경로·크기·수정일·분류로 된 지도를 먼저 그리면, 무엇을 깊이 읽고 무엇을 건너뛸지가 데이터로 결정된다. 분석에서 EDA를 먼저 하는 것과 정확히 같다 — 전체 분포를 보기 전에 개별 레코드부터 파면 안 된다는 그 습관.
세 가지를 관통하는 한 줄은 이렇다. 지식관리는 저장 문제가 아니라 거버넌스 문제다. 무엇을 신호로 볼지(분류), 누가 검증할지(maker≠checker), 무엇을 남기지 말지(레닥션) — 데이터 거버넌스의 원칙을 개인 PC 한 대에 그대로 적용한 게 이 프로젝트의 핵심이었다.
마무리
정리하면 이 볼트는 재귀 메타데이터 인벤토리 → 신호/노이즈 분류 → 멀티 에이전트 정독 → 역할별 Markdown 노트(+[[wikilink]]) → 단일 진입점·변경이력 → 보안 위생 레닥션으로 흐른다. 벡터DB 한 줄 없이, 평문 Markdown만으로 수만 개 파일이 “LLM이 읽는 위키”가 됐다.
AI 시대에 차이를 만드는 건 결국 자기 자료를 거버넌스 가능한 형태로 다스리는 능력이라고 믿는다. 모델은 빌려 쓸 수 있어도, 내 도메인 지식의 구조는 내가 짜야 한다. 무엇을 남기고 무엇을 지울지, 그 판단이 분석가의 일이다.
관련 글·리포(placeholder):
- 자동화 레시피 모음: python-automation-100
- 콘텐츠 파이프라인(자막→블로그) 글: 본 블로그 SRT 자동변환 편 (placeholder)
- 무벡터 색인·PageIndex 관련 읽을거리 정리: 추후 공개 예정 (placeholder)