- HTML Ingest 레이어는 원문 HTML을 LLM-wiki Ingest flow가 다루는 claim/concept 파이프라인에 넣기 전, 본문만 추출·정규화하는 단일 전처리 계층 — 인터페이스(HTML in → 정규화 Markdown + 해시 out)만 고정이고 내부 구현체는 교체 가능
- 기존
LLM-wiki Ingest flow.md가 이미 markdown(A.md,B.md)부터 시작하는 claim 추적을 다루므로, 이 레이어는 그 앞 단계(HTML → 정규화된 markdown)만 담당하는 상보적 구조 - Karpathy의 raw→wiki→schema 3계층 패턴과 Glean의 하이브리드 검색 구조 중 레드팀에서 사실로 확인된 부분만 근거로 채택하고, 미검증 벤치마크 수치는 배제한 설계 기준
해당 개념이 필요한 이유
- LLM-wiki Ingest flow의 예시(
A.md,B.md)는 이미 깨끗한 markdown이라고 가정한다. 실제 원문이 HTML(공지사항, 고시, 게시판)일 때는 네비게이션·광고·사이드바가 chunk에 섞이거나 표·각주가 boilerplate와 함께 유실되는 문제가 그 앞 단계에서 먼저 발생한다 - 이 문제를 claim/concept 레이어 안에서 고치려 하면
stableChunkId,sourceHash같은 기존 추적 규칙과 충돌한다. HTML 정규화는 별도 레이어로 분리해 기존 pipeline은 그대로 두고 입력만 깨끗하게 만드는 것이 맞다 - Andrej Karpathy gist와
nashsu/llm_wiki저장소(레드팀 검증 완료)가 공통으로 Readability.js + Turndown.js 조합을 쓰는 것이 확인됐다 — 이 조합을 기본 구현체로 채택하되, 레이어 자체가 이 두 라이브러리에 종속되지 않도록 인터페이스만 고정한다
AS-IS
flowchart TD H["HTML 원문<br/>(네비게이션·광고·사이드바 포함)"] --> S1["step1 Discover/Classify<br/>(LLM-wiki Ingest flow.md)"] S1 --> S2["step2 Parse/Chunk<br/>heading 기준 분할"] S2 --> P["정제되지 않은 chunk"]
이 상태로 넘기면 생기는 문제: nav/ads가 chunk에 섞이고, 표·각주가 boilerplate와 함께 유실되며, heading 구조가 HTML DOM 순서에 그대로 종속된다.
TO-BE
flowchart TD subgraph NEW["HTML Ingest 레이어 (신규, 이 문서의 범위)"] H["HTML 원문"] --> N["본문 추출 + Markdown 정규화"] N --> HS["정규화 해시 계산"] end HS --> S1["step1 Discover/Classify<br/>(기존 LLM-wiki Ingest flow.md)"] S1 --> S2["step2 Parse/Chunk"] S2 --> S3["step3 Queue Wiki work"] S3 --> S4["step4 이후 동일<br/>(claim 생성 → concept wiki)"] classDef pluggable fill:#FEF3C7,stroke:#D97706,stroke-width:2px,stroke-dasharray: 5 5 class N pluggable
🟧 점선·주황 노드 = 구현체를 자유롭게 교체할 수 있는 지점(인터페이스만 고정). 나머지 실선 노드는 이 문서·기존 문서가 고정한 단계다.
HTML Ingest 레이어 상세
이 레이어의 책임은 하나다 — HTML을 받아 정규화된 Markdown과 해시를 낸다. 내부를 본문 추출/Markdown 변환 2단계로 나눌지 단일 구현체로 합칠지는 구현 선택이고, 레이어 경계와는 무관하다.
- 인터페이스: 입력은 HTML, 출력은 정규화된 Markdown 문자열 +
sourceHash(sha256) 하나뿐이다. 이 두 값만 맞으면 LLM-wiki Ingest flow의stableChunkId(sourcePath, sourceHash, ordinal, heading)규칙에 그대로 올라탄다 — 별도의 ID 체계를 만들 필요가 없다 - 기본 구현체: Readability.js(본문 추출) + Turndown.js(Markdown 변환) 조합.
nashsu/llm_wiki가 웹클리퍼에서 동일 조합을 쓰는 것이 레드팀 검증에서 확인됐다 - 처리 못 하는 것 (명시적 한계): JS로 렌더링되는 동적 페이지(헤드리스 브라우저 렌더링 필요), 페이지네이션된 목록(별도 크롤링 정책 필요)은 이 레이어의 책임 밖이며, 상위 수집기(크롤러/웹클리퍼)에서 먼저 해결돼야 한다
구현체는 교체 가능 — 성능에 직접 영향
레이어 인터페이스만 고정하고 내부 구현체를 바꾸면 본문 추출 정확도·표/각주 보존율·처리 속도가 달라진다. 표가 깨지면 A조 2항 같은 정확한 키워드 검색이 RAG, LLM wiki 관계의 FTS 레이어에서 무력화되므로, 구현체를 바꿀 때는 표 보존율을 회귀 확인 대상으로 삼아야 한다.
| 구현체 | 특징 | 비고 |
|---|---|---|
| Readability.js + Turndown.js | 본문 추출/Markdown 변환이 분리된 JS 2단계 조합 | nashsu/llm_wiki에서 실사용 검증됨 (기본값) |
| trafilatura | 본문 추출+Markdown 변환을 한 번에 처리하는 Python 단일 라이브러리 | 언어 감지·boilerplate 제거 내장 |
| unstructured.io | HTML 외 PDF/DOCX 등도 함께 처리하는 통합 파서 | 파이프라인은 무거워지지만 포맷 커버리지가 넓음 |
구현체를 바꾸더라도 위 인터페이스(HTML in → 정규화 Markdown + 해시 out)만 지키면 이후 LLM-wiki Ingest flow 단계는 전혀 수정할 필요가 없다.
전체 레이어 Wrap-up
기존 두 문서의 내부 로직은 그대로 두고, HTML Ingest 레이어를 맨 앞에 붙여 전체를 한 그림으로 정리하면 다음과 같다.
flowchart TD subgraph L_HTML["HTML Ingest 레이어 (신규 · 이 문서)"] H1[HTML 원문] --> H2["본문 추출 + Markdown 정규화"] --> H4[정규화된 Markdown + 해시] end subgraph L_CLAIM["Claim/Concept 레이어 (기존 · LLM-wiki Ingest flow.md)"] C1["step1~2<br/>Discover/Parse/Chunk"] --> C1Q["step3<br/>Queue Wiki work"] C1Q --> C2["🤖 step4~5<br/>LLM Generate/Validate"] C2 --> C3["step6~7<br/>wiki page + claims.json"] C3 --> C4["step8<br/>concept wiki 생성"] end subgraph L_INDEX["검색 인덱스 레이어 (기존 · RAG, LLM wiki 관계.md)"] I1[(Vector DB)] I2[(FTS 인덱스)] I3[(Graph DB)] end subgraph L_RAG["RAG 질의 응답 레이어 (기존)"] Q[사용자 질문] --> RT[Retriever] --> CTX[관련 Context 선택] --> ANS["🤖 LLM 답변 생성"] end H4 --> C1 C1 -. chunk/claim 텍스트 .-> I2 C2 -. claim 임베딩 .-> I1 C4 -. concept/관계 .-> I3 I1 --> RT I2 --> RT I3 --> RT CTX --> ANS classDef pluggable fill:#FEF3C7,stroke:#D97706,stroke-width:2px,stroke-dasharray: 5 5 classDef llmUsed fill:#DBEAFE,stroke:#2563EB,stroke-width:2px class H2 pluggable class C2,ANS llmUsed
-
🟧 점선·주황 노드(
H2)는 위 TO-BE 다이어그램과 같은 의미 — 구현체 교체 가능 지점이다 -
🤖 파란 노드(
C2,ANS)는 로컬 LLM(Gemma/Qwen)이 실제로 호출되는 단계다. 나머지는 청킹·큐잉·파일 쓰기·그룹핑처럼 결정론적 코드 처리이며,I1(Vector DB)의 임베딩 계산도 별도의 임베딩 모델을 쓰는 것이라 이 뱃지 대상이 아니다 -
왼쪽 두 subgraph(
L_HTML,L_CLAIM)가 “지식 구축” 축이고, 오른쪽 두 subgraph(L_INDEX,L_RAG)가 “질의 응답” 축이다 — 이 구분은 RAG, LLM wiki 관계에 이미 있던 구조를 그대로 따른 것이다 -
L_HTML은 이 문서가 추가하는 유일한 신규 박스이고, 나머지 3개는 기존 문서를 참조만 한다 — 내부 단계(step1~8, claim 병합 로직, concept grouping)는 LLM-wiki Ingest flow를 그대로 본다 -
step3 Queue Wiki work는 LLM-wiki Ingest flow 원본에서 “backend 전용 내부 큐 단계”로 설명된다 — chunk가 바로 LLM 호출로 이어지지 않고 이 큐를 거쳐 순차 처리·크래시 복구가 가능해진다. 원본 문서는 visualizer 설명을 단순화하려 이 단계를 생략했지만, 이 문서는 첫 독자가 번호 순서만 보고도 흐름을 따라갈 수 있도록 그대로 표시했다
모델 업그레이드 시 재처리 범위와 기존 한계의 연결
LLM-wiki Ingest flow의 “13. 현재 방식의 한계”는 A.md의 chunk 1개만 바뀌어도 source 전체 claim이 재생성된다는 문제를 다루고, 해결 방향으로 dependsOnChunks 필드를 제안했다. 로컬 LLM을 Gemma4 → Gemma5로 교체하는 상황도 구조적으로 동일한 문제다 — “내용이 바뀐 것”이 아니라 “그 내용을 합성한 모델이 바뀐 것”이 무효화 조건이 된다는 점만 다르다.
flowchart LR M["모델 교체<br/>gemma4 → gemma5"] --> V{"claim.synthModelVersion<br/>== 신규 모델?"} V -->|예: 이미 최신| K[claim 유지, 재처리 스킵] V -->|아니오: 구버전| S[claim stale 처리] S --> P["해당 claim만 LLM 재생성"] P --> U["wiki/claims.json 갱신<br/>synthModelVersion=gemma5"]
HTML Ingest 레이어(L_HTML)는 모델과 무관하므로 Gemma5로 바뀌어도 100% 캐시 재사용 — 재처리 대상이 아니다dependsOnChunks와 동급으로 claim에synthModelVersion필드를 추가하면, source-hash 교체(내용 변경)와 model-version 교체(품질 개선)를 같은 무효화 메커니즘으로 처리할 수 있다 — 이전 대화에서 나온 “버전 태깅” 권고가 실제로는 이미 설계된 chunk dependency 구조의 확장판인 셈이다
검증된 사실 vs 미검증 주장 (레드팀 필터)
이 레이어 설계에서 실제로 근거로 쓴 것과 배제한 것을 구분해 둔다 — 인용 시 이 표를 기준으로 한다.
| 주장 | 판정 | 이 설계에서의 사용 |
|---|---|---|
| Karpathy raw→wiki→schema 3계층, ingest/query/lint 연산 | 사실 (gist 원문 확인) | L_HTML→L_CLAIM 분리의 이론적 근거로 채택 |
llm_wiki(nashsu)가 Readability.js+Turndown.js+MCP 사용 | 사실 (README 원문 확인) | HTML Ingest 레이어의 기본 구현체 선택 근거로 채택 (교체 가능) |
| Glean 하이브리드 검색(벡터+어휘) + 권한 인지 크롤링 | 사실 (공식 블로그 확인) | L_INDEX가 Vector+FTS+Graph 3종을 유지하는 근거로 채택 |
| Qwen3-30B RAGAS faithfulness 0.91 | 검증 불가 (출처 불명 마케팅 글) | 모델 선택 근거로 사용 금지 — 골든셋 자체 측정으로 대체 |
| Kairntech Qwen-2.5 온프레미스 사례 | 부분 사실 (자사 SEO 블로그 한 줄) | “사례가 있다”는 정도로만 인용, 효과 수치로 인용 금지 |
| 온프레미스 손익분기 가동률 50~83% | 부분 사실 (AWS 한정 벤더 블로그) | TCO 논의의 참고치로만 사용, 확정 수치로 인용 금지 |
참고 문서
- LLM-wiki Ingest flow — chunk/claim/concept 추적 상세, claims.json 병합 로직
- RAG, LLM wiki 관계 — Vector/FTS/Graph DB와 RAG 질의 응답 구조
- Karpathy, “LLM Wiki” gist (2026-04-04)
- nashsu/llm_wiki README
- Google Cloud Blog — Glean uses BigQuery and Google AI to enhance enterprise search