๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ‘จ‍๐Ÿ’ป web.dev/fe

React Framer Motion ํ†บ์•„๋ณด๊ธฐ

by HandHand 2023. 3. 27.

 

๐Ÿ“Œ Framer Motion?

Framer Motion ์€ React ๋กœ ๊ฐœ๋ฐœ๋œ Animation Library ์ž…๋‹ˆ๋‹ค.

๊ด€๋ จ๋œ ํŒจํ‚ค์ง€์ค‘์— ์ง€์†์ ์œผ๋กœ ์‚ฌ์šฉ๋Ÿ‰ ๋ฐ ๊ด€์‹ฌ๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ณ  ์žˆ๋Š” ์ถ”์„ธ์ž…๋‹ˆ๋‹ค. ๐Ÿ“ˆ

์›น์•ฑ์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋‹ค๋ฃจ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ,

๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ์ถฉ๋ถ„ํ•œ ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๊ธฐ์—๋Š” ์ƒ๊ฐ๋ณด๋‹ค ๊ณ ๋ คํ•  ์‚ฌํ•ญ์ด ๋งŽ๊ณ  ๊นŒ๋‹ค๋กœ์šด ๊ฒƒ์ด ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ ์œ„ํด๋ฆฌ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์— ๋„์›€์ด ๋ ์ˆ˜๋„ ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์†Œ๊ฐœํ•ด๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด๋ คํ•ฉ๋‹ˆ๋‹ค.

 

npm trends

 

 

๐Ÿ“Œ TL;DR

Framer Motion ์˜ ํŠน์ง•

 

  • TypeScript ์ง€์›
  • ์ตœ์ ํ™”๋œ ์„ฑ๋Šฅ ๋ฐ ํ’๋ถ€ํ•œ API
    • physics ๊ธฐ๋ฐ˜์˜ ์‚ฌ์‹ค์ ์ธ transitionํšจ๊ณผ ์ œ๊ณต (spring, tween, inertia)
    • ๋ชจ๋˜ ์›น์•ฑ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ•„์š”๋กœ ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ชจ์…˜๋“ค์„ ๊ฐ„๊ฒฐํ•œ API ๋กœ ์ œ๊ณต
  • ์„ ์–ธ์ ์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฝ”๋“œ ๊ตฌํ˜„ (with Component Props, React Hook, Utilities)
  • ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ๋™์ผ ์นดํ…Œ๊ณ ๋ฆฌ์˜ ํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋น„ํ•ด ๋‚ฎ๊ณ  ์ปค์Šคํ…€์— ์šฉ์ดํ•จ
  • (+) Framer ↔ Framer-Motion ๊ฐ„์— ์ ์šฉ์ด ์šฉ์ดํ•จ
    • ์ž๋™ ์ฝ”๋“œ ์ƒ์„ฑ ๊ธฐ๋Šฅ ์ œ๊ณต
    • ๋””์ž์ด๋„ˆ๊ฐ€ motion ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ์‹œ๋Œ€๊ฐ€ ์˜ฌ๊นŒ?
    • Framer ๋ฅผ ๋ฉ”์ธ ๋””์ž์ธํˆด๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ํฐ ์žฅ์ ์ด ๋  ์ˆ˜๋„?

 

๐Ÿ“Œ Framer Motion Quick Tutorial

Framer Motion ๊ตฌ์„ฑ ์š”์†Œ ๋œฏ์–ด๋ณด๊ธฐ

๊ทธ๋Ÿผ ์ด์ œ Framer-Motion ์„ ๊ตฌ์„ฑํ•˜๋Š” ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

โš ๏ธ ์—ฌ๊ธฐ์„œ ๋ชจ๋“  API ๋ฅผ ๋‹ค๋ฃจ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

 

1๏ธโƒฃ Animation

Framer-Motion ์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ€์žฅ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ๋Š” motion ์ž…๋‹ˆ๋‹ค.

motion ์ปดํฌ๋„ŒํŠธ๋Š” ํ‘œ์ค€ HTML ๊ณผ SVG ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ,

์ผ๋ฐ˜์ ์œผ๋กœ animate ์†์„ฑ์œผ๋กœ ์›ํ•˜๋Š” animation ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ํŠน์ • ๊ฐ’์ด๋‚˜ keyframe ์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

