적용 동기
- Table UI에서 focus된 row의 댓글 정보를 보여주는 기능을 구현하는데 적용하였다.
- 구현된 table UI에서 rows를 키보드 UP/DOWN 키로 순회가 가능하였기 때문에 focus가 바뀔 때마다 댓글 정보를 fetch하는 로직을 짜게 되면 불필요한 요청이 많이 발생될 것이 우려되었다.
- 예를 들어 키보드를 이용하여 1번 row에서 30번 row로 이동하게 되면 row가 30번 바뀌므로 30번의 요청을 하게된다.
- 일정 시간 동안 여러 이벤트가 발생했을 때 가장 마지막 이벤트만을 발생시키는 기술인 디바운싱을 적용한다면 이 문제를 우아하게 해결할 수 있을 것이라고 판단하였다.
구현 코드
useDebounce
import { useEffect, useState } from 'react';
const useDebounce = <T>(value: T, delay?: number): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
return () => {
clearTimeout(timer)
}
}, [value, delay]);
return debouncedValue;
}
export default useDebounce;
- 첫번째 파라미터는 디바운싱를 적용할 값을, 두번째 파라미터는 디바운싱 시간을 넣어준다.
- 두번째 파라미터로 들어오는 delay의 경우, 상황에 따라 알맞게 조절해준다.
- 만약 useDebounce(value)라고 작성한다면, value값이 0.5초 동안 대기했다가 만약 이 사이에 값이 바뀌었다면 다시 0.5초를 대기하고, 값이 그대로라면 setDeboundedValue를 하여 state를 변경시킨다.
- useDebounce의 반환값으로 debouncedValue를 반환한다.
- value가 1 -> 2 -> 3 -> 4으로 변경되고 value가 1 -> 2 -> 3 -> 4으로 변화하는 간격이 0.5초 이내라면 디바운싱을 적용하여 값이 1 -> 4로만 바뀌도록 값을 만들 수 있다.
- value가 useState의 초기값으로 들어가는데, value가 바뀐다고 state가 바뀌지 않는다.
리액트 쿼리와 결합
const debouncedId = useDebounce(selectedRowId);
const { data, isLoading } = useQuery(['comment', debouncedId], () => getComment(debouncedId));
- 이런 구현을 통해서 만약 키보드를 이용하여 1번 row에서 30번 row로 이동하게 된다면 row가 30번 바뀌더라도 1번의 요청을 하게된다.