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

Obsidian에 LLM Wiki 만들기 3편 — 동적 뱃지와 dirty check, UX가 엔지니어링을 만날 때

이 글은 Obsidian에 LLM Wiki 만들기 시리즈의 3편이다.

노트 내용을 AI에게 보내주는 기능을 만들면서 든 생각이 있었다.

현재 열린 노트를 읽어 오는 기능적 구현이 필요하긴 한데, 내가 뭔가 물어 볼때마다 내용을 보내면 그것도 토큰을 쓰고, 분석에 시간을 낭비하는 것 같은데… 너 생각은 어때?

노트가 길면 그냥 “안녕” 한마디를 보낼 때도 노트 전체 분량이 매번 같이 날아간다. 토큰 낭비고, 응답도 느려진다.

1차 제안을 그냥 받아들이지 않은 이유

이 문제의 1차 대안은 두 가지였다. (A) [현재 노트 포함] 체크박스를 두는 방식, (B) @현재노트/note 같은 키워드를 감지해서 그때만 노트를 끌어오는 방식. 체크박스 쪽이 제어권이 명확하다는 이유로 A안이 추천됐다.

근데 그냥 받아들이지 않았다.

현재 파일 컨텍스트 포함이 아니라 현재 오픈된 파일의 이름을 표시하는게 더 명확하지 않을까? 그리고 내가 다른 파일을 오픈하면 그 이름이 맞춰서 변경되는 거지. 근데 이거는 한번 체크하고 해제 하는 것을 잊어 버릴 가능성도 상당히 높아서… 어떻게 하는게 좋을지 고민되네

정확한 지적이었다. 그냥 체크박스만 달아두면 두 가지 문제가 남는다 — 지금 어떤 파일을 대상으로 얘기하고 있는지 한눈에 안 보이고, 체크를 켜둔 채로 잊어버리면 엉뚱한 질문에도 노트 전체가 계속 딸려간다.

최종 설계: 일회성으로 스스로 꺼지는 뱃지

이 두 문제를 한 번에 해결하는 방식으로 정리됐다. 입력창 위에 [📄 현재파일명.md] 모양의 뱃지 버튼을 하나 만들고, 이렇게 동작하게 했다.

[ 평상시 대화 ] ──> 뱃지 꺼짐 (토큰 절약 모드)
[ 노트 기반 대화 ] ──> 뱃지 클릭 ──> 활성화, "이번 질문에만 파일 본문 포함"
[ 질문 전송 완료 ] ──> 전송과 동시에 뱃지 자동으로 꺼짐 (리셋)

두 가지가 핵심이다.

그다음 문제: “수정”을 어떻게 판단할까

노트를 매번 새로 보낼지 말지를 정하려면, “이 노트가 마지막으로 보낸 뒤로 실제로 바뀌었는가”를 판단해야 했다. 근데 여기서 또 다른 문제가 생긴다 — 문단 사이에 빈 줄을 하나 추가하거나 공백을 좀 더 넣는 것까지 전부 “수정”으로 치면, 별 의미 없는 변경에도 매번 노트 전체가 다시 날아간다. 그래서 무시해도 되는 변경(공백, 줄바꿈)과 진짜 수정(단어 추가/삭제, 오탈자 교정, #을 붙여 헤딩으로 바꾸는 것 같은 구조적 변화)을 구분하는 dirty check 알고리즘을 세웠다.

  1. 정규화 필터: 모든 줄바꿈·탭·연속 공백을 공백 하나로 합쳐서 비교용 문자열을 만든다. 첫번째 문단\n\n\n두번째 문단첫번째 문단\n두번째 문단은 정규화하면 똑같은 문자열이 되어 “변경 없음”으로 처리된다.
  2. 글자 수 + 해시 더블 체크: 정규화된 텍스트의 글자 수나 가벼운 체크섬을 비교해서 이전 상태와 완전히 같은지 확인한다.
  3. 저장 시점 디바운싱: Obsidian은 타이핑을 멈추고 1~2초 후에 자동 저장한다. 그 저장(modify) 이벤트가 뜨는 시점에 딱 한 번만 정규화 비교를 돌린다.

”이거 느려지는 거 아니야?”

당연히 나온 질문이었다.

이런 경우 이런 사전 체크가 문서 작성이나 채팅에 타이핑이나 기존에 다른 작업에 지연되는 것이 얼마나 될까? 이것 때문에 지연되는 시간이 상당하면 없는게 더 나을 수도 있는데…

답은 “체감 지연은 거의 0%에 가깝다”였다. 정규화·비교 연산은 네트워크 통신이 아니라 순수 메모리 연산이라, A4 열 장 분량(3만 자)을 처리해도 1~5ms밖에 안 걸린다. 인간이 반응을 느끼는 최소 지연이 100ms 정도인 걸 감안하면 체감할 수 없는 수준이다. 게다가 타이핑 도중에는 아예 이 로직이 돌지 않고 저장이 완료된 그 순간에만 한 번 실행되는 구조라 이중으로 안전하다.

혹시 모를 초대형 문서(수십만 자) 대비로 Web Worker를 이용한 백그라운드 처리, 글자 수 임계치로 조기 리턴하는 방어선까지 같이 넣기로 했다. 반대로 이 기능이 없으면 어떻게 되는지도 명확했다 — 엔터 한 번 칠 때마다 노트 전체가 재전송되고 그때마다 서버 응답을 2~4초씩 기다려야 한다. 몇 밀리초의 로컬 연산과 몇 초의 네트워크 왕복, 비교가 안 됐다.

다음 편은 이 플러그인이 단순 채팅을 넘어 “원본을 스스로 읽고 위키를 정리하는” 자율 에이전트로 커지는 이야기다. 그 과정에서 AI가 스스로 성공했다고 거짓 보고를 한 사건도 있었다.


Share this post:

Previous Part
Obsidian에 LLM Wiki 만들기 2편 — 자정이 지나도 날짜가 안 바뀌던 버그
Next Part
Obsidian에 LLM Wiki 만들기 4편 — 자율 Ingest 엔진으로 진화하기까지