웹 애니메이션
좋은 웹 모션은 라이브러리 호출보다 먼저 디자인 결정입니다. 아래 워크플로를 순서대로 따르고, 필요한 단계에서만 규칙 파일을 로드하세요.
워크플로
1. 선택 전에 프로젝트 먼저 읽기
package.json을 확인하세요. 이미 애니메이션 라이브러리가 설치되어 있다면 그것을 사용하세요. 단일 효과를 위해 두 번째 라이브러리를 추가하지 마세요.- 프레임워크(React / Next.js App Router / Vue / Svelte / 순수 HTML)와 (Next.js에서 클라이언트 측 모션에 필요한
"use client") 서버에서 컴포넌트가 렌더링되는지 여부를 확인하세요. - CSS 변수나 테마 파일에 기존 모션 토큰(지속 시간, 이징)이 있는지 확인하고 재사용하세요.
2. 모션의 목적 결정하기
모든 애니메이션에는 역할이 필요합니다. 요소당 하나를 선택하세요:
| 역할 | 예시 | 일반적인 시간 예산 |
|---|---|---|
| 피드백 — 작업 확인 | 버튼 누름, 토글, 클립보드 복사 | 100–200ms |
| 방향 전환 — 요소의 출처나 목적지 표시 | 모달이 트리거에서 열림, 목록 항목 재정렬, 경로 변경 | 200–400ms |
| 주목 — 한 가지에 집중 | 단일 히어로 시퀀스, 새 알림 | 400–1200ms, 한 번 |
| 내러티브 — 스크롤과 연결된 스토리 전달 | 고정된 제품 둘러보기, 스크러빙 타임라인 | 스크롤 거리에 연결 |
요소에 역할이 없다면 애니메이션을 적용하지 마세요. 모든 섹션에 페이드 업 효과를 주는 것보다 하나의 조율된 순간이 더 낫습니다. 지속 시간, 이징, 안무 및 "프리미엄 느낌" 체크리스트는 rules/motion-design.md를 읽으세요.
3. 작업에 가장 가벼운 도구 선택하기
플랫폼 우선, 그 다음 라이브러리:
| 필요 사항 | 선택지 | 규칙 파일 |
|---|---|---|
| 호버, 포커스, 누름, 간단한 루프 | CSS 전환 / @keyframes | css-keyframes.md |
| 대화상자, 팝오버, 드롭다운 진입 및 종료 | CSS @starting-style + transition-behavior: allow-discrete | css-keyframes.md |
| 페이지 / 경로 전환, 상태 간 공유 요소 변형 | View Transitions API | view-transitions.md |
| 간단한 스크롤 연결 리빌, 진행률 표시줄, 패럴랙스 | CSS animation-timeline: view() / scroll() | scroll-animations.md |
| 고정 섹션, 스크러빙 다단계 타임라인, 가로 스크롤 | GSAP + ScrollTrigger | gsap.md |
| 분할 텍스트 / 라인 마스크 헤드라인 리빌 | GSAP SplitText | gsap.md |
| React 진입/종료, 레이아웃 및 공유 레이아웃 애니메이션, 제스처 | Motion for React (motion/react) | framer-motion.md |
| 프레임워크 없는 명령형 애니메이션, 스프링 | Motion (motion) | motion-one.md |
| GSAP 없는 SVG 선 그리기 및 변형 | Anime.js v4 (svg.createDrawable, svg.morphTo) | animejs.md |
| 관련 없는 모양 간 복잡한 경로 변형 | Flubber (또는 GSAP MorphSVG) | flubber.md |
| After Effects 애니메이션 재생 | Lottie (dotLottie) | lottie.md |
| 인터랙티브, 상태 기반 일러스트레이션 애니메이션 | Rive | rive.md |
| 애니메이션 차트 | D3 전환 | d3.md |
| 많은 인터랙티브 2D 도형 (편집기, 다이어그램) | Konva | konva.md |
| 3D, 입자, 셰이더 | Three.js / React Three Fiber | three-js.md |
선택이 명확하지 않다면 rules/choosing-library.md를 읽으세요.
4. 필수 규칙과 함께 구축하기
다음은 모든 라이브러리의 모든 애니메이션에 적용됩니다:
transform과opacity를 애니메이션 처리하세요.width,height,top,left,margin은 애니메이션 처리하지 마세요; 레이아웃 변경에는scale/translate, FLIP (GSAP Flip, Motionlayout) 또는 View Transitions를 사용하세요. rules/performance.md를 참조하세요.prefers-reduced-motion을 존중하세요. 움직임을 불투명도 페이드 또는 즉시 변경으로 대체하세요; 콘텐츠를 보이지 않게 만들면서 진입 자체를 삭제하지 마세요. 스크롤 스크러빙 효과는 정적이 되어야 합니다.- JS가 실행될 때까지 콘텐츠를 숨기지 마세요. 초기 숨겨진 상태를 JS에서 설정하세요(또는
.js클래스 뒤에서), 그래야 스크립트가 실패해도 콘텐츠가 보입니다. SSR을 사용하는 경우, 첫 페인트 전에 초기 스타일을 적용하여 보였다가 숨겨지는 번쩍임을 방지하세요. - 정리하세요. 언마운트 시 애니메이션을 되돌리거나 중지하고(
useGSAP,createScope().revert(),gsap.context), 경로 변경 시 ScrollTrigger를 중지하세요. - 인터랙션 응답성을 유지하세요. 사용자가 트리거한 모든 항목에 대해 중단 가능한 애니메이션: 두 번째 클릭이 첫 번째 클릭 뒤에서 대기하지 않아야 합니다. 애니메이션이 끝날 때까지 입력을 차단하지 마세요.
- 포커스를 방해하지 마세요. 움직이는 요소는 보이는
:focus-visible상태를 유지해야 하며, 애니메이션 대화상자는 여전히 포커스를 올바르게 이동해야 합니다.
5. 실제 브라우저에서 확인하기
코드를 읽는 것만으로 애니메이션이 완료되었다고 보고하지 마세요. 실행하고 확인하세요:
- 재생되며 최종 상태가 디자인과 일치합니다 (중간 및 정지 상태 스크린샷).
- 콘솔 오류가 없고, 시작 시 레이아웃 이동이 없습니다.
-
prefers-reduced-motion: reduce를 에뮬레이션하고 축소된 버전이 작동하며 콘텐츠가 보이는지 확인합니다. - 모바일 너비로 크기 조정: 고정 섹션과 분할 텍스트가 여전히 작동합니다 (크기 조정 시 다시 분할).
- 스크롤 기반 효과가 아래로 스크롤할 때 뿐만 아니라 위로 스크롤할 때도 작동하며, 페이지 중간에서 다시 로드한 후에도 작동합니다.
- 성능 패널: 애니메이션 중 긴 프레임이 없고, 애니메이션 속성으로 인한 레이아웃/페인트 스파이크가 없습니다.
최소 시작점
// GSAP + ScrollTrigger (npm i gsap)
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.from(".card", {
y: 40, opacity: 0, duration: 0.8, ease: "expo.out", stagger: 0.08,
scrollTrigger: { trigger: ".cards", start: "top 80%" },
});
// Motion for React (npm i motion)
import { motion, AnimatePresence } from "motion/react";
<AnimatePresence>
{open && (
<motion.div
key="panel"
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 8 }}
transition={{ type: "spring", duration: 0.35, bounce: 0 }}
/>
)}
</AnimatePresence>
/* 플랫폼 전용 스크롤 리빌: Chrome 115+, Safari 26+, Firefox 159+ */
@media (prefers-reduced-motion: no-preference) {
@supports (animation-timeline: view()) {
.reveal {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
}
}
@keyframes reveal { from { opacity: 0; translate: 0 2rem; } }
규칙 파일
- rules/motion-design.md — 지속 시간, 이징, 안무, 모션을 프리미엄 느낌으로 만드는 요소
- rules/choosing-library.md — 결정 흐름, 기능 매트릭스, 측정된 번들 크기
- rules/performance.md — 컴포지터 전용 속성, 프로파일링,
will-change, 축소 모션 - rules/scroll-animations.md — CSS 스크롤 타임라인, ScrollTrigger 패턴, 부드러운 스크롤
- rules/view-transitions.md — 동일 문서 및 교차 문서 페이지 전환
- rules/css-keyframes.md — 전환,
@keyframes,@starting-style,linear()이징 - rules/gsap.md — 타임라인, ScrollTrigger, SplitText, Flip,
useGSAP - rules/framer-motion.md — Motion for React: variants,
AnimatePresence, layout, gestures - rules/motion-one.md — Motion vanilla JS:
animate, sequences,scroll,inView - rules/animejs.md — Anime.js v4: 타임라인, stagger, SVG 드로잉 및 모핑
- rules/lottie.md — dotLottie 플레이어, 컨트롤, 이벤트
- rules/rive.md — 상태 머신 및 입력
- rules/d3.md — 데이터 결합 전환
- rules/flubber.md — 경로 모핑
- rules/konva.md — 캔버스 2D 도형 및 트윈
- rules/three-js.md — 씬, R3F, 성능
이러한 기술의 실제 예제는 demos/에 있습니다.