개발여행
쓰로틀링과 디바운싱으로 성능 개선 본문
웹앱을 구현하다 보면 사용자의 액션에 따라 각종 이벤트를 발생시킬 때가 있다. 대표적으로 <input>의 change 이벤트나 스크롤 이벤트가 있는데, 이런 이벤트들은 보통 구현하려는 기능 특성상 초 간격으로 수십번씩 발생할 수 있어 그만큼의 함수를 실행시킨다.
이벤트가 많이 발생하게 되면 웹앱의 성능을 저하시켜 사용자 경험에 악영향을 주거나 불필요한 API 요청을 지속적으로 보내 서버 부하를 일으킨다. 이처럼 실행되는 함수가 많을 때, 그 빈도수를 컨트롤해 성능을 끌어올리는 기법이 있다.
쓰로틀링 (Throttling)
쓰로틀링은 일정 시간마다 그 시간 내에 발생하는 모든 이벤트들을 무시하고 제일 마지막으로 감지된 함수만 실행시키는 기법이다.
쓰로틀 React 훅 구현:
import { useEffect, useRef, useState } from "react";
export default function useThrottle<T>(value: T, interval: number) {
const [throttledValue, setThrottledValue] = useState<T>(value);
const lastExecuted = useRef(Date.now());
useEffect(() => {
if (Date.now() >= lastExecuted.current + interval) {
lastExecuted.current = Date.now();
setThrottledValue(value);
} else {
const timerId = setTimeout(() => {
lastExecuted.current = Date.now();
setThrottledValue(value);
}, interval);
return () => clearTimeout(timerId);
}
}, [value, interval]);
return throttledValue;
}
디바운싱 (Debouncing)
디바운싱도 함수가 한꺼번에 너무 많이 실행되지 않도록 제어를 거는 기법인데, 작동 방식이 쓰로틀링과는 약간 다르다. 디바운싱에서는 함수가 호출된 후 특정 시간 동안 동일한 함수가 추가적으로 호출되지 않으면, 그 시간이 경과한 후에 해당 함수를 실행시킨다.
예를 들어 딜레이 시간을 3초로 설정했을 때, 함수를 호출한 순간부터 3초 동안 추가 호출이 없을 경우 그 함수를 실행시킨다. 만약 3초의 구간 동안 함수가 또 호출됐을 경우 타이머가 리셋돼서 3초를 더 기다려야 함수가 실행된다.
디바운스 React 훅 구현:
import { useEffect, useState } from "react";
export default function useDebounce<T>(value: T, delay: number) {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timeoutId = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(timeoutId);
}, [value, delay]);
return debouncedValue;
}