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을 최소화하는 최적화 방법을 구현할 수 있게 되었다.