06 — Motion (시간 축에서의 변화)
한 줄 답: 모션은 **CSS 속성값의 시간 보간(interpolation)**이다. 우리가 신경 써야 할 것은 “무엇을 보간하느냐” (transform·opacity) × “어떻게 보간하느냐” (timing function·composite) × “누가 트리거하느냐” (state·scroll·navigation) × “누가 멀미하느냐” (
prefers-reduced-motion)의 4축이다.
이 챕터가 답하는 질문
transition과animation은 정확히 무엇이 다른가?top: 100px로 슬라이드하면 왜 끊기고,transform: translateY(100px)은 왜 부드러운가?will-change: transform을 모든 요소에 주면 빨라지는가?display: none인 요소가block이 되면서 페이드인 시키려면?- Next.js 페이지 전환에서 카드 하나가 그대로 다음 화면으로 “이동”하게 하려면?
- JS 없이 스크롤 진행도 따라가는 애니메이션은 어떻게?
- 멀미를 호소하는 사용자에게 모션을 어떻게 꺼주는가?
- FLIP 기법(Pinterest·Twitter)은 정확히 무엇을 줄이는 기법인가?
이 8개에 답할 수 있다면, *“왜 우리 앱이 튀는가”*는 *“렌더 파이프라인의 어느 단계가 60fps를 깨는가”*로 환원된다.
챕터 구조
| 문서 | 다루는 것 | 핵심 키워드 |
|---|---|---|
01-transition | 상태 전환 보간 | transition, timing-function, transition-behavior: allow-discrete |
02-animation | 키프레임 기반 자율 애니메이션 | @keyframes, animation-composition, fill-mode, replace/add/accumulate |
03-transform | 2D/3D 변환 | translate·rotate·scale·skew, transform-origin, perspective, 3D context |
04-rendering-perf | Layout·Paint·Composite 파이프라인 | GPU promotion, jank, will-change, FLIP, Compositor-only props |
05-view-transitions | View Transitions API | Same-Doc(SPA), Cross-Doc(MPA, 2024), view-transition-name, morphing |
06-scroll-driven | 스크롤 진행도 ↔ 애니메이션 | animation-timeline, scroll-timeline, view-timeline, view() |
07-accessibility | 모션과 vestibular disorder | prefers-reduced-motion, 멀미, motion design ethics |
5-레이어 모델 안에서의 위치
모션은 Visual의 결과를 시간으로 늘인 것이다. 그래서 05-color-visual(opacity, filter, gradient) 다음에, 07-responsive(viewport 단위) 앞에 놓인다.
Why — 왜 별도의 챕터인가
UI의 체감 품질은 정적인 픽셀이 아니라 그 픽셀이 어떻게 움직이는가에서 갈린다.
- 16ms 지연 = 60fps, 33ms = 30fps, 100ms 이상 = “끊긴다”의 인지 임계.
- 정확히 같은 디자인이라도 transform 기반 슬라이드 vs
left기반 슬라이드의 CPU 사용량은 10배 이상 차이난다. prefers-reduced-motion을 무시한 캐러셀은 vestibular disorder 사용자에게 두통·구토를 유발한다 (WCAG 2.3.3 Animation from Interactions).- 2024년 이후 View Transitions·Scroll-driven Animations가 Baseline에 진입하면서 JS 라이브러리(Framer Motion, GSAP) 일부 영역이 CSS로 흡수됐다.
이 챕터는 *“애니메이션을 추가하면 더 멋져진다”*는 가정을 *“애니메이션은 렌더 파이프라인 비용과 인지 부하의 거래”*라는 공학적 결정으로 바꾼다.
How — 어떻게 읽나
순서대로 5시간. 의존성이 있는 누적형 챕터다.
| # | 파일 | 읽는 데 | 전제 |
|---|---|---|---|
| 01 | 01-transition | 25분 | 02-layout(box model), 01-cascade |
| 02 | 02-animation | 30분 | 01-transition |
| 03 | 03-transform | 30분 | 0-foundations(좌표계), 02-layout |
| 04 | 04-rendering-perf | 35분 | 01·02·03 모두 |
| 05 | 05-view-transitions | 25분 | 04 (composite) |
| 06 | 06-scroll-driven | 25분 | 02 (keyframes), 04 (perf) |
| 07 | 07-accessibility | 15분 | 01~06 전부 (모든 모션에 적용되는 메타 규칙) |
- 빠르게 훑고 싶다면:
01→04→07만 봐도 사고 절반은 막힌다. - SPA 전환 만들기:
03+04+05. - 랜딩 페이지:
02+06+07.
What — 한 페이지 요약
| 문서 | 한 줄 결론 |
|---|---|
| 01 | transition은 상태 변화의 보간이다. transition-behavior: allow-discrete가 display:none 트랜지션을 가능케 한다. |
| 02 | animation은 자율적 키프레임 시퀀스다. animation-composition: add는 변환을 덧붙이는 새 모델. |
| 03 | transform은 레이아웃에 영향 없는 좌표 변환이다. Composite-only라 60fps에 가장 친화적. |
| 04 | 렌더는 Layout → Paint → Composite 파이프라인. transform·opacity는 마지막 단계만 트리거 — 그래서 부드럽다. will-change는 가설 선언이다, 남발하면 메모리 폭발. |
| 05 | View Transitions는 DOM 두 상태를 캡처해 그 사이를 보간. 2024년 Cross-Document(MPA) 전환 Chrome 안착. |
| 06 | Scroll-driven은 animation-timeline: scroll() / view()로 스크롤을 시간 축으로 변환. JS 없는 패럴랙스·진행 바·sticky 페이드. |
| 07 | @media (prefers-reduced-motion: reduce)는 의무. 멀미는 디자인 문제가 아니라 접근성 결함이다. |
What-if — 잘못 만지면
top/left로 슬라이드 → 매 프레임 Layout 재계산 → 모바일에서 30fps도 못 지킨다 (transform으로 바꿔라)backdrop-filter에 animation → iOS Safari에서 GPU 메모리 폭증, jankwill-change: transform을 100개 카드에 → 레이어 100개 → 모바일 GPU 메모리 한계 초과로 오히려 더 느려짐prefers-reduced-motion미고려 → vestibular 사용자에게 두통, WCAG 2.3.3 위반- View Transitions의
view-transition-name을 여러 요소에 같은 이름 → 에러로 트랜지션 자체가 취소 - Scroll-driven에
width애니메이션 → 스크롤할 때마다 Layout → 스크롤 자체가 끊긴다
Insight — 한 단락 이야기
“모션의 역사는 CSS가 GPU와 화해하는 역사다.”
2009년 Webkit이
-webkit-transform을 도입할 때, 핵심은 transform이 layout을 트리거하지 않는다는 점이었다. 같은 해 iPhone OS 3는 이 속성을 H/W 가속해서 60fps를 보장했고, **“GPU 가속 = transform·opacity만”**이라는 사실상 표준이 굳어졌다. 2014년 Paul Lewis가 정리한 FLIP 기법(First/Last/Invert/Play)은 이 제약을 우회하는 공학적 발견이었다 — 레이아웃이 바뀐 결과를 transform으로 역계산해 흉내 내자는 발상. 2023년 View Transitions API는 그 FLIP을 브라우저가 자동으로 해주는 흐름이다. Scroll-driven은 한 발 더 나아가, 시간조차 스크롤로 대체하자고 한다. 이 챕터는 그 30년 진화의 현재 시점 단면이다.
한 단락 요약
Motion은 Visual의 시간 미분이다. 보간(
01·02) × 좌표(03) × 파이프라인(04) × 트리거(05·06) × 윤리(07)의 5축이 모이면, 우리는 *“왜 부드럽지 않을까”*를 *“렌더 파이프라인의 어느 단계가 막혔나”*로 디버깅할 수 있게 된다. 다음 챕터(07-responsive)는 이 모션이 다양한 화면 크기·컨텍스트에서 어떻게 적응하는지를 다룬다.