본문으로 건너뛰기

[Open WebUI] KaTeX 모듈 import를 싱글턴으로 캐싱하여 렌더링 최적화

PR 링크: open-webui/open-webui#21880 상태: Merged | 변경: +19 / -7

들어가며

Open WebUI의 채팅 메시지에 수학 수식이 포함되어 있으면 KaTeX 라이브러리로 렌더링합니다. 문제는 KaTeX, mhchem, CSS를 매 컴포넌트 마운트마다 import()로 로딩하고 있었다는 점입니다. 하나의 메시지에 수십 개의 수식이 있으면, 동일한 모듈 해석(module resolution)이 수십 번 반복됩니다. 이 PR은 Svelte의 context="module" 스크립트 블록을 활용하여 단 한 번만 import하고 모든 인스턴스가 공유하도록 개선합니다.

핵심 코드 분석

인스턴스별 import에서 모듈 레벨 싱글턴으로

Before:

<script lang="ts">
  import { onMount } from 'svelte';
  // ...
  onMount(async () => {
    const [katex] = await Promise.all([
      import('katex'),
      import('katex/contrib/mhchem'),
      import('katex/dist/katex.min.css')
    ]);
    renderToString = katex.renderToString;
  });
</script>

After:

<script lang="ts" context="module">
  import type { renderToString as katexRenderToString } from 'katex';

  // Module-level singleton: load katex once, share across all KatexRenderer instances
  let katexRenderer: Promise<typeof katexRenderToString> | null = null;
  function getKatexRenderer(): Promise<typeof katexRenderToString> {
    if (!katexRenderer) {
      katexRenderer = Promise.all([
        import('katex'),
        import('katex/contrib/mhchem'),
        import('katex/dist/katex.min.css')
      ]).then(([katex]) => katex.renderToString);
    }
    return katexRenderer;
  }
</script>

<script lang="ts">
  import { onMount } from 'svelte';
  // ...
  onMount(async () => {
    renderToString = await getKatexRenderer();
  });
</script>

Svelte에서 context="module" 스크립트 블록은 컴포넌트 클래스 단위로 한 번만 실행됩니다. 이 영역에 Promise를 저장하면 첫 번째 인스턴스만 실제 import를 수행하고, 이후 인스턴스들은 이미 resolve된(또는 resolve 중인) 동일한 Promise를 재사용합니다.

왜 이게 좋은가

  1. 중복 모듈 해석 제거: 수십 개의 수식이 포함된 메시지에서 KaTeX import가 1회로 줄어듭니다.
  2. 완전히 투명한 변경: 사용자 입장에서 기능적 차이가 전혀 없는 "공짜 점심(free lunch)" 최적화입니다.
  3. Promise 패턴의 자연스러운 활용: 첫 번째 호출 시 Promise를 캐싱하고, 이후 호출은 같은 Promise를 await하므로 경합 조건(race condition) 걱정이 없습니다.
  4. Svelte 패턴 활용: 프레임워크가 제공하는 context="module" 메커니즘을 정확히 활용하여 별도의 전역 상태 관리 없이 구현했습니다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글