본문으로 건너뛰기

[Open WebUI] 검색 쿼리 디바운스 적용으로 불필요한 DB 요청 감소

PR 링크: open-webui/open-webui#20982 상태: Merged | 변경: +139 / -31

들어가며

Open WebUI의 관리 페이지(사용자 목록, 함수 목록, Knowledge, Notes 등)에서 검색창에 글자를 입력하면 Svelte의 반응형 구문($:)이 즉시 반응하여 매 키 입력마다 DB 쿼리나 필터링 함수를 실행하고 있었습니다. "performance"라는 단어를 입력하면 11번의 쿼리가 연속으로 발생하는 셈입니다. 이 PR은 검색 쿼리에 디바운스(debounce)를 적용하여, 사용자가 입력을 멈춘 후 200~300ms 뒤에 한 번만 쿼리를 실행합니다.

핵심 코드 분석

반응형 구문에 디바운스 적용

Before (UserList.svelte):

$: if (query) {
  page = 1;
}

$: if (query !== null && page !== null && orderBy !== null && direction !== null) {
  getUserList();
}

After:

let searchDebounceTimer: ReturnType<typeof setTimeout>;

$: if (query !== undefined) {
  clearTimeout(searchDebounceTimer);
  searchDebounceTimer = setTimeout(() => {
    page = 1;
    getUserList();
  }, 300);
}

$: if (page !== null && orderBy !== null && direction !== null) {
  getUserList();
}

onDestroy(() => {
  clearTimeout(searchDebounceTimer);
});

이 패턴이 총 8개 컴포넌트에 일관되게 적용되었습니다:

  • Functions.svelte (300ms)
  • UserList.svelte (300ms)
  • Groups/Users.svelte (300ms)
  • Knowledge.svelte (300ms)
  • Notes.svelte (300ms)
  • Knowledge/KnowledgeSelector.svelte (200ms)
  • Commands/Knowledge.svelte (200ms)
  • Commands/Prompts.svelte (200ms)

실시간 입력 자동완성(Commands 계열)은 200ms, 페이지네이션이 있는 목록 조회는 300ms의 디바운스 시간을 적용했습니다.

왜 이게 좋은가

  1. DB 쿼리 횟수 대폭 감소: 10자 입력 시 10회 쿼리가 1회로 줄어듭니다. 다수의 사용자가 동시에 검색하는 환경에서 백엔드 부하가 크게 감소합니다.
  2. 사용자 경험 유지: 200~300ms 디바운스는 사용자가 체감하기 어려운 수준이며, 오히려 중간 결과가 깜빡이는 현상이 사라져 UX가 개선됩니다.
  3. 메모리 누수 방지: onDestroy에서 타이머를 정리하여, 컴포넌트가 해제된 후 불필요한 콜백 실행을 방지합니다.
  4. query와 다른 필터 분리: query 변경은 디바운스를 거치지만, 정렬 기준이나 페이지 변경은 즉시 반영되도록 반응형 구문을 분리했습니다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글