정의
로컬 문서 그래프는 한 문서(루트)에서 출발해, related·wikilink 등으로 연결된 이웃을 **BFS(너비 우선 탐색)**로 최대 N홉까지 모은 노드·엣지 집합이다. 시각화는 force-directed layout(노드 간 인력·반발 시뮬레이션)으로 화면에 배치한다.
published/public 문서만 노드로 포함하고, draft·private는 그래프에서 제외해 독자에게 보이는 지식 지도만 보여준다.
왜 필요한가
TIL·Knowledge 상세는 본문 링크와 related 목록으로 관계를 텍스트로만 전달한다. 승격 경로·선행 지식·허브 문서를 한눈에 보려면 제한 깊이 그래프가 낫다. 전체 사이트 그래프가 아니라 현재 글 주변만 보여 주면 노드 수를 통제할 수 있다.
작성자에게는 고아 노드(이웃 없음)·과도한 허브(깊이 1에서 수십 엣지) 진단에도 쓰인다.
동작 원리
- RelationIndex: 빌드 시 frontmatter
related·본문 wikilink를 slug/type 기준 인접 리스트로 정규화. getLocalGraph(root, maxDepth): 큐 기반 BFS. depth 0 = 루트, 1~N홉 frontier 확장.- 필터:
isPublishedPublic(neighbor)false면 노드·엣지 스킵. - 엣지 dedupe:
source|target|kind정규 키(방향 무관 중복 제거). - UI: depth 슬라이더(1~3), 타입별 색, 루트 강조, 클릭 시 locale-aware router로 이동.
- 번들:
force-graph등 무거운 canvas는next/dynamic({ ssr: false })로 클라이언트 청크 분리.
실무 적용
graph.ts는 순수 함수 + Vitest(깊이·필터·dedupe·비공개 제외).DocumentGraphView는 props로LocalGraphData만 받고, canvas 컴포넌트는 dynamic import.- Playwright: 그래프 마운트, depth 변경,
prefers-reduced-motion스모크. - 노드
href는 문서 locale 유지 — i18n 라우터와 함께 검증. - 홈·stats 등 인접 UI 카피는
messages/*.json키로 분리.
트레이드오프
| 선택 | 장점 | 단점 |
|---|---|---|
| BFS 로컬 그래프 | 노드 수 예측 가능, 상세 페이지 맥락 유지 | 전역 지도·클러스터 분석 불가 |
| 전체 사이트 그래프 | 구조 한눈에 | 수백 노드·초기 로드·레이아웃 불안정 |
| 텍스트 related 목록만 | 가볍고 a11y 단순 | 밀도·경로 파악 어려움 |
| SSR canvas | SEO에 그래프 이미지 | force-graph는 window 의존 |
사용하면 안 되는 경우
- 관계 데이터가 없거나 related가 비어 있는 초안 문서(빈 그래프 UX 필요).
- 수천 노드 허브를 depth 3으로 열 때(폭발 — depth UI·상한 필수).
- 접근성만으로는 그래프가 필수 정보인 경우(텍스트 related 병행).
흔한 실수
- BFS 없이 1홉만 하드코딩해 "주변 지식"이 얕게 보임.
- draft 문서를 노드에 포함해 비공개 제목이 노출.
- force-graph를 페이지 상단에 동기 import해 LCP·TTI 악화.
- 양방향 엣지를 source/target 순서만 바꿔 두 번 렌더.
- plain
next/link로 노드 클릭 — locale 유실( i18n router 사용).
관련 개념
- hierarchical-document-navigation — 텍스트 목록 네비
- list-virtualization-windowing — 긴 목록은 그래프 대신 virtual list
- inverted-index-full-text-search — 전문 검색 인덱스(관계 축과 별개)