• **GSAP (GreenSock Animation Platform)**은 JavaScript 기반의 κ³ μ„±λŠ₯ μ• λ‹ˆλ©”μ΄μ…˜ 라이브러리
  • DOM μš”μ†ŒλΏ μ•„λ‹ˆλΌ μ–΄λ–€ 객체의 μ–΄λ–€ 속성이든 μ• λ‹ˆλ©”μ΄μ…˜ν•  수 μžˆλŠ” λ²”μš© ν”„λ‘œνΌν‹° μ„Έν„°
  • Tween(단일 μ• λ‹ˆλ©”μ΄μ…˜)κ³Ό Timeline(μ‹œν€€μ‹± μ»¨ν…Œμ΄λ„ˆ)으둜 κ΅¬μ„±λ˜λŠ” 2-레벨 μ• λ‹ˆλ©”μ΄μ…˜ μ‹œμŠ€ν…œ

ν•΄λ‹Ή κ°œλ…μ΄ ν•„μš”ν•œ 이유

  • Hyperframesμ—μ„œ μ• λ‹ˆλ©”μ΄μ…˜μ€ GSAP νƒ€μž„λΌμΈμœΌλ‘œ μ •μ˜ν•˜κ³ , ν”„λ ˆμž„μ›Œν¬κ°€ seekFrame()을 톡해 μŠ€ν¬λŸ¬λΉ™ν•œλ‹€
  • GSAP νƒ€μž„λΌμΈμ„ { paused: true }둜 λ§Œλ“€κ³  window.__timelines에 λ“±λ‘ν•˜λŠ” νŒ¨ν„΄μ΄ Hyperframes의 핡심 κ·œμ•½
  • CSS μ• λ‹ˆλ©”μ΄μ…˜λ§ŒμœΌλ‘œλŠ” ν”„λ ˆμž„ λ‹¨μœ„ 탐색(seek)이 μ–΄λ ΅μ§€λ§Œ, GSAP은 timeline.totalTime(seconds)둜 μ •ν™•ν•œ ν”„λ ˆμž„ 탐색이 κ°€λŠ₯

AS-IS β€” λ”œλ ˆμ΄ 기반 μˆ˜λ™ 타이밍

// 각 μ• λ‹ˆλ©”μ΄μ…˜μ˜ μ‹œμž‘ μ‹œμ μ„ μˆ˜λ™μœΌλ‘œ 계산해야 함
gsap.to("#a", { x: 100, duration: 1, delay: 0 });
gsap.to("#b", { y: 50, duration: 1, delay: 1 });     // #a λλ‚œ ν›„
gsap.to("#c", { opacity: 0, duration: 0.5, delay: 2 }); // #b λλ‚œ ν›„
// 쀑간에 ν•˜λ‚˜ λ°”λ€Œλ©΄ 이후 λͺ¨λ“  delayλ₯Ό μˆ˜μ •ν•΄μ•Ό 함

TO-BE β€” Timeline μ‹œν€€μ‹±

const tl = gsap.timeline({ paused: true });
tl.to("#a", { x: 100, duration: 1 })      // 0μ΄ˆλΆ€ν„° μžλ™
  .to("#b", { y: 50, duration: 1 })        // #a λλ‚˜λ©΄ μžλ™
  .to("#c", { opacity: 0, duration: 0.5 }); // #b λλ‚˜λ©΄ μžλ™
// ν•˜λ‚˜λ₯Ό μˆ˜μ •ν•΄λ„ 이후 타이밍이 μžλ™μœΌλ‘œ 쑰정됨

Tween β€” μ• λ‹ˆλ©”μ΄μ…˜μ˜ μ΅œμ†Œ λ‹¨μœ„

Tween은 β€œλŒ€μƒ 객체의 속성 값을 일정 μ‹œκ°„μ— 걸쳐 λ³€ν™”μ‹œν‚€λŠ” λ‹¨μœ„β€λ‹€.

3κ°€μ§€ 생성 방식

