프로젝트 회고, 리팩토링/포트폴리오 프로젝트

포트폴리오 resize 이벤트 리팩토링

plla2 2023. 8. 29. 14:18

포트폴리오 제작 중에 브라우저의 화면 너비를 구해서 너비에 따라 화면구성을 달리해줘야 했다. 그래서 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를 통해 변수의 값을 유지하면서 렌더링 사이에서 변경할 수 있었다.

 

https://oneoneone.kr/content/a58b31f0

 

 

참고

 

🌐 브라우저 Resize 이벤트 최적화 하기

Window Resize Event 브라우저 & 윈도우 화면 높이 / 너비 구하는 법 window.innerWidth; // 브라우저 화면의 너비 window.innerHeight; // 브라우저 화면의 높이 window.outerWidth; // 브라우저 전체의 너비 window.outerHeigh

inpa.tistory.com

 

 

[Javascript] 디바운싱과 쓰로틀링

디바운스와 쓰로틀링 모두 웹에서 발생하는 이벤트를 제어하는 방법이다. 예를 들어 스크롤 이벤트의 경우 스크롤링 할 때마다 발생하는데, 그 때마다 같은 작업을 실행하게 되면 성능 문제가

velog.io

 

 

스로틀링과 디바운스 | 일일일

스크롤 이벤트를 디바운스로 처리하기에 어려움이 있어서 스로틀링을 적용하고 적용한 방법에 대해 설명했다. 스로틀링은 일정 시간 동안 이벤트가 발생하면 처음 한 번만 실행되고, 일정 시간

oneoneone.kr