소개
20여 년 회사 생활 동안 쌓인 문서가 여기저기 흩어져 있었습니다. Dropbox, 로컬 PC, 외장하드, 구글드라이브에 나뉘어 있고, 폴더 이름만 봐서는 어디에 뭐가 있는지 알 수 없었습니다. 문제는 두 가지였습니다.
필요할 때 못 찾는다 — "그 견적서 어디 있더라"
여러 자료를 종합해 결론을 내기 어렵다 — 자료가 5개 폴더에 흩어져 있으면 전체 그림이 안 보인다
개인 자료(비망록·교회·재무)도 같은 상태였습니다.
RAG로 문서를 올려두고 질문하는 방식은 써봤지만, 질문할 때마다 처음부터 다시 찾는다는 한계가 있었습니다. 쌓이는 게 없었습니다.
그러던 중 Andrej Karpathy가 공개한 LLM Wiki 패턴을 봤습니다. 핵심은 이겁니다 — LLM이 마크다운 위키를 직접 쓰고 유지하게 하면, 지식이 질문할 때마다 재구성되는 게 아니라 누적되는 자산이 된다. 사람은 자료를 고르고 질문하고, 요약·교차참조·정리 같은 잡일은 LLM이 한다는 역할 분담도 마음에 들었습니다.
그래서 회사 업무용과 개인용 위키 두 개를 만들어봤습니다.
진행 방법
사용 도구
Claude Code (Opus) — 위키를 실제로 쓰고 유지하는 주체
Python 표준 라이브러리 +
openpyxl/pypdf/pymupdf— 엑셀·PDF 판독git — 위키가 마크다운이라 버전 관리가 공짜로 따라옵니다
시작 프롬프트
처음 던진 프롬프트는 이 한 줄이 전부였습니다.
https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f 읽고
나만의 llm wiki 구조를 만들어줘Claude가 gist를 읽고 도메인·저장 위치를 물어본 뒤, 저장소 뼈대를 만들었습니다.
구조 — Karpathy 원문은 3레이어, 저는 4레이어
원문은 raw(원본) / wiki(LLM이 쓰는 지식) / schema(운영 규칙) 3층입니다. 그런데 문서가 2만 건이 넘으니 전부 위키에 넣는 건 불가능했습니다. 그래서 층을 하나 더 얹었습니다.
1. 카탈로그 "어디 있는지" ← 파일 목록만 훑음. 토큰 0
↓ 선별 (사람이 덩어리 단위로 판단)
2. 원본 제자리에 그대로 ← 옮기지 않음
↓
3. 위키 "무엇을 아는지" ← 고른 것만 ingest
↑
4. 스키마 CLAUDE.md ← 운영 규칙서이 카탈로그 층이 이번 시도에서 가장 큰 수확이었습니다. 파일을 열지 않고 목록만 훑으니 2만 8천 건 스캔에 1분, 토큰은 0입니다. 그런데 "못 찾겠다" 문제의 절반이 여기서 바로 해결됐습니다.
실제 디렉터리
llm-wiki/
├── CLAUDE.md # 운영 규칙서 (핵심)
├── catalog/ # 원본 문서 목록 (스캔 산출물)
│ ├── work-dropbox.csv # 파일 1건 = 1행. 엑셀에서 열림
│ └── work-dropbox.md # 사람이 읽는 요약
├── index.md # 전역 카탈로그
├── log.md # append-only 연대기
├── raw/ # 원본 (불변)
├── wiki/
│ └── <도메인>/
│ ├── index.md
│ ├── sources/ # 소스 1개 = 페이지 1개
│ ├── entities/ # 사람·회사·제품
│ ├── concepts/ # 개념·패턴
│ └── syntheses/ # 질문에서 승격된 분석
├── templates/
└── tools/가장 중요한 건 CLAUDE.md
232줄짜리 운영 규칙서입니다. 이게 없으면 LLM은 그냥 챗봇이고, 있으면 규율 있는 위키 관리자가 됩니다. 핵심 규칙 몇 개만 옮기면:
## 3. INGEST — 새 소스 넣기
1. 읽는다
2. 논의한다 — 핵심 요지 3~5개를 사람에게 먼저 말한다
3. 도메인을 정한다
4. 소스 페이지를 쓴다
5. 파급 페이지를 갱신한다
- 한 소스가 5~15개 페이지를 건드리는 게 정상이다.
1개만 건드렸다면 교차참조를 놓친 것이다.
6. 모순을 처리한다 — 지우지 말고 ## 미해결 쟁점에 양쪽을 남긴다
7. 인덱스를 갱신한다
8. 원본을 처리한다 (카탈로그에서 찾은 소스는 옮기지도 복사하지도 않는다)
9. 로그를 남긴다
10. 보고한다
## 10. 절대 하지 말 것
- raw/ 안의 파일 내용 수정·삭제
- 인덱스·로그 갱신 없이 위키 페이지만 고치기
- 근거 소스 없이 사실을 단정하기 (근거 없으면 (추론) 표시)
- 모순을 조용히 덮어쓰기 — 항상 양쪽을 남긴다
- 사람 승인 없이 페이지 삭제·병합, 새 도메인 생성, 이 스키마 변경시행착오를 겪을 때마다 이 파일에 규칙을 추가했습니다. 그게 다음 세션으로 전달되는 유일한 방법이라서요.
도구 6종 (656줄, 표준 라이브러리만)
python tools/catalog-scan.py "<폴더경로>" --name <이름> [--class 회사]
python tools/catalog-find.py <낱말> [--구분 회사] [--ext xlsx] [--since 2020]
python tools/wiki-search.py "질의어" [--domain d] [--type concept]
python tools/wiki-lint.py
python tools/new-domain.py <slug> "<표시 이름>" "<한 줄 설명>"카탈로그 스캐너의 핵심 부분입니다. 파일을 열지 않고 메타데이터만 수집합니다.
def scan(root: Path):
rows, errors = [], 0
root = root.resolve()
for dirpath, dirnames, filenames in os.walk(root, onerror=lambda e: None):
dirnames[:] = [d for d in dirnames if d not in SKIP_DIRS]
d = Path(dirpath)
rel_dir = d.relative_to(root)
top = rel_dir.parts[0] if rel_dir.parts else "(최상위)"
for fn in filenames:
fp = d / fn
st = fp.stat() # 메타데이터만
rows.append({
"구분": CLASSIFY.get(top, "미분류"), # 회사/개인 자동 분류
"최상위폴더": top,
"경로": str((rel_dir / fn).as_posix()),
"파일명": fn,
"확장자": fp.suffix.lower().lstrip(".") or "(없음)",
"크기KB": round(st.st_size / 1024),
"수정일": datetime.fromtimestamp(st.st_mtime).strftime("%Y-%m-%d"),
})
return rows, errorswiki-lint.py는 위키 건강검진입니다. 기계가 할 수 있는 것만 잡고, 모순·낡은 주장 같은 의미 점검은 LLM이 따로 합니다.
frontmatter 누락 / slug 중복 / 깨진 [[링크]] / 고아 페이지 / 인덱스 미등재 / 400줄 초과 / 180일 미갱신스캔·검색 실제 화면
$ python tools/catalog-scan.py "C:/Users/Admin/Dropbox" --name work-dropbox --class 회사
스캔 중: C:\Users\Admin\Dropbox …
구분 '회사' 만 담는다
파일 6,316개 수집
→ catalog/work-dropbox.csv
→ catalog/work-dropbox.md
$ python tools/catalog-find.py 견적 --ext xlsx --since 2020
2026-07-29 [회사] 16KB 모던디앤씨 기타 견적현황 260413.xlsx
C:\Users\Admin\Dropbox\절삭공구\WORLDIA\...\모던디앤씨 기타 견적현황 260413.xlsx
2026-07-02 [회사] 10KB 견적검토 260702.xlsx
C:\Users\Admin\Dropbox\절삭공구\WORLDIA\...\미코세라믹스\견적검토 260702.xlsx
...
19건 중 상위 5건.📷 (여기에 캡처 삽입: 카탈로그 검색 결과 / Obsidian 그래프 뷰 / 위키 페이지 화면)
세션을 이어가는 방법
며칠에 걸쳐 작업하다 보니 대화를 새로 시작해도 이어지게 만들어야 했습니다. wiki/_meta/session-YYYY-MM-DD-<주제>.md에 「한 일 / 결정과 근거 / 현재 상태 / 다음에 할 일 / 재개하는 법」을 남기고, 다음 세션은 이 한 줄로 시작합니다.
CLAUDE.md 읽고 wiki/_meta/의 최신 세션 기록부터 이어서 하자결과와 배운 점
만들어진 것
회사 위키
개인 위키
커밋
9
17
위키 페이지
21
15
도메인
ESG, 기술
재무, 교회, 비망록
카탈로그
6,316건
15,194건
lint
ERROR 0
ERROR 0
도구 656줄, 운영 규칙서 232줄. 저장소 크기는 마크다운만 담아서 몇 MB입니다 (원본 바이너리는 gitignore).
실제로 나온 결과
숫자보다 이게 중요할 것 같습니다.
① ESG 진단 — 개선 우선순위가 뒤집혔습니다 협력사 ESG 진단 자료를 넣었더니 자가진단 397점 → 검증 359점이었습니다. 처음엔 "온실가스 측정이 +10점으로 최우선"이라는 결론이 나왔는데, 나중에 산업별 가중치(지배구조 53.96%)를 발견하고 다시 계산하니 온실가스는 +0.13점, 관리시스템이 +1.69점으로 완전히 역전됐습니다.
② 연금 계약 9건의 행방을 전부 찾았습니다 2023년과 2026년 통합연금포털 자료를 대조했더니 계약 5건이 "사라져" 있었습니다. 가입일이 열쇠였습니다 — 연금저축은 계좌이체를 해도 최초 가입일이 승계되는데, 그 날짜가 정확히 일치했습니다. 해지가 아니라 5개 기관에 흩어진 연금저축을 한 곳으로 통합한 것이었습니다.
③ 보험 대장이 5년 반 만에 현행화됐습니다 파일 폴더는 2020년 10월에 멈춰 있었는데, 협회 조회를 넣으니 폴더에 없던 유지 계약이 7건 나왔습니다.
④ 교회 자료 6,320건의 구조가 잡혔습니다 개별 문서를 한 건도 열지 않고 폴더·파일명만으로 두 폴더가 중복이 아니라 시기·역할로 갈렸다는 것, 20년 사역 이력을 정리했습니다.
시행착오 — 5가지 다 적습니다
1. 카탈로그 층을 처음부터 안 만들어서 사흘을 썼습니다 ESG 자료 5건을 전부 정독하는 방식으로 시작했습니다. 그런데 카탈로그를 만들고 나서 검색하니 더 최신인 2023년판 자료가 이미 있었습니다. 뭘 가졌는지 모르는 채 로 가진 것 중 일부만 붙들고 작업한 셈입니다. → 규칙화: "카탈로그를 건너뛰고 대량 문서를 바로 ingest하려 들지 말 것. 끝나지 않는다."
2. 가중치 없는 점수로 우선순위를 매겨서 결론이 뒤집혔습니다 66개 지표를 단순 합산하면 모든 지표가 같은 무게가 됩니다. 실제로는 산업군 가중치가 붙었고, 순위가 완전히 달라졌습니다. → 교훈: 1차 자료의 원시 숫자만 보지 말고, 그 숫자가 최종 결론으로 가는 산식을 먼저 확인할 것.
3. 파일명 기반 추론이 세 번 빗나갔습니다
개인정보 파일 10건으로 의심 → 실제로는 3건 (나머지는 "홍길동" 예시가 든 빈 서식)
보험 대장을 파일명으로 작성 → 협회 조회와 크게 다름
안전관리 기록 "2개월 공백" 발견 → 종이로 작성하고 계셨음 → 규칙화: "파일 목록에서 나온 판단은 항상 무엇이 파일로 남았는가이지 무엇을 했는가가 아니다. 파일 부재를 근거로 '안 했다'고 쓰지 말 것."
4. 전제를 확정하지 않고 시작해서 13개 페이지를 두 번 고쳤습니다 "SK 평가와 NICE 진단 중 어느 쪽이 공식인가"라는 전제가 흔들리면서, 위상 표기를 하루 사이에 뒤집었다가 되돌렸습니다. → 교훈: 새 도메인은 "이 도메인의 기본 전제"를 먼저 확정하고 ingest에 들어갈 것. 가장 비싼 건 자료 판독이 아니라 전제가 바뀌어서 다시 고치는 것입니다.
5. 세션 인수인계를 빼먹으면 하루가 뒤처집니다 대화를 지우기 전에 세션 기록을 안 남겼더니, 새 세션이 하루 전 지점에서 시작하려 했습니다.
꿀팁 3가지
① 스캔 PDF는 pymupdf로 렌더링 + 컨택트 시트 154페이지 스캔 슬라이드를 이미지 4장으로 압축해서 읽었습니다.
# 1) 텍스트 레이어 확인 — 슬라이드는 제목만 남아 있어 목차를 만들 수 있다
# 2) 본문이 벡터면 이미지 추출이 안 되므로 렌더링
d = fitz.open(pdf); d[n].get_pixmap(dpi=110).save("page.png")
# 3) 페이지가 많으면 저해상도 썸네일을 격자로 합쳐 한 장으로 훑고,
# 필요한 페이지만 원해상도로 다시 렌더링② 카탈로그 CSV는 gitignore, 요약 md만 커밋 5MB CSV가 스캔할 때마 다 통째로 바뀌면 git 이력이 부풉니다. 재생성에 1분이면 되니 요약만 남깁니다.
③ 원본은 옮기지 말고 경로만 기록 88GB를 복제할 이유가 없습니다. 소스 페이지의 origin:에 절대경로를 씁니다.
도움이 필요한 부분
비정형 개인 기록(비망록)의 페이지 구조를 어떻게 잡아야 할지 모르겠습니다. 현재 페이지 타입은
source / entity / concept / synthesis인데, 비망록의 단위는 사건과 시기라 잘 안 맞습니다.event타입을 추가할까 고민 중입니다.필기 앱 백업(
.nbk,.nsa) 같은 독자 포맷을 읽을 방법을 못 찾았습니다.위키가 수백 페이지로 커지면 인덱스+grep으로 부족할 텐데, qmd 같은 로컬 검색으로 갈아탈 시점을 언제로 잡아야 할지 궁금합니다.
앞으로의 계획
비망록 도메인 본격 착수 — 26년치
개인자료부터. 학습 이력(대학원 2번 포함)과 교회 사역 이력을 시간축으로 엮으면 뼈대가 나올 것 같습니다회사 문서 6,316건 중
KBM_경영4,312건(2004~2026, 20년치) 선별 ingestObsidian vault로 열어서 그래프 뷰로 보기
카탈로그를 외장하드·구글드라이브까지 확장
도움 받은 글
Andrej Karpathy, "LLM Wiki" — https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f 이 사례의 출발점입니다. 3레이어 구조와 ingest/query/lint 세 연산, index.md·log.md 규약을 그대로 가져왔습니다. 원문이 "구조는 도메인에 맞춰 각자 인스턴스화하라"고 명시하고 있어서, 카탈로그 층을 얹는 것도 그 취지에 맞다고 봤습니다.
qmd — https://github.com/tobi/qmd (마크다운 로컬 검색. 아직 안 썼지만 규모가 커지면 도입 예정)