<motion.div 
    animate={{ 
        scale: [1, 2, 2, 1, 1], 
        rotate: [0, 0, 180, 180, 0] 
    }} 
/>

 

animate ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•Œ์•„์„œ ํ•ด๋‹น ๊ฐ’์œผ๋กœ ๋ณ€ํ™”ํ•˜๋ฉฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ motion ์€ ๋ณ€ํ™”ํ•˜๋Š” ๊ฐ’์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์ ์ ˆํ•œ transition ํšจ๊ณผ๋ฅผ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.

(์˜ˆ๋ฅผ ๋“ค์–ด x, y ๋‚˜ scale , rotate ๊ณผ ๊ฐ™์€ physical ์†์„ฑ๋“ค์€ spring , opacity ๋‚˜ color ๋Š” tween ํšจ๊ณผ)

๋ฌผ๋ก  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์›ํ•˜๋Š” ํšจ๊ณผ๋ฅผ ์ง€์ •ํ• ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ animate ์— ์ง€์ •๋œ keyframes ๋“ค์€ ๊ณ ๋ฅด๊ฒŒ ๋ถ„๋ฐฐ๋œ animation ์‹คํ–‰์‹œ๊ฐ„์„ ๊ฐ€์ง€๋Š”๋ฐ,

times ์†์„ฑ์„ ํ†ตํ•ด 0~1 ์ดˆ ์‚ฌ์ด์—์„œ ๊ฐ ํ”„๋ ˆ์ž„๋ณ„ ์‹œ์ž‘์‹œ๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

<motion.circle
    cx={500}
    animate={{ cx: [null, 100, 200] }}
    transition={{ ease: 'easeOut', duration: 3, times: [0, 0.2, 1] }}
/>

 

์• ๋‹ˆ๋ฉ”์ด์…˜์˜ transition stage ๋ฅผ ์ถ”์ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด,

motion ์ปดํฌ๋„ŒํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” animation event props ์„ ์ด์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

<motion.div 
    animate={{ x: 100, opacity: 0 }} 
    onAnimationStart={onStart}
    onUpdate={onUpdate}
    onAnimationComplete={definition => {
    console.log('Completed animating', definition)
  }}
/>

 

๋˜ํ•œ motion ์ปดํฌ๋„ŒํŠธ๋Š” SSR(ServerSide Rendering) ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์ผ๋ถ€ SVG ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ์—๋Š” ์•„์ง๊นŒ์ง€ ์™„์ „ํžˆ ํ˜ธํ™˜๋˜์ง€๋Š” ์•Š๋Š”๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ’ก React Tree ์–ธ๋งˆ์šดํŠธ ์‹œ์—๋„ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

ํŠน์ • ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM ํŠธ๋ฆฌ์—์„œ ์ œ๊ฑฐ๋  ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์œ ์ง€ํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•˜๋Š”๊ฒŒ ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ react-transition-group ์„ ์ด์šฉํ•˜๋ฉด

์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•˜๊ธฐ ์ „์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์›ํ•˜๋Š”๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

show && <Popup />

 

Framer-Motion ์—์„œ๋Š” ์ด๋ฅผ ์œ„ํ•ด AnimatePresence ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

<AnimatePresence>
    {show && <Popup />}
</AnimatePresence>

 

2๏ธโƒฃ ๋ณต์žกํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ตฌํ˜„์„ ์œ„ํ•œ Variants

ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹จ์ˆœํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ์—๋Š” animate ์†์„ฑ ํ•˜๋‚˜๋กœ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ• ๊ฒ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์— ์ „ํŒŒ๋˜์–ด ๋ณตํ•ฉ์ ์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

์ด๋ฅผ ์œ„ํ•ด์„œ Framer-Motion ์€ variants ๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

variants ๋Š” ๋ถ€๋ชจ์˜ ์ž์‹ motion ์ปดํฌ๋„ŒํŠธ๋“ค๋กœ ์ „ํŒŒ(propagation) ๋˜๊ณ ,

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์‹๋“ค์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์กฐ์œจ(orchestration)ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

 

variants ๋ฅผ ๋™์ (dynamic)์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, custom ์†์„ฑ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

const variants = {
  visible: i => ({
    opacity: 1,
    transition: {
      delay: i * 0.3,
    },
  }),
}

