IT/React

리액트 스크롤 이벤트(React Scroll Event) 적용하기

라임웨일 2022. 4. 26. 15:46
반응형

 

요즘은 다양한 웹 환경에서  스크롤 이벤트를 요청하는 경우가 이전에 비해 굉장히 많아졌습니다. 오히려 아무런 동적 애니메이션 효과나 이벤트가 없는 정적인 웹 화면이 무언가 심심하고 이상하게 생각되기도 합니다. 

 

리엑트에서 스크롤 이벤트를 구현하는 방법은 사용자(유저)가 스크롤 이벤트를 발생시키는 지 확인하고 스크롤이 발생한다면 이벤트를 적용하는 방법이 가장 일반적으로 생각하는 방법입니다.  이를 위해서 scroll 이벤트를 이용하여 해당 값을 가져오게 됩니다.  하지만 실제로 이렇게 적용해보면 굉장히 많은 문제점이 발생됩니다.

 

- 스크롤 이벤트를 바로 적용한 경우

useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll); //clean up
    };
  }, []);

  const handleScroll = () => {
    console.log('scrolled');
  };

 

위와 같은 방식으로 구현을 한 후  콘솔창을 통해 확인을 하게 되면 사용자는 스크롤 이벤트가 많이 진행되지 않았음에도 불구하고 이벤트 지속적으로 발생해서 로그가 순식간에 무수히 많이 발생하는 것을 볼 수 있습니다. (🥶🥶🥶🥶 꺅~~~~~)

 

이런 이유가 발생하는 이유는 React의 특성상 변화가 있을 때 DOM을 다시 탐색하고 변화가 있는 부분을 Render하여  다시 그려주기(이 부분이 브라우저의 동작원리 중 리플로우, 리페인팅에 해당합니다.) 때문인데 위와 같은 방식으로 구현을 하게 되면 성능에도 문제가 발생합니다. 

 

위와 같은 현상과 성능 개선을 위해 스크롤 이벤트에 Timer를 두어서 Timer안에서 이벤트가 발생하고 이벤트가 발생된 후 해당 타이머는 초기화를 시켜주어 이벤트의 중복을 통한 성능 지연을 방지합니다. 

 

- 성능개선 코드

export default function App() {  
  const targetRef = useRef(null);  
  const handleScroll = () => {
    console.log("scrolling");
    
    if (window.scrollY > 0) {
      targetRef.current.style.position = "fixed";      
    }
  };

  useEffect(() => {    
    const timer = setInterval(() => {
      window.addEventListener("scroll", handleScroll);
    }, 100);
    return () => {
      clearInterval(timer);
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  return (
    <div className="App">
      <div ref={targetRef}>이벤트 발생위치</div>
    </div>
   );
}

 

위 코드로 적용하고 로그를 확인해보면 처음 코드와는 확연히 다르게 로그가 발생되는 것을 확인하실 수 있습니다. 

감사합니다.

 

참고 : https://stackoverflow.com/questions/68751736/throttle-window-scroll-event-in-react-with-settimeout

반응형
광고차단(애드블록)프로그램이나 브라우저를 사용중이시면 프로그램을 비활성화이나 블로그 주소를 예외 처리 해주시면 광고가 노출됩니다. 귀찮고 번거롭겠지만 광고 클릭은 저에게는 큰 힘이 됩니다. 🙇🏻‍♂️🙇🏻‍♀️
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)
//