[WebTranslator 개발기 #08] 단어 번역 획일화 문제와 LLM 사전 파이프라인 특화

크롬 확장 프로그램 개발기 8편: 고성능 LLM을 연동하고도 NMT 기계 번역처럼 단순 1줄 뜻만 나오던 단어 번역 획일화 버그를 해결하고, IPA 발음기호와 예문이 포함된 LLM 전용 사전 파이프라인을 구축한 과정을 다룹니다.
LLM 구조화 사전 생성 파이프라인 및 NMT 듀얼 라우팅 아키텍처 다이어그램

지난 7편에서는 Google, Google Gemini, OpenAI GPT, LibreTranslate를 포괄하는 다중 엔진 어댑터(Adapter)를 설계하고, LLM 특유의 서술형 마크다운 응답을 안전하게 정제하는 parseAndCleanJson 파이프라인을 구축하여 배치 번역의 안정성을 확보했습니다.

그러나 다양한 번역 엔진을 붙인 후 실전에서 '선택 영역 단어 번역(Word Lookup)' 기능을 테스트하던 중 예상치 못한 문제가 발생했습니다. 고성능 LLM인 Gemini 3.5 Flash나 GPT-5.6 Luna를 선택했음에도 불구하고, 무료 구글 번역이나 LibreTranslate를 쓸 때와 완전히 똑같이 game ➔ 경기, 시합이라는 1줄짜리 단순 기계 번역 텍스트만 획일적으로 출력되는 결함이 나타난 것입니다.

이번 글에서는 단어 번역에서 문장 번역 함수로 우회하던 라우팅 결함을 분석하고, NMT 기계 번역의 한계를 극복하여 IPA 발음기호, 품사, 핵심 뜻, 실생활 예문을 제공하는 LLM 전용 사전 파이프라인과 듀얼 라우터를 구축한 과정을 정리해 보고자 합니다.

1. 문장 번역과 단어 사전의 정보 요구 차이

사용자가 웹페이지의 긴 문단을 번역할 때와 특정 단어 하나만을 마우스로 드래그했을 때 기대하는 정보의 형태는 완전히 다릅니다.

구분 문장 번역 (Sentence Translation) 단어 사전 조회 (Word Lookup)
핵심 목적 문맥에 맞는 자연스러운 한국어 의역 단어의 본질적 의미, 발음, 문법 정보 습득
필수 요구 데이터 1:1 매칭 번역 문장 IPA 발음기호, 품사, 다의어 3개, 실생활 예문
NMT 엔진의 한계 전체 문맥을 준수하게 번역 가능 사전적 언어 메타데이터 자체 생성 불가
LLM 엔진의 강점 도메인 전문 뉘앙스 정밀 번역 프롬프트 기반 완벽한 구조화 사전 생성

구글 번역이나 LibreTranslate 같은 신경망 기계 번역(NMT) 엔진은 문장을 변환하도록 학습된 모델이므로 단어에 대한 발음기호나 예문을 생성할 수 없습니다. 반면 LLM은 전용 프롬프트를 주입하면 백과사전 수준의 구조화된 사전 데이터를 단숨에 생성할 수 있는 압도적인 잠재력을 가지고 있습니다.

2. AI의 단순 라우팅 실수와 획일화 버그

AI 어시스턴트에게 단어 번역 요청 처리 로직을 구현하도록 지시했습니다.

// dictionary.js: 단순 텍스트 번역 함수로의 무차별 우회 (오류 코드)
async function fetchWordDefinition(word, engine) {
  // 치명적 결함: 엔진 종류와 상관없이 일반 문장 번역 함수를 그대로 호출!
  const simpleTranslation = await translateSingleText(word, engine);
  
  return {
    word: word,
    definition: simpleTranslation // 발음기호, 품사, 예문 전부 누락
  };
}

결함 원인 분석

AI는 단어 조회(`lookupWord`) 요청이 들어왔을 때, 엔진별 특성을 전혀 고려하지 않고 내부적으로 기존의 일반 문장 번역용 함수(translateSingleText)를 그대로 호출해 버렸습니다.

그 결과 비싼 API 비용을 지불하는 고성능 LLM을 연동해 두었음에도 불구하고, LLM에게 단순 문장 번역 프롬프트만 전달되어 무료 NMT 엔진과 하등 다를 바 없는 1줄짜리 뜻만 획일적으로 반환되었던 것입니다.

3. 해결책 1: LLM 전용 구조화 사전 빌더 (`fetchLLMDictionary`)

단어 조회를 일반 번역기에 던지지 않고, LLM 엔진일 때는 사전 전용 프롬프트(buildDictionaryPrompt)를 주입하여 JSON 규격 데이터를 직접 생산하도록 지시를 수정했습니다.

단어 조회를 일반 번역기에 던지지 마라. LLM 엔진(Gemini/GPT)일 때는 buildDictionaryPrompt(word)를 통해 구조화된 JSON({ pronunciation, pos, definitions, examples })을 요청하고, NMT 엔진일 때만 Fallback으로 기본 번역을 제공하도록 파이프라인을 분리해라.
You are an expert English-Korean lexicographer.
Analyze the given English word and output ONLY a JSON object matching this schema:
{
  "word": "string",
  "pronunciation": "[IPA]",
  "pos": "part of speech (noun/verb/adj...)",
  "definitions": ["주요 뜻 1", "주요 뜻 2", "주요 뜻 3"],
  "examples": [
    { "en": "Example sentence 1", "ko": "예문 한국어 번역 1" }
  ]
}

4. 해결책 2: 지능형 듀얼 라우팅 (`lookupWord`)

엔진의 성격에 따라 LLM 고품질 사전 모드NMT 경량 Fallback 모드로 분기하는 라우팅 시스템을 완성했습니다.

// src/background/dictionary.js: 지능형 듀얼 단어 사전 라우터
export async function lookupWord(word, settings) {
  const { engine, targetLang = "ko" } = settings;

  // 1. LLM 엔진 계열: 고품질 구조화 사전 데이터 생성
  if (["gemini", "openai", "claude", "ollama"].includes(engine)) {
    return await fetchLLMDictionary(word, engine, targetLang, settings);
  }

  // 2. NMT 기계 번역 엔진 계열: 경량 1차 뜻 모드 Fallback
  const simpleTrans = await translateWithGoogle(word, targetLang);
  return {
    word: word,
    pronunciation: "",
    pos: "기계 번역",
    definitions: [simpleTrans],
    examples: []
  };
}

5. 검증 결과 및 클라이언트 사전 카드 UX

듀얼 라우터를 적용한 후 단어 드래그 번역을 검증했습니다.

  1. Gemini 3.5 Flash / GPT-5.6 Luna: 단어를 드래그하자마자 [ɡeɪm] | 명사 | 1. 경기 2. 게임 3. 사냥감과 함께 실생활 예문 및 한국어 번역이 담긴 프리미엄 사전 팝업 카드가 1초 만에 렌더링 완료.
  2. Google Translate / LibreTranslate: 사전 정보는 생략되지만 초고속으로 기본 뜻이 표출되는 경량 모드로 완벽한 안정성 유지.

마무리하며

단어 사전 팝업이 고품질로 완성되자, 사용자가 단어를 드래그하여 사전 팝업을 띄워둔 상태에서 단축키(Alt+A)로 페이지 전체 번역을 실행하면 이전 팝업 레이어가 DOM에서 정리되지 않고 전체 번역 레이어와 뒤엉켜 화면이 하얗게 먹통이 되는 상태 충돌(State Collision) 버그가 발생했습니다.

다음 글에서는 선택 영역 팝업과 전체 페이지 번역 간의 상태 머신을 일원화하고, 단축키 입력 시 기존 팝업을 안전하게 회수하는 DOM 상태 충돌 해결 과정을 다루어 보겠습니다.