<motion.li
  custom={i}
  animate="visible"
  variants={variants}
/>

 

๊ทธ๋ฆฌ๊ณ  ํ•˜๋‚˜์˜ motion ์—์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ variants ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ ๊ฐ variants ์—์„œ ๊ฒน์น˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์†์„ฑ์ด ์กด์žฌํ•˜๋ฉด, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์ •์˜๋œ ๊ฒƒ์œผ๋กœ ์ง€์ •๋ฉ๋‹ˆ๋‹ค.

 

<motion.div variants={['open', 'primary']} />

 

3๏ธโƒฃ Layout Animation

width , height ๋“ฑ๋“ฑ์˜ css layout ๊ด€๋ จ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์ฃผ์š” ์„ฑ๋Šฅ์ €ํ•˜๋ฅผ ์ผ์œผํ‚ค๋Š” ์š”์†Œ์ž…๋‹ˆ๋‹ค.

Framer-Motion ์—์„œ๋Š” ์ด๋Ÿฌํ•œ layout ๊ด€๋ จ ๊ฐ’ ๋ณ€๊ฒฝ์„ ์ถ”์ ํ•˜์—ฌ

transform ๊ธฐ๋ฐ˜์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

 

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ผ๋ฐ˜์ ์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ตฌํ˜„์— ์‚ฌ์šฉ๋˜๋Š” ์†์„ฑ์ด ์•„๋‹ˆ๋”๋ผ๋„

์›ํ•˜๋Š” transition ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(justify-content ๋Š” ํ˜„์žฌ ์ŠคํŽ™์ƒ transitionable ํ•œ ์†์„ฑ์ด ์•„๋‹™๋‹ˆ๋‹ค.)

 

์ด์ฒ˜๋Ÿผ, layout ๊ณผ ๊ด€๋ จ๋œ ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ๋ฉด re-render ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด์„œ ์ ์ ˆํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์›ํ•˜๋Š” transition ์œผ๋กœ ์ปค์Šคํ…€๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

4๏ธโƒฃ Gesture Animation

Framer-Motion ์€ React ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ์ด๋ฒคํŠธ๋ฅผ ํ™•์žฅํ•œ

hover, tap, pan, viewport, drag ๊ด€๋ จ gesture detection system ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋“ค์€ ๋ชจ๋‘ motion ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋ฉฐ

whileHover, whileTap, whileDrag, whileInView ๋“ฑ์˜ helper props ๋“ค๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ด๋“ค์€ transition prop ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ์›ํ•˜๋Š” gesture ํšจ๊ณผ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ

๋‘๊ฐœ ์ด์ƒ์˜ gesture ๊ฐ€ ํ•จ๊ป˜ ๋™์ž‘๋  ๊ฒฝ์šฐ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

motion ์€ ์ด๋“ค gesture ์‚ฌ์ด์—์„œ ์•Œ์•„์„œ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ฅธ interplay ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

 

5๏ธโƒฃ Draggable

Framer-Motion ์—์„œ๋Š” drag gesture ์™€ ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ์— drag ๋ผ๋Š” ์†์„ฑ์„ ๋ถ€์—ฌํ•ด์ฃผ๋ฉด draggable ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

drag ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๊ธฐ์œ„ํ•ด px ๋‹จ์œ„๋กœ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ๋Œ€์ƒ์ด ๋  ์ปดํฌ๋„ŒํŠธ์˜ ref ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Reorder Group ์€ child component ์˜ key ๋ฅผ ํ†ตํ•ด ์œ„์น˜ ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๊ณ ,

๋ณ€ํ™”๋œ ์ˆœ์„œ์— ๋งž๋Š” ์ƒํƒœ๋ฅผ onReorder prop ์„ ํ†ตํ•ด ์—…๋ฐ์ดํŠธํ•ด์ค๋‹ˆ๋‹ค.

 

6๏ธโƒฃ Scroll linked & triggerd Animation

์ธํ„ฐ๋ ‰ํ‹ฐ๋ธŒ ์›น์—์„œ๋Š” ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•œ ์—ฌ๋Ÿฌ transition ํšจ๊ณผ๋“ค์„ ๊ตฌํ˜„ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ๋Š” ์Šคํฌ๋กค ์ •๋„์— ๋”ฐ๋ผ ์ƒ๋‹จ progress bar ๋ฅผ ๋…ธ์ถœํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

 

 

