[Open WebUI] CodespanToken에서 JS 트랜지션을 CSS 애니메이션으로 교체하여 메인 스레드 부하 제거
PR 링크: open-webui/open-webui#23258 상태: Merged | 변경: +21 / -19
들어가며
Open WebUI에서 스트리밍 중 렌더링되는 인라인 코드(codespan)마다 Svelte의 transition:fade가 적용되고 있었습니다. 이 트랜지션은 JS로 구동되어 메인 스레드에서 인라인 스타일을 적용하고 라이프사이클 콜백을 실행합니다. 스트리밍 중 수십~수백 개의 코드스팬이 렌더링되면 메인 스레드에 상당한 부하를 줍니다. 이 PR은 동일한 시각 효과(100ms fade)를 CSS @keyframes로 교체하고, 중복된 <code> 블록을 하나로 통합합니다.
핵심 코드 분석
Before: JS 트랜지션 + 중복 엘리먼트
<script>
import { fade } from 'svelte/transition';
</script>
{#if done}
<code class="codespan cursor-pointer" on:click={...}>
{unescapeHtml(token.text)}
</code>
{:else}
<code transition:fade={{ duration: 100 }} class="codespan cursor-pointer" on:click={...}>
{unescapeHtml(token.text)}
</code>
{/if}
트랜지션을 조건부로 적용하기 위해 <code> 블록이 완전히 중복되어 있습니다.
After: CSS 애니메이션 + 단일 엘리먼트
<code
class="codespan cursor-pointer {!done ? 'fade-in-token' : ''}"
on:click={...}>
{unescapeHtml(token.text)}
</code>
<style>
@keyframes fade-in-token {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in-token {
animation: fade-in-token 100ms ease-out;
}
</style>
fade import가 제거되고, 조건부 클래스 하나로 전체 로직이 대체됩니다.
왜 이게 좋은가
- 메인 스레드 해방: CSS 애니메이션은 브라우저의 컴포지터 스레드에서 처리됩니다. JS 트랜지션이 매 코드스팬마다 실행되던 것과 달리, 메인 스레드를 전혀 차지하지 않습니다.
- 코드 중복 제거:
{#if}/{:else}로 동일한<code>블록을 두 번 작성할 필요가 없어졌습니다. - 번들 크기 감소:
svelte/transition에서fadeimport가 제거됩니다. - 동일한 시각 효과: 100ms ease-out으로 사용자가 차이를 느끼지 못합니다.
참고 자료
관련 포스트
- [Open WebUI] JS transition을 CSS 애니메이션으로 교체하여 스트리밍 렌더링 최적화
- [Open WebUI] TTS 문장 파싱을 showCallOverlay 가드로 감싸 불필요한 O(n^2) 연산 제거
- [Open WebUI] CodeEditor에서 EditorView 미해제로 인한 메모리 누수 수정
- [Open WebUI] UserMessage에서 JSON 직렬화 대신 structuredClone과 빠른 경로 비교 적용
- [Open WebUI] JSON.parse(JSON.stringify()) 를 structuredClone으로 교체
PR Analysis 의 다른글
- 이전글 [triton] Proton CUPTI Graph Replay 힙 증가 재현 테스트 추가
- 현재글 : [Open WebUI] CodespanToken에서 JS 트랜지션을 CSS 애니메이션으로 교체하여 메인 스레드 부하 제거
- 다음글 [Ray] 외부 소비자의 Object Store 사용량을 Resource Manager 예산에 반영
댓글