[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를 재사용합니다.
왜 이게 좋은가
- 중복 모듈 해석 제거: 수십 개의 수식이 포함된 메시지에서 KaTeX import가 1회로 줄어듭니다.
- 완전히 투명한 변경: 사용자 입장에서 기능적 차이가 전혀 없는 "공짜 점심(free lunch)" 최적화입니다.
- Promise 패턴의 자연스러운 활용: 첫 번째 호출 시 Promise를 캐싱하고, 이후 호출은 같은 Promise를
await하므로 경합 조건(race condition) 걱정이 없습니다. - Svelte 패턴 활용: 프레임워크가 제공하는
context="module"메커니즘을 정확히 활용하여 별도의 전역 상태 관리 없이 구현했습니다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [faster-qwen3-tts] Windows 네이티브 셋업 및 벤치마크 스크립트 추가
- 현재글 : [Open WebUI] KaTeX 모듈 import를 싱글턴으로 캐싱하여 렌더링 최적화
- 다음글 [triton] WSSpecialize에서 초기화된 Barrier의 Invalidation 추가
댓글