React

[React] debouncing 기법을 활용한 검색 기능 구현

dev_seon 2022. 12. 20. 23:18

글 목록 검색 기능을 구현했던 과정을 정리해보도록 하겠습니다.

 

먼저, 처음에 검색 기능을 구현할 때에는 아래와 코드와 같이 input 태그에 사용자의 입력이 발생하면 서버에 API 요청을 전송하는 방식을 생각했습니다.

 

const SearchBar = ({ placeholder, setDataList }: SearchBarProps) => {
	const [keyword, setKeyword] = useState('');

	const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
		setKeyword(event.target.value);
	};
	
    // input의 value(keyword)가 변할 때마다 서버에 데이터를 요청함
	useEffect(() => {
		getFilteredQuestionList(keyword).then((res) => setDataList(res));
	}, [keyword]);

	return (
		<SearchContainer>
			<form>
				<input
					type="text"
					placeholder={placeholder}
					onChange={handleChange}
					value={keyword}
				/>
			</form>
		</SearchContainer>
	);
};

export default SearchBar;

 

그러나 해당 방식으로 검색 기능을 구현하게 되면 아래 이미지와 같이 사용자가 한 단어를 입력하는 중임에도 서버에 수많은 요청이 전송되는 것을 확인할 수 있었습니다. 

 

이러한 검색 기능의 성능을 개선하기 위해 debouncing 기법을 적용하기로 했습니다.

(여기서 debouncing은 단위시간 내에 연이어 호출되는 함수들 중 마지막 함수만 호출하는 것을 의미합니다.)

 

// useDebounce.tsx

import { useEffect, useState } from 'react';

export const useDebounce = (value: string, delay: number) => {
	const [debounceValue, setDebounceValue] = useState(value);

	useEffect(() => {
		const handler = setTimeout(() => {
			setDebounceValue(value);
		}, delay);

		return () => {
			clearTimeout(handler);
		};
	}, [value, delay]);

	return debounceValue;
};
// SearchBar.tsx
const SearchBar = ({ placeholder, setDataList }: SearchBarProps) => {
	const [keyword, setKeyword] = useState('');
    // useDebounce hook을 적용한 debouncedKeyword 선언
	const debouncedKeyword = useDebounce(keyword, 500);

	const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
		setKeyword(event.target.value);
	};

	// debouncedKeyword가 변할 때 서버에 데이터 요청
	useEffect(() => {
		getFilteredQuestionList(debouncedKeyword).then((res) => setDataList(res));
	}, [debouncedKeyword]);

	return (
		<SearchContainer>
			<form>
				<input
					type="text"
					placeholder={placeholder}
					onChange={handleChange}
					value={keyword}
				/>
			</form>
		</SearchContainer>
	);
};

export default SearchBar;

 

구현은 위와 같이 useDebounce라는 custom hook을 생성한 후 이를 이전에 작성했던 SearchBar 컴포넌트에 적용하는 방식으로 진행했습니다.

이렇게 debouncing 기법을 적용한 후 다시 검색을 해보니 아래와 같이 마지막 입력이 발생하고 0.5초 정도가 지난 후 서버에 검색 결과 데이터에 대한 요청이 한 번만 전달되는 것을 확인할 수 있었습니다.