React 애니메이션, Framer Motion vs GSAP 뭘로 최적화할까요?

React에서 애니메이션 적용 시 자주 사용되는 라이브러리 두가지에 대해서 알아봅니다.

ReactFramerFramer-motionGSAP애니메이션
--

React 애니메이션, Framer Motion vs GSAP: 뭘로 최적화할까요?

React로 웹사이트를 만들다 보면 꼭 욕심나는 게 있죠. 바로 '애니메이션'입니다. 사용자의 눈을 사로잡는 부드러운 인터랙션을 구현할 때, Framer Motion과 GSAP는 아마 가장 먼저 떠오르는 선택지일 겁니다.

두 라이브러리 모두 정말 훌륭하지만, 사실 성능을 최적화하는 접근 방식이 완전히 다릅니다.

  • Framer Motion은 "React 컴포넌트처럼" 생각하고, React 생태계 안에서 똑똑하게 움직이도록 최적화되어 있어요.
  • GSAP는 "초고성능 엔진"을 React의 렌더링 사이클에 방해되지 않게 '안전하게' 연결하는 데 집중하죠.

이번 글에서는 두 라이브러리가 어떤 차별화된 방법으로 성능을 잡는지, 좀 더 파고들어 보겠습니다.

1. Framer Motion: React와 한 몸처럼 움직이는 최적화

Framer Motion은 애니메이션을 React의 선언적인 방식 그대로 다룹니다. 최적화 전략도 React 개발자라면 "아, 이 문제!" 할 만한 것들을 해결하는 데 초점을 맞추고 있죠.

핵심 전략 1: LazyMotion (가벼운 시작을 위한 코드 분리)

Framer Motion의 가장 강력한 무기 중 하나입니다. 애니메이션 기능을 전부 다 불러오는 게 아니라, 딱 필요한 기능만 골라서 불러올 수 있게 해줍니다.

  • 어떻게 하냐면요? LazyMotion 컴포넌트로 애니메이션을 쓸 컴포넌트를 감싸주고, domAnimation (가벼운 필수 기능) 같은 기능 묶음을 지정해주는 거예요.
  • 뭐가 좋을까요? 웹사이트 첫 로딩 속도에 치명적인 '번들 사이즈'를 확 줄여줍니다. 사용자가 당장 쓰지도 않을 드래그 기능 때문에 첫 페이지가 버벅댈 필요가 없는 거죠.
import { LazyMotion, domAnimation, m } from "framer-motion";

function MyComponent() {
return (
<LazyMotion features={domAnimation}>
  {/* m.div에 필요한 최소 기능만 쏙! */}
  <m.div animate={{ scale: 1.5 }} />
</LazyMotion>
);
}

핵심 전략 2: 알아서 해주는 하드웨어 가속

Framer Motion은 기본적으로 transform이나 opacity처럼 성능에 유리한 속성들을 사용해 애니메이션을 만듭니다.

  • 어떻게 하냐면요? 이런 속성들은 브라우저가 레이아웃을 다시 계산할 필요 없이 GPU가 바로 처리해줘서 아주 빠릅니다.
  • 뭐가 좋을까요? 개발자가 일일이 신경 쓰기 귀찮은 will-change 같은 CSS 속성을 애니메이션이 시작할 때 알아서 켜고, 끝나면 알아서 꺼줍니다. 덕분에 성능은 챙기면서 메모리 낭비는 막아주죠.

핵심 전략 3: AnimatePresence (사라질 때의 미학)

React에서 컴포넌트가 사라질 때(Unmount) 애니메이션을 넣는 건 꽤나 골치 아픈 일입니다. AnimatePresence는 이 과정을 정말 우아하게 해결해 줍니다.

  • 어떻게 하냐면요? 컴포넌트가 DOM에서 사라지기 전에, exit 애니메이션이 끝날 때까지 잠깐 기다려줍니다.
  • 뭐가 좋을까요? useEffectsetTimeout으로 복잡하게 타이밍을 맞출 필요가 없어집니다. React의 생명주기와 애니메이션을 자연스럽게 연결해 줘서 코드가 정말 깔끔해져요.

2. GSAP: React를 방해하지 않는 고성능 엔진

GSAP는 React와는 별개로 움직이는, 정말 빠른 JavaScript 애니메이션 엔진입니다. React에서 GSAP를 최적화한다는 건, 이 강력한 엔진이 React의 리렌더링을 방해하지 않고 메모리 누수 없이 깔끔하게 작동하도록 만드는 게 핵심입니다.