7๏ธโƒฃ Motion Values

๋ชจ๋“  motion ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ MotionValue ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ animation ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ์—๋Š” ์ด ๊ฐ’์„ ์ง์ ‘ ๋‹ค๋ฃฐ ์ผ์ด ์—†์ง€๋งŒ, ์ข€ ๋” ๋ณต์žกํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ

์ง์ ‘ ์ด ๊ฐ’์„ ์ƒ์„ฑํ•ด์„œ motion ์ปดํฌ๋„ŒํŠธ์— ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด animation state ๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ์ฐธ์กฐํ•˜์—ฌ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์˜ motion ์„ ๋™๊ธฐํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ

react ์˜ render cycle ์— ๊ด€๊ณ„์—†์ด visual ์†์„ฑ์„ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Framer-Motion ์—์„œ๋Š” ์ด๋Ÿฌํ•œ Motion Value ๋“ค์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์—ฌ๋Ÿฌ react hook ๋“ค์„ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

useTransform, useSpring, useVelocity ๋“ฑ์œผ๋กœ ํŠน์ • Motion Value ์— ๋”ฐ๋ผ ๋ณ€ํ™”ํ•˜๋Š”

์ƒˆ๋กœ์šด Motion Value ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜, useTime ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ”„๋ ˆ์ž„ ๋‹จ์œ„์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์™ธ์—๋„ ์—ฌ๋Ÿฌ hook ๋“ค์ด ์žˆ์œผ๋‹ˆ, ํ•„์š”์— ๋”ฐ๋ผ ์ ์ ˆํ•œ feature ๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋„ค์š”.

 

8๏ธโƒฃ Utilities

์ด์™ธ์—๋„ Framer-Motion ์—์„œ๋Š” ์—ฌ๋Ÿฌ ์ธํ„ฐ๋ ‰์…˜ ๊ตฌํ˜„์— ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š”

useAnimationFrame, useInView, useDragControls ๋“ฑ์˜ ์œ ์šฉํ•œ custom hook ๋“ค์„ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

๋ณด๋‹ค ๋ณต์žกํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ตฌํ˜„์ด ํ•„์š”์— ํ•œ ๊ฒฝ์šฐ์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

 

๐Ÿ“Œ styled-component ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š”๋ฒ•

1๏ธโƒฃ styled-component ๋ฅผ animatable ํ•˜๊ฒŒ ๋ฐ”๊พธ๊ธฐ

styled-component ์˜ as prop ์„ ์‚ฌ์šฉํ•˜์—ฌ Motion ์ปดํฌ๋„ŒํŠธ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

 

<MyComponent as={motion.div} animate={{ y: 100 }} />

 

2๏ธโƒฃ styled-component ๋กœ ์ปค์Šคํ…€ํ•œ Framer Motion ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

styled-component ์˜ ์Šคํƒ€์ผ์„ ํ™•์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

const MyCustomComponent = styled(motion.div)`
  width: 2rem;
  background-color: tomato;
`;

 

Animate Styled Components with Framer Motion!

 

Animate Styled Components with Framer Motion!

I love Framer Motion because it's a library that's easy to use and powerful. I've created page transi...

dev.to

 

๐Ÿ“Œ ๋ฒˆ๋“ค์‚ฌ์ด์ฆˆ ์ตœ์ ํ™”ํ•˜๊ธฐ

Framer-Motion ์€ ์˜จ์ „ํžˆ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ 50kb ์ด์ƒ์˜ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ€์ง€๋Š” ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.

๋Œ€์‹  rollup ์ด๋‚˜ webpack ๊ณผ ๊ฐ™์€ ๋ฒˆ๋“ค๋ง ํˆด์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, tree-shaking ์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,

ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์ด์ง€๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด ํŒจํ‚ค์ง€์˜ ๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜๋Š” motion ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จํ•  ๊ฒฝ์šฐ 29kb ๋ฏธ๋งŒ์œผ๋กœ๋Š” ์ตœ์ ํ™”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ,

๋งŒ์•ฝ motion ์ปดํฌ๋„ŒํŠธ์™€ ๋‹ค๋ฅด๊ฒŒ ๋ชจ๋“  ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ธฐ๋Šฅ๋“ค์„ preload ํ•˜์ง€ ์•Š๋Š” m ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด

