Skip to content
게으른 엔지니어의 기술 블로그
Go back

AI Wiki(ikeniborn)를 파보니 — API 키를 data.json에서 뺀 이유

비슷한 옵시디안 플러그인 여섯 개를 파보니 · 2/7편

지난 글에서 가장 크고 활발한 obsidian-llm-wiki를 봤다. 이번엔 스타 수는 훨씬 적지만(4개), 소스를 열어보니 진지하게 만들고 있다는 게 바로 느껴진 AI Wiki(ikeniborn)다.

9월 2일까지도 커밋되던 작은 프로젝트

9월 2일, GitHub API로 확인하니 4스타·0포크인데, 마지막 push도 바로 그날이었다. 스타 수와 실제 개발 강도가 꼭 비례하지 않는다는 걸 보여주는 사례였다.

docs/superpowers 폴더 — 같은 방식으로 만들어지고 있다

리포를 열어보고 놀란 게 하나 있었다. docs/superpowers/(plans, specs, notes, intents 폴더까지) 구조가 그대로 있었다. 이건 Claude Code의 superpowers 스킬(브레인스토밍 → 설계 문서 → 계획 → 서브에이전트 실행)로 개발할 때 생기는 산출물 구조다. 지금 이 플러그인도 같은 워크플로로 만들어지고 있으니, 겉보기엔 전혀 다른 프로젝트인데 개발 방법론 자체는 이미 같은 계보였다.

가장 실질적인 발견 — local.json 분리

main.ts를 읽다가 이 문장을 봤다.

“Rewrite local.json keeping only local-specific fields.” “Scrub apiKey from synced data.json — sensitive.”

Obsidian 플러그인의 data.json은 Obsidian Sync나 CouchDB(LiveSync) 같은 볼트 동기화 대상에 그대로 포함된다. AI Wiki는 API 키·프록시 인증정보처럼 민감한 값을 data.json과 분리된 local.json(디바이스 로컬에만 남고 동기화 안 됨)에 따로 저장한다. 실제로 코드에 마이그레이션 함수(migrateToLocalV1, migrateToLocalV2)까지 있어서, 예전 버전 사용자의 키도 자동으로 옮겨준다.

이걸 보고 지금 만드는 플러그인의 settings.ts를 다시 열어봤다 — apiKey, openaiApiKey, claudeApiKey가 전부 평범한 설정 필드로 data.json에 저장되고 있었다. CouchDB로 볼트를 동기화하고 있는 지금 구성에서는, 이 키들이 그대로 동기화 서버로 올라가고 있다는 뜻이다. 이름 고민보다 훨씬 급하게 손볼 부분을 여기서 찾았다.

마이그레이션을 아홉 겹으로 쌓았다

onload() 안에 순차 마이그레이션 함수가 거의 아홉 개 가까이 쌓여 있었다(migrateJsonlDomainStorage, migrateIndexFormat, migrateDropSections, migrateOkfFrontmatter…). 각각 개별 try/catch로 감싸서, 하나가 실패해도 Notice로만 알리고 나머지 마이그레이션은 계속 진행한다. 스키마가 자주 바뀌는 프로젝트에서 업그레이드 안전성에 신경을 많이 쓴 흔적이다.

컨트롤러 패턴 — main.ts는 얇게

obsidian-llm-wiki가 믹스인으로 main.ts를 부풀렸다면, AI Wiki는 반대다. 실제 로직(ingest/query/lint/init/exportOkf)을 전부 WikiController라는 별도 클래스에 몰아넣고, main.ts는 그 컨트롤러를 만들어서 커맨드에 연결만 하는 얇은 오케스트레이터다. 지금 만드는 플러그인의 main.ts(157줄, GeminiChatView에 위임) 구조가 오히려 이쪽에 더 가까웠다.

상태바에 LLM 신뢰도를 실시간으로 보여준다

structuralErrorCounter라는 구독 가능한 스토어가 있고, 이걸 상태바에 연결해서 “Schema: 0/0”처럼 구조화 출력이 검증 통과/재시도/ 실패한 개수를 실시간으로 보여준다. LLM이 스키마에 안 맞는 응답을 얼마나 자주 내는지 사용자가 항상 볼 수 있게 만든 UI였다 — 지금 만드는 플러그인엔 이런 상시 노출 지표가 없다.

배운 점

스타 수만 보고 넘어갔으면 놓쳤을 플러그인이었다. 실제로 코드를 열어보니 규모는 작아도 보안(local.json 분리)과 마이그레이션 안전성 양쪽에서 가장 신경 쓴 흔적이 많았다 — 특히 API 키 분리는 지금 만드는 플러그인이 바로 따라 해야 할 정도로 실질적인 차이였다.


Share this post:

비슷한 옵시디안 플러그인 여섯 개를 파보니

  1. 1. obsidian-llm-wiki(karpathywiki)를 파보니 — 임베딩 없이 그래프로 검색하는 이유
  2. 2. AI Wiki(ikeniborn)를 파보니 — API 키를 data.json에서 뺀 이유
  3. 3. AI RAG + LLM Wiki를 파보니 — 서비스 파일 30개짜리 설계가 하루 만에 버려졌다
  4. 4. Auto LLM Wiki를 파보니 — 바꾸기 전에 미리 보여주는 게 핵심이었다
  5. 5. Ziran LLM Wiki를 파보니 — 말로 설명하면 평가해주는 파인만 학습법
  6. 6. GenWiki를 파보니 — 1099줄짜리 파일 하나가 전부였다
  7. 7. 여섯 개를 다 보고 나서 — 지금 만드는 것과 비교해보니