지난 글에서 정교하지만 하루 만에 버려진 프로젝트를 봤다. 네 번째는 이 시리즈에서 obsidian-llm-wiki 다음으로 스타가 많은(13개, 4포크) Auto LLM Wiki(youzhixiaomutou)다.
차별점은 검색이 아니라 문서 파싱이었다
package.json 의존성부터 남달랐다 — LLM SDK보다 @e965/xlsx,
jszip, mammoth, word-extractor, ppt-to-text 같은 문서
파싱 라이브러리가 더 많았다. 실제로 src/rawParsers.ts가 따로
있어서, 엑셀·워드·파워포인트 파일을 텍스트로 뽑아 인제스트하는
걸 핵심 기능으로 삼고 있었다. 다른 다섯 개는 대부분 마크다운(과
일부는 PDF)만 다루는데, 여긴 사무용 문서 포맷 전반을 커버 범위로
잡은 게 눈에 띄는 차이였다.
바꾸기 전에 미리 보여준다 — previewModal, changePlan
더 인상 깊었던 건 previewModal.ts와 changePlan.ts였다. AI가
위키 페이지를 만들거나 고치기 전에, “이렇게 바꿀 겁니다”라는 계획을
먼저 모달로 보여주고 사용자가 승인해야 실제로 파일이 바뀌는
구조였다. 지금 만드는 플러그인도, 그리고 이 시리즈의 다른 플러그인
대부분도 “인제스트 → 바로 파일 씀 → 다 끝나면 결과 리포트”인데,
Auto LLM Wiki는 “계획 → 승인 → 실행” 순서로 한 단계를 더 넣어뒀다.
AI가 노트를 잘못 병합하거나 엉뚱하게 나눠버리는 사고를 사전에
막는 데는 이쪽이 더 안전한 설계다.
Provider 추상화는 인터페이스 하나로 단순하게
providers/LLMProvider.ts라는 인터페이스가 있고 그걸 구현하는
providers/OpenAIProvider.ts가 있는 구조였다. obsidian-llm-wiki가
Vercel AI SDK라는 완성된 라이브러리로 멀티 프로바이더를 해결했다면,
여긴 직접 인터페이스 하나 정의하고 provider별 구현체를 하나씩
추가하는 훨씬 단순한 방식이다. provider 종류가 많지 않다면(README
기준으론 그렇게 많지 않았다) 이 쪽이 의존성도 적고 이해하기도
쉽다.
ChatController 인터페이스
class LLMWikiPlugin extends Plugin implements ChatController처럼
플러그인 클래스 자체가 별도로 정의된 ChatController 인터페이스를
구현하도록 짜여 있었다. 채팅 뷰(chatView.ts)가 플러그인 인스턴스를
구체 클래스가 아니라 인터페이스로만 참조할 수 있게 해서, 뷰와
플러그인 본체 사이의 결합을 느슨하게 만든 설계였다.
배운 점
이 플러그인을 보고 나서 “같은 컨셉이라도 어디에 힘을 주느냐가 완전히 다를 수 있다”는 게 제일 크게 남았다. 검색 정교함이나 프롬프트 설계가 아니라, “다루는 파일 형식을 넓히는 것”과 “AI가 실수하기 전에 사람이 검토할 기회를 주는 것” 두 가지에 집중한 선택이었다. 지금 만드는 플러그인도 “인제스트 후 결과만 리포트” 대신 “계획을 먼저 보여줄지” 한번 생각해볼 만한 지점이었다.