포트폴리오 제작 중에 브라우저의 화면 너비를 구해서 너비에 따라 화면구성을 달리해줘야 했다. 그래서 window의 resize 이벤트를 사용하기로 하였다. 하지만 이대로 사용하였을 때 브라우저 창 resizing마다 콜백 코드가 계속해서 실행되었다. resizing마다 콜백 코드를 계속해서 실행해줘야할 수도 있지만 저는 resizing마다 실행할 필요가 없기 때문에 매우 비효율적이라 생각하였다. 그렇게해서 찾아보게 된 개념이 디바운싱과 쓰로틀링이다. 디바운싱, 쓰로틀링 두개 다 웹에서 발생하는 이벤트를 제어하는 방법이라고 한다.
디바운싱(Debouncing) - 연속으로 호출되는 함수들 중에 마지막에 호출되는 함수만 실행되도록 하는 것
쓰로틀링(Throttling) - 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것
처음엔 아래코드처럼 innerWidth를 그대로 상태로 담아서 사용하고 콘솔을 찍어 확인해보았더니 resizing마다 계속해서 로그가 찍히는 것을 볼 수 있었다. 그래서 브라우저 창을 늘리거나 줄이기를 끝낸 뒤에 이벤트를 실행하도록하여 최적화된 화면을 구성할 수 있을 것이다.
const [screenWidth, setScreenWidth] = useState(window.innerWidth);
const handleResize = () => {
setScreenWidth(window.innerWidth);
};
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
아래처럼 setTimeout 메서드를 사용하여 최적화를 간단하게 할 수 있다. setTimeout메서드로 0.4초가 지나기 전 resize이벤트가 발생되면 이전에 설정해둔 내용을 clear 시키고 다시 새로운 resizeTimerRef를 설정해준다. 따라서 resizing마다 로그가 찍히지 않는 것이다.
const [screenWidth, setScreenWidth] = useState(window.innerWidth);
const resizeTimerRef = useRef<NodeJS.Timeout | null>(null);
const handleResize = () => {
setScreenWidth(window.innerWidth);
console.log("resize");
};
useEffect(() => {
const handleResizeWithTimer = () => {
if (resizeTimerRef.current !== null) {
clearTimeout(resizeTimerRef.current);
}
resizeTimerRef.current = setTimeout(handleResize, 400);
};
window.addEventListener("resize", handleResizeWithTimer, false);
return () => {
if (resizeTimerRef.current !== null) {
clearTimeout(resizeTimerRef.current);
}
window.removeEventListener("resize", handleResizeWithTimer);
};
}, []);
또한, useEffect 훅을 사용하기 때문에 useEffect내부에서 변수를 선언하고 사용할 땐 주의해야한다.
useEffect는 렌더링 된 후 실행되기 때문에, 그 안에서 변수를 선언하면 매 렌더링마다 새로운 변수가 생성되기 때문에 원하는 결과를 얻을 수 없다. 그렇기 때문에 resizeTimer를 useRef로 관리하였다. useRef.current를 통해 변수의 값을 유지하면서 렌더링 사이에서 변경할 수 있었다.
참고
🌐 브라우저 Resize 이벤트 최적화 하기
Window Resize Event 브라우저 & 윈도우 화면 높이 / 너비 구하는 법 window.innerWidth; // 브라우저 화면의 너비 window.innerHeight; // 브라우저 화면의 높이 window.outerWidth; // 브라우저 전체의 너비 window.outerHeigh
inpa.tistory.com
[Javascript] 디바운싱과 쓰로틀링
디바운스와 쓰로틀링 모두 웹에서 발생하는 이벤트를 제어하는 방법이다. 예를 들어 스크롤 이벤트의 경우 스크롤링 할 때마다 발생하는데, 그 때마다 같은 작업을 실행하게 되면 성능 문제가
velog.io
스로틀링과 디바운스 | 일일일
스크롤 이벤트를 디바운스로 처리하기에 어려움이 있어서 스로틀링을 적용하고 적용한 방법에 대해 설명했다. 스로틀링은 일정 시간 동안 이벤트가 발생하면 처음 한 번만 실행되고, 일정 시간
oneoneone.kr