핵심 전략 1: useGSAP (안전한 사용과 자동 청소)

React 컴포넌트 안에서 GSAP를 쓰다 보면 가장 무서운 게 메모리 누수입니다. 컴포넌트는 사라졌는데, 애니메이션은 계속 실행되려고 하는 상황이죠.

  • 어떻게 하냐면요? @gsap/react 패키지의 useGSAP 훅을 사용하면 됩니다. 이 훅 안에서 만든 모든 애니메이션은 자동으로 '컨텍스트'라는 곳에 등록돼요.
  • 뭐가 좋을까요? useEffect의 클린업 함수처럼, 컴포넌트가 사라질 때 등록됐던 모든 애니메이션을 알아서 .kill()(제거) 해줍니다. 개발자가 깜빡하고 청소 코드를 빼먹어서 생기는 문제를 원천 봉쇄해 주죠. 정말 마음이 편해집니다.
import { useGSAP } from "@gsap/react";
import { useRef } from "react";

function MyComponent() {
const container = useRef();

// 이 안에서 만든 GSAP 애니메이션은
// 컴포넌트가 사라질 때 자동으로 청소됩니다.
useGSAP(
() => {
gsap.to(".box", { x: 300 });
},
{ scope: container } // scope로 범위를 좁혀주는 센스!
);

return (
<div ref={container}>
  <div className="box"></div>
</div>
);
}

핵심 전략 2: ref로 DOM 직접 제어 (React 리렌더링 우회)

GSAP가 압도적인 성능을 내는 비결은 React의 렌더링 과정을 살포시 비켜가는 데 있습니다.

  • 어떻게 하냐면요? React의 state를 바꿔서 애니메이션을 주는 게 아니라, useRef로 가져온 실제 DOM 요소(ref.current)에 직접 스타일을 적용합니다.
  • 뭐가 좋을까요? 애니메이션 매 프레임마다 state가 바뀌면, React는 계속해서 리렌더링을 하느라 바빠집니다. GSAP는 React 몰래(?) DOM을 직접 움직이기 때문에, 이런 비싼 렌더링 비용이 전혀 들지 않아요. 수백 개 요소가 동시에 춤추는 복잡한 애니메이션도 거뜬히 소화하는 이유죠.

그래서, 제 프로젝트엔 뭘 써야 할까요?

정리하자면 이렇습니다.

  • Framer Motion이 끌린다면:

  • React의 선언적인 방식이 너무 편하고, 컴포넌트처럼 다루고 싶을 때.

  • 버튼 호버, 모달 등장, 페이지 전환 같은 일반적인 UI 인터랙션이 주력일 때.

  • **초기 로딩 속도(번들 사이즈)**가 무엇보다 중요할 때 (LazyMotion).

  • GSAP가 끌린다면:

  • 스크롤에 따라 펼쳐지는 복잡한 스토리텔링 애니메이션이 필요할 때.

  • 수백, 수천 개의 요소가 동시에 움직여야 하는 최고 수준의 성능이 필요할 때.

  • ScrollTrigger 같은 강력한 플러그인을 활용해 역동적인 사이트를 만들고 싶을 때.

'무조건 이게 더 좋다'는 건 없습니다. 내 프로젝트가 **'첫 로딩 속도'**가 더 급한지, 아니면 **'복잡한 애니메이션의 런타임 성능'**이 더 중요한지 고민해보고, 딱 맞는 라이브러리를 선택하는 게 베스트입니다.


🔗 더 깊게 파고들기 (공식 문서)

이 글을 읽고 더 궁금해지셨다면, 공식 문서를 확인해 보세요.

Framer Motion

GSAP

  • GSAP ❤️ React (React에서 GSAP 쓰기): useGSAP 훅과 메모리 관리에 대한 필수 가이드.
  • [useGSAP() 훅 API](<https: //www.google.com/search?q=%5Bhttps://gsap.com/docs/v3/React/useGSAP/%5D(https://gsap.com/docs/v3/React/useGSAP/)>): useGSAP 훅의 상세한 옵션들.
    • [gsap.context()](<https: //www.google.com/search?q=%5Bhttps://gsap.com/docs/v3/GSAP/gsap.context/%5D(https://gsap.com/docs/v3/GSAP/gsap.context/)> ): useGSAP의 핵심 원리이자, 메모리 관리를 위한 GSAP의 기능.

댓글

0/2000
Newsletter

이 글이 도움이 되셨나요?

새로운 글이 발행되면 이메일로 알려드립니다.

뉴스레터 구독하기