React Debounce 최적화 경험 👨‍🔧

9606 단어 ReactReact

Debounce? 🙄

Debounce는 특정 시간 동안 연속적으로 호출되는 이벤트 중 마지막 이벤트만 호출할 때 사용하는 기법이다.


어디에 적용할까? 🧐

현재 진행하고 있는 토이 프로젝트에서 AutoComplete(자동완성) 컴포넌트에 lodash의 debounce를 적용했다. 사용자가 입력한 문자열을 네이버 책 검색 Open API의 Query String으로 전달하고, 응답받은 책 목록 데이터를 자동 완성 목록에 반영했다.

그런데, 사용자가 타이핑을 할 때마다 API를 호출하게 되면 짧은 시간 동안 너무 많은 API를 호출하게 되고 이는 네트워크 트래픽 증가로 이어져 이를 방지하고자 도입했다.


적용 💡

function AutoCompleteBook(props) {
  const { value, width, onChange, isReadOnly } = props;
  const [inputValue, setInputValue] = useState('');
  const [options, setOptions] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  // ... 로직

  const lazyFetchBooks = useCallback(
    debounce(async (bookTitle) => {
      try {
        const res = await apiCall({
          url: `/ext/book?bookTitle=${bookTitle}`,
          method: 'get',
        });
        const result = getAjaxData(res);
        setOptions(result.map(item => ({ ...item, key: item.isbn, text: item.title })));
      } catch (error) {
        handleAjaxError(error);
      } finally {
        setIsLoading(false);
      }
    }, 750), 
    [],
  );

   return (
    <Autocomplete
      // ... props
      onInputChange={(_e, newInputValue) => {
        setIsLoading(true);
        lazyFetchBooks(newInputValue);
        setInputValue(newInputValue);
      }}
      noOptionsText={
        isLoading ? (
          <div style={{ textAlign: 'center' }}>
            <CircularProgress size={25} />
          </div>
        ) : (
          '검색결과가 없습니다.'
        )
      }
    />
  );
}

마지막 이벤트 발생 이후 750ms 동안 추가 이벤트가 발생하지 않을 경우 debounce 콜백 함수 실행하도록 코드를 작성했다. 이를 통해 타이핑을 할 때마다 ajax 통신이 발생하는 것을 예방할 수 있었다.

여기서 한 가지 주의할 점은 useCallback hook api를 사용하지 않으면, state 변경으로 렌더링이 발생할 때마다 debounce 함수가 생성된다. 이는 여러 개의 debounce 함수가 병렬로 실행되니 주의하도록 하자.


이 경험을 통해 📝

React에서 ajax call을 최소화하는 최적화 방법을 구현할 수 있게 되었다.

좋은 웹페이지 즐겨찾기