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

Obsidian 플러그인을 영어로 옮기려니, 버튼 글자가 상태값 노릇을 하고 있었다

Read in English →

Obsidian에 LLM Wiki 만들기 · 6/6편

개인적으로 만들고 있는 Obsidian 플러그인이 있다. 아직 공개 전이고, 기사나 메모를 넣으면 LLM이 개념별 노트로 정리해 위키를 쌓아 가는 도구다. 이번 주에 두 가지를 했다. 플러그인 이름을 바꿨고, 한국어로만 나오던 화면을 영어로도 나오게 했다. 둘 다 문자열을 찾아 바꾸는 일처럼 보였는데, 막상 열어 보니 바꾸려던 문자열 중 일부가 이름이나 문구가 아닌 다른 일을 하고 있었다. AI 코딩 에이전트와 같이 작업했고, 그런 곳을 번역이나 치환 전에 먼저 찾아낸 것이 이번 작업의 대부분이었다.

이름 하나 바꾸는 데 일괄 치환을 못 했다 — Obsidian 플러그인 이름 변경

옛 이름은 Gemini Butler였다. 처음엔 Gemini 전용으로 만들었지만 지금은 OpenAI가 기본이고, Gemini는 고를 수 있는 세 곳 중 하나다. 이름만 Gemini라 새 이름 Ripen Wiki로 바꾸기로 했다. 그런데 코드에서 gemini를 전부 지울 수는 없었다.

그래서 일괄 치환은 하지 않았다. 바꿀 클래스를 목록으로 정해 그것만 바꾸고, 바꾼 뒤 남은 gemini-가 모델 이름뿐인지 다시 셌다.

플러그인 id는 더 까다로웠다. Obsidian은 플러그인 데이터를 id 이름의 폴더에 둔다. id가 바뀌면 Obsidian에게는 새 플러그인이라 설정, API 키, 임베딩 캐시가 따라오지 않는다. 옮기는 코드를 짤 수도 있었지만 이 플러그인을 쓰는 보관함이 두 곳뿐이라, 두 번 쓰고 나면 다시는 안 쓸 코드였다. 볼트마다 파일을 손으로 한 번 복사하는 쪽을 골랐다.

설치는 GitHub 저장소에서 베타 플러그인을 받아 주는 BRAT으로 한다. 기존 항목을 업데이트하자 “Update of plugin failed”로 실패했다. 원인은 끝내 보지 못했다. 저장소는 새로 만들지 않고 이름만 바꿨고(이슈와 지난 릴리스가 그대로 따라온다), BRAT에서 “Add Beta plugin”으로 새 주소를 다시 추가하자 새 폴더에 깨끗하게 설치됐다. 거기에 옛 폴더의 설정 파일을 복사해 넣었다.

영어 화면을 만들려니 한국어 문자열이 세 종류였다 — Obsidian 플러그인 다국어(i18n)

설정 화면은 먼저 영어로 바꿔 두었다. 남은 건 채팅창이었다. 채팅창과 명령 결과 쪽 코드에는 번역 함수 호출이 하나도 없었고, 한국어가 든 줄이 약 400개였다. 이걸 세 종류로 나눴다.

종류예처리
화면 문구입력창 안내, 버튼, 진행 표시, 명령 결과 보고, 알림, 오류번역한다
LLM에 보내는 글프롬프트, LLM에 넘기는 노트 목록그대로 둔다. 실측으로 다듬어 온 프롬프트다
보관함에 쓰는 글작업 기록 파일, 노트 형식 안내그대로 둔다. 표시 언어를 바꿀 때마다 노트 언어가 섞이면 안 된다

”한 번에 해도 섞이지 않나?” — 화면 문구가 상태값을 겸하던 곳 (data 속성)

에이전트가 영역 세 개를 한 번에 할지 나눠서 할지 묻길래, 한 번에 해도 섞이지 않느냐고 물었다. 에이전트는 이 말을 두 가지로 나눠 답했다. 화면에 한국어와 영어가 섞여 나오는 건 릴리스를 마지막에 한 번만 하면 막을 수 있다. 진짜 위험은 같은 문자열이 화면 문구이면서 다른 데도 쓰이는 경우였다. 코드가 화면 문구를 조건으로 검사하고 있으면, 그 문구를 번역하는 순간 영어 화면에서 그 기능이 오류 없이 멈춘다. 그래서 번역을 시작하기 전에 그런 문자열부터 찾기로 했다.

실제로 있었다.

