Communitygithub.com

웹 애니메이션 스킬

템플릿이 아닌, 세심하게 디자인된 인터랙티브 웹 애니메이션을 설계하고 구축합니다. 웹사이트나 웹 앱에 모션(페이지 로드, 스크롤 효과, 텍스트 리빌, 마이크로인터랙션, 페이지 전환 등)이 필요할 때 사용하세요.

웹 애니메이션 스킬란 무엇인가요?

이 스킬은 웹 애니메이션을 설계하고 구현하는 전문가 에이전트입니다. CSS 전환, @keyframes, Scroll-Driven 애니메이션, View Transitions API, GSAP (ScrollTrigger, SplitText, Flip), Motion (React 및 vanilla JS), Anime.js v4, Lottie, Rive, D3, Flubber, Konva, Three.js/React Three Fiber 등 다양한 라이브러리와 기법을 지원합니다. 작업 흐름은 프로젝트 분석, 모션 목적 결정 (피드백/방향 전환/주목/내러티브), 가장 가벼운 도구 선택, 필수 규칙 (transform/opacity 우선, prefers-reduced-motion 존중, JS 실행 전 콘텐츠 숨김 금지, 정리, 인터랙션 응답성 유지, 포커스 방해 금지) 적용, 실제 브라우저에서 검증 순서로 진행됩니다. 주로 Cursor, Claude Code, Codex와 같은 AI 코딩 에이전트에서 사용됩니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/yuzhang-ai/web-animation-skill/tree/HEAD

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

웹 애니메이션

좋은 웹 모션은 라이브러리 호출보다 먼저 디자인 결정입니다. 아래 워크플로를 순서대로 따르고, 필요한 단계에서만 규칙 파일을 로드하세요.

워크플로

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 전환 / @keyframescss-keyframes.md
대화상자, 팝오버, 드롭다운 진입 및 종료CSS @starting-style + transition-behavior: allow-discretecss-keyframes.md
페이지 / 경로 전환, 상태 간 공유 요소 변형View Transitions APIview-transitions.md
간단한 스크롤 연결 리빌, 진행률 표시줄, 패럴랙스CSS animation-timeline: view() / scroll()scroll-animations.md
고정 섹션, 스크러빙 다단계 타임라인, 가로 스크롤GSAP + ScrollTriggergsap.md
분할 텍스트 / 라인 마스크 헤드라인 리빌GSAP SplitTextgsap.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
인터랙티브, 상태 기반 일러스트레이션 애니메이션Riverive.md
애니메이션 차트D3 전환d3.md
많은 인터랙티브 2D 도형 (편집기, 다이어그램)Konvakonva.md
3D, 입자, 셰이더Three.js / React Three Fiberthree-js.md

선택이 명확하지 않다면 rules/choosing-library.md를 읽으세요.

4. 필수 규칙과 함께 구축하기

다음은 모든 라이브러리의 모든 애니메이션에 적용됩니다:

  1. transform과 opacity를 애니메이션 처리하세요. width, height, top, left, margin은 애니메이션 처리하지 마세요; 레이아웃 변경에는 scale/translate, FLIP (GSAP Flip, Motion layout) 또는 View Transitions를 사용하세요. rules/performance.md를 참조하세요.
  2. prefers-reduced-motion을 존중하세요. 움직임을 불투명도 페이드 또는 즉시 변경으로 대체하세요; 콘텐츠를 보이지 않게 만들면서 진입 자체를 삭제하지 마세요. 스크롤 스크러빙 효과는 정적이 되어야 합니다.
  3. JS가 실행될 때까지 콘텐츠를 숨기지 마세요. 초기 숨겨진 상태를 JS에서 설정하세요(또는 .js 클래스 뒤에서), 그래야 스크립트가 실패해도 콘텐츠가 보입니다. SSR을 사용하는 경우, 첫 페인트 전에 초기 스타일을 적용하여 보였다가 숨겨지는 번쩍임을 방지하세요.
  4. 정리하세요. 언마운트 시 애니메이션을 되돌리거나 중지하고(useGSAP, createScope().revert(), gsap.context), 경로 변경 시 ScrollTrigger를 중지하세요.
  5. 인터랙션 응답성을 유지하세요. 사용자가 트리거한 모든 항목에 대해 중단 가능한 애니메이션: 두 번째 클릭이 첫 번째 클릭 뒤에서 대기하지 않아야 합니다. 애니메이션이 끝날 때까지 입력을 차단하지 마세요.
  6. 포커스를 방해하지 마세요. 움직이는 요소는 보이는 :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; } }

규칙 파일

이러한 기술의 실제 예제는 demos/에 있습니다.

관련 스킬