snack-game / front

스낵게임! 선택한 스낵 숫자합을 10을 만들면 점수를 얻는 게임입니다!
https://snackga.me
14 stars 0 forks source link

[Refactoring] 공통 컴포넌트 애니메이션을 framer -> GSAP 으로 교체 #229

Closed nijuy closed 3 months ago

nijuy commented 4 months ago
nijuy commented 3 months ago

@dev-dong-su 이거 작업하던 도중에 고민이 생겼는데 내용이 길어서 코멘트로 적어보았습니다.............. ╯︿╰

framer-motion을 GSAP으로 바꾸는 게 괜찮을까?

1. 일부 기능의 경우 같은 코드를 GSAP으로 바꿀 때 늘어나는 코드 양이 많다

예를 들어 hover 이벤트를 구현할 때

// framer-motion은 이걸로 되지만
<motion.div whileHover={{ scale: 2 }}><motion.div> 
// GSAP은 약간 많이 (...) 길어진다
  const buttonRef = useRef<HTMLButtonElement>(null);

  const { contextSafe } = useGSAP();

  useGSAP(() => {
    const tl = gsap.timeline({ paused: true });
    tl.to(buttonRef.current, { scale: 2, duration: 0.15 });

    const onHover = contextSafe(() => tl.play());
    const onHoverLeave = contextSafe(() => tl.reverse());

    buttonRef.current?.addEventListener('pointerenter', onHover);
    buttonRef.current?.addEventListener('pointerleave', onHoverLeave);

    return () => {
      buttonRef.current?.removeEventListener('pointerenter', onHover);
      buttonRef.current?.removeEventListener('pointerleave', onHoverLeave);
    };
  });

2. 완전한 대체가 불가능한 거 같다

(이건 제 추측입니다..!!)

GSAP으로 최대한 비슷하게 바꾸기 위해 framer-motion를 조금 살펴보던 중에, 우선순위에 관한 코드를 발견했습니다. 문서에서도 제스처 사이 우선순위에 대한 부분이 언급되어 있더라고요..!

motion components automatically manage the interplay between these while props. So for instance, if hovering starts and stops while the tap gesture is active, the tap gesture receives priority and any properties defined on both will remain in their tapped state. - Docs

반면 GSAP은 우선순위를 사용자가 관리할 수 있거나 내부에서 보장하는 순서가 따로 있진 않은 거 같아요

이게 왜 문제가 되냐면, Button 같은 경우 Hover, Tab을 모두 적용해야 하는데 GSAP timeline을 2개 만들어서 각 제스처를 적용했을 때 framer 만큼 매끄럽게 돌아가지가 않더라고요..


여기까지 알아봤을 때 그냥 framer를 공통 컴포넌트에 한해서만 유지하자고 할까..? 라는 생각이 들었는데 bundlephobia에서 조회해보니까 gsap + @gsap/react 의 번들 사이즈랑 framer-motion의 번들 사이즈가 거의 맞먹어서......... 차라리 매끄러움을 살짝 포기하더라도 gsap으로 가는 게 전체 번들 사이즈면에서 나을지......... 또 고민이 되더라고요

엉엉.. 저도 아직 딱 결론을 내리고 코멘트 다는 게 아니라 내용이 좀 이랬다저랬다 하는 점 양해 부탁합니더 같이 의논해보고 싶어용

gsap gsap/react framer-motion
gsap gsap_react framer-motion
dev-dong-su commented 3 months ago

오호 생각치 못한 부분인데 아주 좋은 고민거리내요! @nijuy 👍 확실히 저도 고민이 많이 되네요..

1. 일부 기능의 경우 같은 코드를 GSAP으로 바꿀 때 늘어나는 코드 양이 많다

아무래도 더 세부적으로 제어가 가능하다 보니 개발자의 책임과 코드양의 트레이드오프가 존재하네요.. 자주 사용되는 애니메이션을 훅으로 분리해 ref만 적용할 수 있도록 애니메이션 시스탬을 만들 필요가 있어보이긴 해요. 그치만 이것도 비용이라 흠...

2. 완전한 대체가 불가능한 거 같다

이 부분은 아마 gsap 가 자체적으로 .then 메서드를 지원하기에 await로 동기적인 동작을 수행할 수 있어서 그런 것 같습니다. framer-motion의 경우는 추상화가 많이 되어있다보니 우선순위를 통해 문제를 해결해 본 것 같네용.

   gsap.to(this.messageLabel, {
      alpha: 0,
      duration: 0.2,
      ease: 'linear',
      delay: 0.6,
    });
    await gsap.to(this.messageLabel.scale, {
      x: 3,
      y: 3,
      duration: 0.8,
      ease: easeMidSlowMotion,
    });

향후를 생각한다면 더 편리하고 쉽게 적용이 가능한 framer-motion을 사용하는게 좋을 것 같다는 생각이 들었어요. gsap의 경우 세부적인 애니메이션 제어가 가능하지만 그만큼 개발비용이 증가하니 게임이 아니라면 이런 세부적인 제어가 필요할까? 라는 의문도요. 결론적으로 저는 gsap 는 게임에서만 사용하고 framer-motion은 유지하기로 기울었어요. 보리 생각은 어떤가요?

nijuy commented 3 months ago

아무래도 더 세부적으로 제어가 가능하다 보니 개발자의 책임과 코드양의 트레이드오프가 존재하네요..

저도 이렇게 멋지게 말하는 습관을 들여야겠어요

결론적으로 저는 gsap 는 게임에서만 사용하고 framer-motion은 유지하기로 기울었어요.

좋습니다!! 특히 게임이 아닌 부분에서 이런 세부적인 제어가 필요할까? 라는 부분에 공감합니다...🥺 단순히 라이브러리 간소화하면 좋은 거 아닌가??!?! 하는 생각에서 출발한 이슈인데 그 과정에 들어가는 비용이나 이걸로 달성할 수 있는 결과에 대한 고민이 부족했던 거 같아요

해당 이슈는 닫아두겠습니다! 하던 일이 증발한 관계로,, 내일 뭐해둘지 띵킹의 시간 갖겠습니다