์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ์‚ฌ์ด์ฆˆ๋ฅผ 4.9kb ๊นŒ์ง€ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(๋Œ€์‹  ์ดํ›„์— ์‚ฌ์šฉํ•˜๋ ค๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ feature ์— ๋”ฐ๋ผ ๋กœ๋“œํ•˜๋Š” ํŒจํ‚ค์ง€ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋‹ฌ๋ผ์ง€๊ฒ ์ฃ )

 

LazyMotion & m ์œผ๋กœ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™”ํ•˜๊ธฐ

์•ž์„œ ๋งํ–ˆ๋“ฏ์ด, motion ์€ ๋ชจ๋“  ์• ๋‹ˆ๋ฉ”์ด์…˜ feature ๋ฅผ preload ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๋“ค๊นŒ์ง€ ํฌํ•จํ•ด์„œ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

๋Œ€์‹ ์— LazyMotion ์„ ํ†ตํ•ด์„œ ํ•„์š”ํ•œ feature ๋ฅผ ๋‹ด์€ animation set ์„ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

<LazyMotion features={domAnimation}>
  {children}
</LazyMotion>

 

์—ฌ๊ธฐ์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ animation set ์€ ํ˜„์žฌ ๋‹ค์Œ ๋‘๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค.

์ด๋ถ€๋ถ„์€ ์ถ”ํ›„์— ๋ฒ„์ „ ์—…๊ทธ๋ ˆ์ด๋“œ์— ๋”ฐ๋ผ ๋ณด๋‹ค ์„ธ๋ถ„ํ™”๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด๋ณด์ด๋„ค์š”.

(Framer-Motion ์˜ ๋ฉ”์ธ feature ๋‹จ์œ„๋กœ ์ชผ๊ฐœ์ง€์ง€ ์•Š์„๊นŒ์š”?)

  • domAnimation : animations, variants, exit animations, tap/hover/focus gestures (+15kb)
  • domMax : ๋ชจ๋“  feature ํฌํ•จ (+25kb)

 

์œ ์˜ํ•  ์ ์€ LazyMotion ์„ motion ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, motion ์˜ preload ๋•Œ๋ฌธ์—

LazyMotion ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์ด์ ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—,

m ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋Š” strict ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

<LazyMotion strict features={domAnimation}>
  <motion.div />
</LazyMotion>

 

LazyMotion ์— strict ์„ค์ •์„ ํ•˜๊ณ  motion ์„ ๋ Œ๋”๋งํ•˜๋ ค๊ณ  ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

 

๋”ฐ๋ผ์„œ LazyMotion ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—๋Š” strict ์„ค์ •์„ ๊ฐ•์ œํ•˜๋Š” ๊ฒƒ์ด

๋ฒˆ๋“ค๋ง ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋” ๋‚˜์€ ๋ฐฉํ–ฅ์ด๋ผ๊ณ  ๋ณด์ด๋„ค์š”.

 

๐Ÿ“Œ ๋งˆ๋ฌด๋ฆฌ