λ©”μ„œλ“œμ˜λ―Έμ˜ˆμ‹œ
gsap.to()ν˜„μž¬ κ°’ β†’ λͺ©ν‘œ κ°’gsap.to("#box", { x: 100, duration: 1 })
gsap.from()μ§€μ • κ°’ β†’ ν˜„μž¬ κ°’gsap.from("#box", { opacity: 0, duration: 1 })
gsap.fromTo()μ‹œμž‘ κ°’ β†’ 끝 κ°’ λͺ¨λ‘ μ§€μ •gsap.fromTo("#box", { x: 0 }, { x: 100 })

μ£Όμš” 속성

속성섀λͺ…κΈ°λ³Έκ°’
durationμ• λ‹ˆλ©”μ΄μ…˜ 길이(초)0.5
delayμ‹œμž‘ μ „ λŒ€κΈ° μ‹œκ°„(초)0
ease가감속 곑선"power1.out"
repeat반볡 횟수 (-1 = λ¬΄ν•œ)0
yoyo반볡 μ‹œ μ—­λ°©ν–₯ μž¬μƒfalse

Timeline β€” μ‹œν€€μ‹± μ»¨ν…Œμ΄λ„ˆ

Timeline은 μ—¬λŸ¬ Tween을 ν•˜λ‚˜λ‘œ λ¬Άμ–΄ μ œμ–΄ν•˜λŠ” μ»¨ν…Œμ΄λ„ˆλ‹€.

Position Parameter β€” 배치의 핡심

μ„Έ 번째 인자둜 νƒ€μž„λΌμΈ λ‚΄ μ •ν™•ν•œ 배치λ₯Ό μ§€μ •ν•œλ‹€:

const tl = gsap.timeline();
 
// μ ˆλŒ€ μ‹œκ°„
tl.to("#a", { x: 100 }, 3);         // 3초 지점에 배치
 
// μƒλŒ€ μ‹œκ°„
tl.to("#b", { y: 50 }, "+=1");      // 이전 끝 + 1초
tl.to("#c", { opacity: 0 }, "-=0.5"); // 이전 끝 - 0.5초 (μ˜€λ²„λž©)
 
// 이전 μ• λ‹ˆλ©”μ΄μ…˜ κΈ°μ€€
tl.to("#d", { scale: 2 }, "<");      // 이전 μ‹œμž‘κ³Ό λ™μ‹œμ—
tl.to("#e", { rotation: 90 }, ">");  // 이전 끝과 λ™μ‹œμ—

ν”„λ‘œκ·Έλž˜λ§€ν‹± μ œμ–΄

tl.play();            // μž¬μƒ
tl.pause();           // μΌμ‹œμ •μ§€
tl.seek(1.5);         // 1.5초 μ§€μ μœΌλ‘œ 점프
tl.totalTime(3);      // 3초 μ§€μ μœΌλ‘œ 이동 (repeat 포함)
tl.progress(0.5);     // 50% μ§€μ μœΌλ‘œ 이동
tl.reverse();         // μ—­λ°©ν–₯ μž¬μƒ
tl.duration();        // 전체 길이 λ°˜ν™˜

Hyperframesμ—μ„œμ˜ GSAP μ‚¬μš© νŒ¨ν„΄

// 1. λ°˜λ“œμ‹œ paused: true
const tl = gsap.timeline({ paused: true });
 
// 2. μ ˆλŒ€ μœ„μΉ˜ νŒŒλΌλ―Έν„°λ‘œ μ •ν™•ν•œ 타이밍 μ§€μ •
tl.from("#title", { opacity: 0, y: -50, duration: 1 }, 0);
tl.to("#subtitle", { opacity: 1, duration: 0.5 }, 1.5);
 
// 3. composition-id와 λ§€μΉ­ν•˜μ—¬ 등둝
window.__timelines = window.__timelines || {};
window.__timelines["my-video"] = tl;
 
// β†’ ν”„λ ˆμž„μ›Œν¬κ°€ tl.totalTime(frame/fps)둜 각 ν”„λ ˆμž„μ„ μŠ€ν¬λŸ¬λΉ™

μ°Έκ³  λ¬Έμ„œ