검색창에 debounce 적용해보기

Jieunmoon·2023년 10월 14일

[JavaScript] 디바운스

짧은 시간내 연속된 함수 / event 호출 시, 호출되는 모든 함수를 비효율적으로 매번 처리하지 않고 정해진 딜레이 후에 한번만 처리하는 패턴

왜 쓰이는가 ?

  • 전반적인 성능 향상
  • 비용절약 (유료 API나 서비스를 사용하고 있을 때 네트워크 요청 회수를 절감함으로 비용적인 측면에서 절약할 수 있음)

디바운스를 적용하지 않았을 때 문제점

한 글자 칠 때마다 불필요한 통신을 하게 된다.
ex) 'kor'을 치면 네트워크 탭에 들어가서 봤을 때 통신이 총 3번 이루어지게 된다. 'k' , 'ko', 'kor' 이렇게 호출됨

디바운스 적용

hook 생성

import { useEffect, useState } from 'react';

function useDebounce<T>(value: T, delay: number = 500): T {
  const [debounceVal, setDebounceVal] = useState<T>(value); //value: 받아온 input값

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebounceVal(value); // delay후 값을 새로 업데이트
    }, delay);
    return () => { // 클린업함수 적용 (unmount 됐을 때 eventhandler 깨끗히 청소)
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debounceVal; // 새로 업데이트된 값을 return
}

export default useDebounce;

Search.tsx

  const [currentSearchTerm, setCurrentSearchTerm] = useState<string>(''); // 현재 검색어
  const navigate = useNavigate();
  const [recentSearchTerms, setRecentSearchTerms] = useState<string[]>([]); // 최근 검색어 목록
  const localStorageKey = 'searchWords';
  const [searchResults, setSearchResults] = useState(null); // 검색 결과 데이터

  const debounceSearchTerm = useDebounce<string>(currentSearchTerm);
  // currentSearchTerm가 업데이트 되면 
  // useDebounce훅에 값을 전달
  // 훅을 통해 처리된 값을 debounceSearchTerm변수에 담아서 쓴다.

  useEffect(() => {
    const getSearchProduct = async () => {
      try {
        const response = await fetch(
          `https://pet-commerce.shop/v1/api/product/search?searchWord=${encodeURIComponent(
            currentSearchTerm,
          )}`,
        );

        if (!response.ok) {
          throw new Error('No results found');
        }
        const data = await response.json();
        setSearchResults(data);
      } catch (err) {
        console.error(err);
      }
    };

    if (debounceSearchTerm) {
      getSearchProduct();
    }
  }, [debounceSearchTerm]); // debounce 처리된 검색어 변수의 값이 변경될 때 실행 

0개의 댓글