[Open WebUI] DOMParser 대신 html-entities로 HTML 디코딩 최적화
PR 링크: open-webui/open-webui#23165 상태: Merged | 변경: +3 / -3
들어가며
Open WebUI에서 LLM 응답을 스트리밍으로 표시할 때, 각 텍스트 토큰마다 unescapeHtml 함수가 호출됩니다. 기존 구현은 new DOMParser().parseFromString()을 사용하여 매번 완전한 DOM 문서를 생성했습니다. 이는 스트리밍 중 매 프레임마다 불필요한 DOM 트리 생성과 GC 부하를 발생시켰습니다.
핵심 코드 분석
Before: DOMParser로 전체 DOM 문서 생성
export function unescapeHtml(html: string) {
const doc = new DOMParser().parseFromString(html, 'text/html');
return doc.documentElement.textContent;
}
DOMParser.parseFromString()은 전달받은 HTML 문자열로부터 완전한 Document 객체를 생성합니다. &, < 같은 간단한 HTML 엔티티를 디코딩하기 위해 HTML parser, DOM 트리 빌더, 메모리 할당이 모두 동작합니다.
After: html-entities 라이브러리의 decode 사용
import { decode } from 'html-entities';
export function unescapeHtml(html: string): string {
return decode(html);
}
이미 프로젝트 의존성에 포함된 html-entities 라이브러리의 decode 함수를 사용합니다. 이 함수는 문자열 치환 방식으로 HTML 엔티티를 디코딩하므로 DOM 생성 없이 동작합니다.
왜 이게 좋은가
- GC 부하 감소: DOM 문서 객체 생성이 사라져 가비지 컬렉션 부하가 크게 줄어듭니다. LLM 스트리밍 중에는 이 함수가 초당 수십~수백 번 호출될 수 있어 영향이 큽니다.
- 의존성 추가 없음:
html-entities는 이미MarkdownTokens.svelte에서 같은 용도로 사용 중이므로 새로운 의존성을 추가하지 않습니다. - 타입 안전성 향상: 반환 타입이
string | null에서string으로 명확해졌습니다.
단 3줄의 변경이지만, hot path에서의 불필요한 객체 할당을 제거한 효과적인 최적화입니다. 브라우저 API가 항상 최적의 선택이 아닐 수 있다는 좋은 사례입니다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Open WebUI] 비중국어 콘텐츠에 대한 불필요한 처리 스킵으로 스트리밍 성능 개선
- 현재글 : [Open WebUI] DOMParser 대신 html-entities로 HTML 디코딩 최적화
- 다음글 [Open WebUI] ChatItem 사이드바 메모리 누수 수정
댓글