웹 애니메이션 성능 티어 리스트 완전 정리 ("The Web Animation Performance Tier List")

okorion·2025년 12월 3일

1. 핵심 요약

  • 애니메이션 성능은 레이아웃(Layout) → 페인트(Paint) → 합성(Composite) 단계 중 어디를 유발하느냐로 결정된다.
  • S-Tier = GPU 합성 단계만 실행 → 가장 부드러운 결과(60/120fps)
    transform·opacity·filter·clip-path 등
  • CSS 변수·레이아웃 변경·DOM 측정·쓰래싱(thrashing)은 성능 최악
  • “빠른 애니메이션”의 기준은 단순 프레임레이트가 아니라 메인 스레드 차단 없이 즉각적인 반응성을 유지하는지 여부

2. 렌더링 파이프라인 이해 (Why)

브라우저가 한 프레임을 그릴 때 거치는 단계:

단계의미발생 시 비용
Layout요소 크기·위치 계산가장 비쌈 (재귀 영향 큼)
Paint픽셀 다시 그림Layout보다는 낮지만 비쌈
Composite이미 그려진 레이어를 GPU에서 합성가장 저렴함
  • 상위 단계가 발생하면 아래 단계도 반드시 발생함
    Layout → Paint → Composite
    Paint → Composite

즉, Composite만 유발하는 기법이 최강이다.


3. 스레드 구조

메인 스레드

  • JS 실행, 스타일 계산, 레이아웃, 페인트 등 대부분의 작업 담당
  • 바쁘면 애니메이션 프레임 손실(jank) 발생

컴포지터 스레드

  • transform/opacity 등 합성 단계만 필요할 때 애니메이션을 단독 실행
  • 메인 스레드가 막혀도 애니메이션이 계속 부드럽게 유지

S-Tier = 컴포지터 스레드에서 돌 수 있는 애니메이션


4. 애니메이션 성능 티어 리스트 (What)

전체 기준:

  • S: 합성 전용
  • A: 메인 스레드 기반이지만 합성만 유발
  • B: 측정 비용 1회 + A/S-tier
  • C: Paint 발생
  • D: Layout 발생
  • F: Thrashing = 최악

5. S-Tier — 합성(Animation on Compositor)

사용 가능한 속성

  • transform
  • opacity
  • filter
  • clip-path

특징

  • 메인 스레드와 분리 → GPU에서 60~120fps 유지
  • CSS / WAAPI / Motion으로 작성 시 가장 안정적

주의점

  1. 브라우저 de-optimization
    Safari처럼 compositor 기능이 제한될 경우 자동으로 메인 스레드로 폴백

  2. 레이어 크기 폭발

    • transform/opacity를 위한 레이어 생성 → 너무 크면 GPU 메모리 초과
    • 특히 무한 마키(ticker) 등은 레이어 폭이 매우 큼
  3. filter: blur는 가속되지만 값이 커질수록 기하급수적 비용 증가

스크롤 기반 S-tier

  • ScrollTimeline / ViewTimeline 활용 → 스크롤 자체가 컴포지터에서 실행
  • scrollTop 읽기 기반 애니메이션은 D-tier (메인 스레드 개입)

6. A-Tier — 레이어 기반 합성(Main Thread-driven Composite)

조건:

  • 대상 요소가 이미 레이어로 승격(promoted to layer) 되어 있을 것

레이어 승격 조건

  • transform/opacity 애니메이션 존재
  • 3D transform
  • position: fixed/sticky
  • backdrop-filter
  • 또는 will-change: transform 등 힌트

주의: will-change는 과다 사용 시 GPU 메모리 초과 위험

예시

  • GSAP / requestAnimationFrame 기반 transform 변경
  • Motion의 독립 transform 애니메이션

속성

  • GPU 합성만 트리거 → 보통 매우 빠름
  • 단, 메인 스레드가 막히면 영향 받음

7. B-Tier — DOM 측정 1회 포함 + A/S 애니메이션

대표 예: FLIP 레이아웃 애니메이션

  • First → Last → Invert → Play 기법
  • transform으로 위치/사이즈를 보정하여 S-tier처럼 동작
  • 하지만 초기 측정(레이아웃 읽기) 1회 필요

Motion의 layout 애니메이션이 이 카테고리.


8. C-Tier — Paint 발생

트리거

  • background-color
  • color
  • border-radius
  • mask-image / gradient
  • CSS 변수 변경

CSS 변수 성능 문제

  1. 변경 시 항상 Paint 발생

  2. 전역 CSS 변수는 스타일 재계산 폭발(F-Tier로 격하)

    • DOM 전체 1000개+ 요소 재계산 가능
    • 실제 사례: 매 프레임 global var 업데이트 → 8ms 소모

해결책

  • 변수 스코프 축소(html → 특정 섹션)
  • @property + inherits: false 사용하여 상속 차단

SVG 속성 변경

  • d, cx, cy, r 등 변경 시 무조건 paint

View Transition API가 C~D에 있는 이유

  • 기본 crossfade는 S-tier
  • 하지만 width/height 기반 확장·축소는 D-tier
  • 인터럽트 불가 → UI 반응성 저하 → C-tier 유지

9. D-Tier — Layout 발생

특징

  • Layout은 가장 비싼 단계
  • 형제·부모·자식 DOM 전체 영향을 받을 수 있음

예:

  • width/height/left/top/bottom
  • flex 값 변경
  • grid-template 변경
  • display 변경

최적화

  • position: absolute/fixed를 사용해 레이아웃 영향 범위 축소
  • contain: layout 적용

10. F-Tier — Thrashing (절대 금지)

정의

  • Write → Read → Write → Read 반복
  • Layout 강제 → 수십 fps 손실

예시:

element.style.width = "100px"
const w = element.offsetWidth  // Layout 강제
element.style.width = w * 2 + "px"

React useLayoutEffect에서 DOM 읽기/쓰기 조합할 때 흔히 발생.

해결책

  • 측정과 업데이트를 프레임 단위로 배치(batch)
  • Motion의 frame.read / frame.update 같은 API 사용

11. 결론 (How)

  • 성능 문제의 90%는 레이아웃 또는 큰 blur/filter

  • 나머지는 CSS 변수 스코프, 레이어 폭, Safari 폴백 등 섬세한 요소들

  • 최적의 애니메이션 전략:

    1. 먼저 S-tier 가능한지 확인 (transform/opacity)
    2. 레이어 크기·픽셀 비용 고려
    3. CSS 변수·SVG·레이아웃 기반 애니메이션 최소화
    4. 불가피할 경우 FLIP(B-tier) 기법 활용
    5. 측정은 반드시 batching

원문 - The Web Animation Performance Tier List

profile
okorion's Tech Study Blog.

0개의 댓글