Web Platform (Chromium 130+, Safari 18+, Firefox 130+)
애니메이션 (transition / keyframes) 성능 최적화
매 한 줄
"매 transform 과 opacity 만이 GPU 합성 layer 위에서 60/120fps 으로 부드럽게 흐른다". 매 layout 또는 paint 를 trigger 하는 property (width, height, top, left, margin) 의 animate 는 매 main thread CPU 의 reflow 를 매 frame 마다 강제 → jank. 매 2026 modern web (CH 130+, Safari 18+) 의 compositor-only animation 의 사용 — will-change, contain, view-transition-name 매 핵심.
매 핵심
매 Rendering Pipeline 의 4 단계
Style — CSS rule 매 element 매 매칭.
Layout (reflow) — 매 geometry 의 계산 (position, size). 매 비싼 단계.
Paint — pixel buffer 매 fill (color, image, shadow).
Composite — GPU 매 layer 의 합성 (transform, opacity).
매 transform/opacity 매 변경 시 매 Composite 만 trigger → 매 main thread block 의 X.
매 GPU 합성 trigger
transform (translate, rotate, scale, skew) — 매 layout 의 영향 X.
opacity — 매 paint 의 영향 X.
filter — 매 composited layer 위 의 GPU shader.
clip-path (transform 기반) — 매 GPU friendly.
매 비싼 properties (피해야 함)
width, height, top, left, margin, padding — 매 reflow 매 trigger.
box-shadow, border-radius (애니메이트 시) — 매 paint 매 매 frame.
/* ❌ Bad: layer 의 영구 promotion → memory bloat */.everywhere{will-change:transform;}/* ✅ Good: 매 interaction 직전 의 hint, 매 종료 후 매 제거 */.button{transition:transform200ms;}.button:hover{will-change:transform;}.button:not(:hover){will-change:auto;}/* JS 의 dynamic toggle */btn.addEventListener('mouseenter',()=>btn.style.willChange='transform');btn.addEventListener('animationend',()=>btn.style.willChange='auto');
Pattern 4: contain 의 layout 격리
.list-item{contain:layoutpaintstyle;/* 매 child 의 reflow 매 ancestor 의 propagate 의 X */}.modal{contain:strict;/* layout + paint + size + style */}
Pattern 5: View Transitions API (2026 stable)
/* 매 navigation 의 자동 cross-fade — Chrome 130+, Safari 18+ */@view-transition{navigation:auto;}::view-transition-old(card),::view-transition-new(card){animation-duration:400ms;}.card[data-id="42"]{view-transition-name:card-42;}
// SPA 의 trigger
document.startViewTransition(()=>{renderNewState();});
Pattern 7: Web Animations API (declarative + JS control)
constanim=element.animate([{transform:'translateX(0)',opacity:0},{transform:'translateX(100px)',opacity:1}],{duration:500,easing:'cubic-bezier(0.4, 0, 0.2, 1)',fill:'forwards'});anim.onfinish=()=>element.style.willChange='auto';anim.pause();// scrubbing 의 가능
/* 매 Safari 의 layer promotion 의 강제 — 2026 매 거의 불필요 (will-change 의 사용) */.legacy-promoted{transform:translateZ(0);/* 또는 backface-visibility: hidden; */}
언제: animation jank 의 진단, will-change 의 적절한 scope 의 권고, layout-trigger property 의 transform 의 변환.
언제 X: 매 specific timing curve 의 design 결정 — 매 designer 의 영역.
❌ 안티패턴
Animate top/left/width/height: 매 reflow 매 frame, jank 의 보장.
will-change 의 globalsync: 매 모든 element 의 promotion → GPU memory exhaustion.
@keyframes 의 box-shadow animate: 매 paint 의 매 frame, 매 mobile 의 dropped frames.
JavaScript setInterval 의 animation: 매 rAF 의 사용 — 매 vsync 의 sync 의 X.
prefers-reduced-motion 의 무시: 매 vestibular disorder user 의 motion sickness.