[React] 화면 크기에 따라 함수 실행 제어하기
포스트
취소

[React] 화면 크기에 따라 함수 실행 제어하기

문제 상황

스크롤 애니메이션이 들어간 페이지를 만들다 보면 데스크톱에서는 잘 보이지만, 모바일에서는 오히려 불편한 경우가 있습니다.

예를 들어 가로로 이동하는 GSAP 애니메이션을 큰 화면에서만 실행하고, 화면 너비가 1080px 이하일 때는 실행하지 않게 만들고 싶을 수 있습니다.

이럴 때는 현재 화면 크기를 확인한 뒤 조건에 맞을 때만 함수를 실행하면 됩니다.


기존 코드

처음에는 화면 크기와 관계없이 애니메이션을 바로 등록했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
useEffect(() => {
  const projectList = document.getElementById("projectList");

  gsap.to(".projectsBox", {
    xPercent: -100,
    scrollTrigger: {
      trigger: ".projectsBox",
      start: `${projectList.clientHeight + 150}px 99%`,
      end: `100%-=${projectList.clientHeight}px 10%`,
      scrub: 0.5,
    },
  });
}, []);

이렇게 하면 모바일 화면에서도 애니메이션이 등록됩니다.

화면이 좁은 환경에서는 레이아웃이 깨지거나 불필요한 스크롤 동작이 생길 수 있습니다.


화면 너비 조건 추가하기

window.innerWidth를 확인해서 특정 너비 이상일 때만 실행할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
useEffect(() => {
  const setupAnimation = () => {
    if (window.innerWidth <= 1080) return;

    const projectList = document.getElementById("projectList");
    if (!projectList) return;

    gsap.to(".projectsBox", {
      xPercent: -100,
      scrollTrigger: {
        trigger: ".projectsBox",
        start: `${projectList.clientHeight + 150}px 99%`,
        end: `100%-=${projectList.clientHeight}px 10%`,
        scrub: 0.5,
      },
    });
  };

  setupAnimation();
}, []);

이제 화면 너비가 1080px 이하라면 애니메이션 등록을 건너뜁니다.


resize 이벤트까지 처리하기

사용자가 브라우저 크기를 변경할 수도 있으므로 resize 이벤트를 함께 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
useEffect(() => {
  const setupAnimation = () => {
    if (window.innerWidth <= 1080) return;

    const projectList = document.getElementById("projectList");
    if (!projectList) return;

    gsap.to(".projectsBox", {
      xPercent: -100,
      scrollTrigger: {
        trigger: ".projectsBox",
        start: `${projectList.clientHeight + 150}px 99%`,
        end: `100%-=${projectList.clientHeight}px 10%`,
        scrub: 0.5,
      },
    });
  };

  setupAnimation();
  window.addEventListener("resize", setupAnimation);

  return () => {
    window.removeEventListener("resize", setupAnimation);
  };
}, []);

cleanup에서 이벤트를 제거해주면 컴포넌트가 사라진 뒤에도 이벤트가 남아 있는 문제를 막을 수 있습니다.


GSAP에서는 cleanup도 중요해요

GSAP ScrollTrigger를 사용하는 경우에는 애니메이션이 중복 등록되지 않도록 정리 로직도 고려해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
useEffect(() => {
  let animation: gsap.core.Tween | null = null;

  const setupAnimation = () => {
    animation?.kill();

    if (window.innerWidth <= 1080) return;

    const projectList = document.getElementById("projectList");
    if (!projectList) return;

    animation = gsap.to(".projectsBox", {
      xPercent: -100,
      scrollTrigger: {
        trigger: ".projectsBox",
        start: `${projectList.clientHeight + 150}px 99%`,
        end: `100%-=${projectList.clientHeight}px 10%`,
        scrub: 0.5,
      },
    });
  };

  setupAnimation();
  window.addEventListener("resize", setupAnimation);

  return () => {
    animation?.kill();
    window.removeEventListener("resize", setupAnimation);
  };
}, []);

화면 크기가 바뀔 때마다 애니메이션을 새로 등록한다면 이전 애니메이션을 정리하는 것이 안전합니다.


마무리

화면 크기에 따라 특정 함수를 실행할지 결정하려면 window.innerWidth를 조건으로 사용할 수 있습니다.

처음 렌더링 시 한 번 실행하고, 화면 크기 변경까지 대응해야 한다면 resize 이벤트를 함께 등록하면 됩니다.

이벤트 리스너와 애니메이션 인스턴스는 cleanup에서 정리해두는 것이 좋습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.