고친 방식은 같다. 상태는 상태대로 따로 둔다. 버튼 상태는 data-run-state 속성(idle, running, done)에, 자동 감지 여부는 카드를 만들 때 넘기는 플래그에 두고, 판단은 그것으로만 한다. 화면 글자는 사전에서 꺼내 쓴다. 완료 요약의 값은 done/missing으로 바꾸고 화면에 띄울 때 번역한다. 영어 모드에서도 버튼 상태 판단과 줄 나누기가 맞는지 테스트를 따로 넣었다.

영어 화면에 LLM이 쓴 한국어가 남았다 — LLM 출력 언어

번역을 마치고 테스트용 보관함에서 영어로 명령들을 실제로 돌려 봤다. 화면 문구는 모두 영어로 나왔다. 그런데 태그 정리 결과의 병합 이유는 한국어였다. 이유는 LLM이 쓰는데, 프롬프트가 한국어라 LLM도 한국어로 답한다. 프롬프트는 건드리지 않기로 했던 범위라 에이전트는 그대로 둘지 물었다. 나는 영어로 쓰는 사람에게 한글로 뭘 알려 주면 글꼴도 없어서 이상하게 나올 거라고 했다.

그래서 LLM이 쓴 글 중 화면에 그대로 나오는 것만 표시 언어를 따르게 했다. 태그 병합 이유, 노트 정리 제안의 사유, 자동 병합 사유, 채팅 답변 끝의 참고 노트 목록이다. 노트 본문의 언어 규칙(원문 언어를 따른다)은 그대로 뒀다.

조건이 하나 있었다. 한국어 모드의 프롬프트는 한 글자도 바뀌면 안 된다. 실측으로 다듬은 결과가 흔들리지 않게 하려는 것이다. 영어 모드일 때만 지시를 바꾸거나 더하고, 바꾸기 전과 후의 한국어 프롬프트 다섯 개를 비교해 똑같은지 확인했다.

여기서도 겸용 문자열이 하나 나왔다. 채팅창은 답변에 “인용된 보관함 지식이 없습니다.”라는 문장이 있으면 참고 노트 표시를 뗀다. LLM이 영어로 쓰기 시작하면 이 문장이 안 나온다. 두 언어의 문장을 상수로 두고, 둘 중 하나라도 있으면 떼도록 바꿨다.

영어 모드에서 실제로 돌려 보니 태그 병합 이유와 채팅 답변의 참고 노트 목록이 영어로 나왔다. 노트 정리 제안은 그 스캔에서 제안이 한 건도 나오지 않아, 사유가 영어로 나오는지는 아직 화면에서 보지 못했다. 지시가 들어가는 것만 단위 테스트로 확인했다.

릴리스 뒤에 하나를 놓친 게 드러났다. 자동 병합 사유는 판정과 함께 저장해 두고 다음 스캔에서 다시 꺼내 쓰는데, 저장할 때의 언어를 기록하지 않아 한국어 모드에서 받은 사유가 영어 화면에 그대로 나왔다. 다음 릴리스에서 언어가 다르면 저장된 사유 대신 그 언어의 일반 문구를 보여 주게 고쳤다. LLM이 쓴 글이 화면에 나오는 길에는 저장했다가 다시 꺼내는 길도 있었다.

남는 생각

이름 변경과 다국어 작업은 성격이 달라 보이지만 걸린 곳은 같았다. 이름처럼 보이는 문자열이 모델 id였고, 화면 문구처럼 보이는 문자열이 상태값이었다. 일괄로 바꿨다면 오류 메시지 하나 없이 어떤 기능이 영어 화면에서만 멈췄을 것이다. 바꾸기 전에 그 문자열을 비교하는 코드가 있는지부터 찾는 것, 그리고 애초에 화면 글자로 상태를 판단하지 않는 것. 이번에 그걸 찾게 만든 건 “섞이지 않나?”라는 짧은 질문이었다.


Share this post:

Obsidian에 LLM Wiki 만들기

  1. 1. Obsidian에 LLM Wiki 만들기 — 시리즈 소개
  2. 2. Obsidian에 LLM Wiki 만들기 1편 — 이미 있는 플러그인 10개를 두고 왜 또 만들었나
  3. 3. Obsidian에 LLM Wiki 만들기 2편 — 자정이 지나도 날짜가 안 바뀌던 버그
  4. 4. Obsidian에 LLM Wiki 만들기 3편 — 동적 뱃지와 dirty check, UX가 엔지니어링을 만날 때
  5. 5. Obsidian에 LLM Wiki 만들기 4편 — 자율 Ingest 엔진으로 진화하기까지
  6. 6. Obsidian 플러그인을 영어로 옮기려니, 버튼 글자가 상태값 노릇을 하고 있었다