View Transitions API — 페이지 전환 애니메이션의 새 표준
브라우저 표준 트랜지션 API. startViewTransition 호출만으로 cross-fade, view-transition-name으로 morphing, MPA 자동 전환까지 라이브러리 없이.
페이지나 라우트를 전환할 때 부드러운 애니메이션을 주려면 보통 Framer Motion 같은 라이브러리가 필요했습니다. View Transitions API는 브라우저가 표준으로 제공하는 트랜지션 도구로, "이전 화면 스냅샷"과 "새 화면" 사이를 자동으로 연결해줍니다.
1. 기본 사용
1document.startViewTransition(() => { 2 // DOM을 변경하는 콜백 3 updateContent(); 4});
브라우저가 호출 직전 화면을 스냅샷으로 저장하고, 콜백이 끝나면 새 화면을 그린 뒤 두 상태를 자동으로 cross-fade합니다.
2. 같은 요소 사이의 morphing
서로 다른 두 페이지에 있는 같은 요소(예: 카드 → 상세 헤더)를 매끄럽게 연결하려면 view-transition-name을 부여합니다.
1<!-- 목록 페이지 --> 2<article style="view-transition-name: post-26"> 3 <h2>제목</h2> 4</article> 5 6<!-- 상세 페이지 --> 7<header style="view-transition-name: post-26"> 8 <h1>제목</h1> 9</header>
이름이 같은 요소가 두 화면에 모두 있으면, 브라우저가 두 위치 사이를 매끄럽게 보간합니다. 카드가 헤더로 펼쳐지는 듯한 효과가 자동으로 만들어집니다.
3. CSS로 트랜지션 커스터마이징
기본 cross-fade를 다른 효과로 바꾸려면 의사 요소를 사용합니다.
1::view-transition-old(root) { 2 animation: 200ms ease-out fade-out; 3} 4::view-transition-new(root) { 5 animation: 200ms ease-out fade-in; 6} 7 8@keyframes fade-out { to { opacity: 0; } } 9@keyframes fade-in { from { opacity: 0; } }
root를 특정 이름으로 바꾸면 그 요소만 다른 애니메이션을 적용할 수 있습니다.
1::view-transition-old(post-26), 2::view-transition-new(post-26) { 3 animation: 300ms ease-out slide; 4}
4. SPA에서 사용 — Next.js App Router
1'use client'; 2import { useRouter } from 'next/navigation'; 3 4function Card({ id, title }) { 5 const router = useRouter(); 6 const onClick = () => { 7 if (document.startViewTransition) { 8 document.startViewTransition(() => router.push(`/blog/${id}`)); 9 } else { 10 router.push(`/blog/${id}`); 11 } 12 }; 13 return ( 14 <article style={{ viewTransitionName: `post-${id}` }} onClick={onClick}> 15 <h2>{title}</h2> 16 </article> 17 ); 18}
라우트 전환을 startViewTransition으로 감싸면, Next.js가 새 페이지를 그릴 때 자동으로 트랜지션이 적용됩니다.
5. MPA (Multi-Page) 지원
서버 렌더링 페이지 전환에도 적용됩니다.
1@view-transition { 2 navigation: auto; 3}
같은 origin의 페이지 이동에 자동으로 트랜지션을 적용합니다. SPA 구조 없이도 페이지 전환 애니메이션이 가능해집니다.
6. 주의할 점
- Promise를 반환합니다.
startViewTransition().finished로 트랜지션 완료를 기다릴 수 있습니다. view-transition-name은 페이지에서 unique해야 합니다. 같은 이름이 두 개면 무시됩니다.- prefers-reduced-motion 사용자에게는 비활성화하는 게 권장됩니다. CSS에서 처리.
1@media (prefers-reduced-motion: reduce) { 2 ::view-transition-old(root), 3 ::view-transition-new(root) { animation: none; } 4} - 브라우저 지원: Chrome 111+, Safari 18+, Firefox 미지원(2026년 5월 기준). 미지원 브라우저는 그냥 즉시 전환되므로 fallback이 자연스럽습니다.
7. 정리
| 시나리오 | 적용 |
|---|---|
| 카드 → 상세 morphing | view-transition-name 동일하게 |
| 단순 fade | startViewTransition() 호출만 |
| MPA 페이지 전환 | @view-transition { navigation: auto } |
| Reduced motion | media query로 비활성화 |
라이브러리 없이도 부드러운 전환이 가능하고, 서버 렌더링 페이지에도 적용됩니다. 도입 비용이 거의 없으면서 사용자 경험이 즉시 좋아집니다.
참고: MDN — View Transitions API / Chrome Developers — Smooth transitions.