์ด ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ฉฐ ๋Š๋‚€ ์žฅ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

  1. declarative animation code
  2. ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ด€๋ จ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. (๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ)
  3. ๊ฐ„๊ฒฐํ•˜๊ณ  ๋ช…ํ™•ํ•œ Rich API
    1. ๋ณต์žกํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด๋ณด์ž…๋‹ˆ๋‹ค.
    2. ๊ตฌํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šด physics ๊ธฐ๋ฐ˜์˜ ์‚ฌ์‹ค์ ์ธ transition ํšจ๊ณผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  4. ์นœ์ ˆํ•œ ๋ฌธ์„œ์™€ ์ง€์†์ ์ธ ์—…๋ฐ์ดํŠธ
    1. ์ตœ๊ทผ PR ๋“ค์„ ๋ณด๋ฉด animation timeline ๊ด€๋ จ ๊ธฐ๋Šฅ๋“ค์ด ๊ฐœ๋ฐœ์ค‘์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  5. ๋””์ž์ธ ํˆด์ธ Framer ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋””์ž์ด๋„ˆ์™€์˜ ํ˜‘์—…์— ์ข€ ๋” ๋„์›€์ด ๋˜์ง€ ์•Š์„๊นŒ?
    1. ๋””์ž์ธ๊ณผ ํ”„๋กœ๋•์…˜๊ณผ์˜ ๊ฐ„๊ทน์ด ์ข€๋” ์†์‰ฝ๊ฒŒ ์ขํ˜€์งˆ ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋„๊ตฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๋‹ค๋งŒ ์œ ์˜ํ•  ์‚ฌํ•ญ๋„ ๋ช‡๊ฐ€์ง€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  1. ์šฐ์„  ์šฉ๋Ÿ‰์ด ํฐ ํŽธ์ด๋‹ค.
    1. ๋Œ€์‹  ํ•„์š”ํ•œ๊ฒƒ๋งŒ ๊ฐ€์ ธ๋‹ค ์“ฐ๋ฉฐ tree-shaking ๋„ ์ง€์›ํ•˜๊ธฐ์— ์–ด๋Š์ •๋„ ๋ณด์™„ ๊ฐ€๋Šฅํ•  ๋“ฏํ•ฉ๋‹ˆ๋‹ค.
    2. ๊ทธ๋ ‡๊ธฐ์— ๊ฐ€๋ณ๊ณ  ๋‹จ์ˆœํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด ๊ตณ์ด,,?
      1. ๊ทผ๋ฐ ์•ฑ ๋‚ด์— ๋งŽ์€ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์žˆ๋‹ค๋ฉด, ์ด๊ฑธ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ์œ ์ง€๋ณด์ˆ˜์— ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  2. ํ•ด๋‹น ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณ„๋„๋กœ ์ตํ˜€์•ผํ•ฉ๋‹ˆ๋‹ค.
    1. ๊ทผ๋ฐ ์‚ฌ์šฉ๋ฒ•์ด ์–ด๋ ค์šด ๊ฒƒ์€ ์•„๋‹ˆ๋ผ์„œ ํฐ ๋‹จ์ ์œผ๋กœ ๋ณด์ด์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
    2. ์˜คํžˆ๋ ค ํ†ต์ผ๋œ ์ฝ”๋“œ๋กœ ์œ ์ง€๋ณด์ˆ˜์— ๋„์›€์ด ๋˜์ง€ ์•Š์„๊นŒ์š”?
  3. ์ž์ฒด ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ (chart, drag&drop ๋“ฑ) ์™€์˜ ํ˜ธํ™˜์„ฑ์€?
    1. ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๊ฒฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์žˆ๋Š”์ง€ ์ฐพ๊ณ , ๊ทธ๋Ÿด๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”์ง€ ์ƒ๊ฐํ•ด๋ณผ ํ•„์š”๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    2. ๋‹ค๋งŒ ์ด๋ฏธ ์ž์ฒด์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ œ๊ณตํ•œ๋‹ค๋ฉด, ๊ตณ์ด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—๋„ ์ ์šฉํ•  ํ•„์š”๋Š” ์—†์–ด ๋ณด์ด๋„ค์š”.
  4. SSR ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ผ๋ถ€ SVG ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    1. ํ•ด๋‹น svg ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ผ์ด ์—†๋‹ค๋ฉด ๋‹น๋ถ„๊ฐ„ ํฐ ๋ฌธ์ œ๋Š” ์•„๋‹๋“ฏ ํ•ฉ๋‹ˆ๋‹ค.

 

์ง€์†์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜๋ฉฐ ๋ฐœ์ „ํ•˜๊ณ  ์žˆ๋Š” ํŒจํ‚ค์ง€์ธ๋งŒํผ, ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ์œ„ํ•ด ๋ˆˆ์—ฌ๊ฒจ ๋ณผ๋งŒํ•˜์ง€ ์•Š์„๊นŒ์š”?

์šฐ์„  ์ผ๋ถ€ ํ”„๋กœ์ ํŠธ์— ์‹คํ—˜์ ์œผ๋กœ ๋„์ž…ํ•ด๋ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

์—ฌ๋Ÿฌ๋ถ„๋“ค์˜ ์˜๊ฒฌ์ด ๊ถ๊ธˆํ•˜๋„ค์š”!

 

๋ฐ˜์‘ํ˜•

๐Ÿ’ฌ ๋Œ“๊ธ€