단일 페이지 애플리케이션의 전환 보기

웹페이지의 일반적인 패턴은 새 전체 HTML 문서를 로드하지 않고 JavaScript를 사용하여 페이지의 콘텐츠를 동적으로 대체하는 것입니다. 이를 단일 페이지 애플리케이션(SPA)이라고 합니다. 뷰 전환을 사용하면 SPA의 페이지 간에 연속성이나 컨텍스트를 표시할 수 있습니다.

전체 페이지 전환

사용자가 SPA에서 새 뷰로 이동하면 프레임워크에서 DOM을 새 콘텐츠로 바꿉니다. 이렇게 하면 콘텐츠가 바로 표시되지만 현재 콘텐츠와 새 콘텐츠 간에 전환을 제공하려면 어떻게 해야 할까요?

전환은 이전 뷰와 새 뷰를 동시에 표시하는 경우가 많습니다(예: 이전 뷰를 페이드 아웃하는 동안 새 뷰를 페이드 인). 기존 콘텐츠가 대체되므로 뷰 전환 전에는 이 문제가 있었습니다.

뷰 전환을 사용하려면 DOM 변경 로직을 콜백으로 래핑해야 합니다. 이 예에서는 MyRouter라는 웹 구성요소에서 제공하는 기본 라우터 구현이 있습니다. 뷰 전환을 사용 설정하는 방법은 사용 중인 라우터와 프레임워크에 따라 다릅니다.

document.startViewTransition(() => updateTheDOMSomehow());

이렇게 하면 이전 뷰가 페이드 아웃되는 동안 새 뷰가 페이드 인되는 기본 전환이 사용 설정됩니다.

어떤 상황인가요? document.startViewTransition()를 호출하면 브라우저에서 이전 뷰의 스냅샷을 찍습니다. 그런 다음 전달한 콜백 함수를 호출하여 DOM을 새 뷰로 업데이트합니다 (아직 표시하지는 않음). 콜백 함수가 완료되면 브라우저에서 새 콘텐츠로의 전환을 시작합니다.

// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
  updateTheDOMSomehow();
  return;
} else {
  // With a View Transition:
  document.startViewTransition(() => updateTheDOMSomehow());
}

전환 맞춤설정

이전 예에서 본 것처럼 기본 뷰 전환은 새 뷰를 페이드 인하는 동시에 이전 뷰를 페이드 아웃합니다. 뷰 전환으로 생성된 가상 요소를 스타일링하여 사이트의 스타일에 더 잘 맞게 전환을 맞춤설정할 수 있습니다.

::view-transition-old()로 나가는 전환을 지정하고 ::view-transition-new()로 들어오는 전환을 지정할 수 있습니다. ::view-transition-group()을 사용하여 두 값 모두 지정할 수도 있습니다.

이 예에서는 이전 뷰가 slide-out-to-left 전환을 사용하여 전환되고 새 뷰가 slide-in-from-right 전환을 사용하여 전환됩니다. 둘 다 200밀리초의 지속 시간을 갖습니다.

::view-transition-group(root){
  animation-duration: 200ms;
}

::view-transition-old(root) {
  animation-name: slide-out-to-left;
}

::view-transition-new(root) {
  animation-name: slide-in-from-right;
}

컨텍스트에 따라 다른 전환

사용자가 무엇을 하고 있는지에 따라 전환을 다르게 할 수 있습니다. 예를 들어 홈페이지의 링크를 클릭하면 오른쪽에서 새 뷰가 슬라이드되는 경우 홈페이지로 돌아가는 링크를 클릭하면 왼쪽에서 홈 뷰가 슬라이드될 것으로 예상됩니다.

:active-view-transition-type() 가상 클래스를 사용하여 다양한 애니메이션을 지정할 수 있습니다.

html:active-view-transition-type(forwards) {
  &::view-transition-old(root) {
    animation-name: slide-out-to-left;
  }

  &::view-transition-new(root) {
    animation-name: slide-in-from-right;
  }
}

그런 다음 document.startViewTransition()를 호출할 때 사용할 뷰 전환 유형을 선택할 수 있습니다.

const direction = next === 'home' ? 'backwards' : 'forwards';

document.startViewTransition({
  update: updateTheDOMSomehow,
  types: [direction],
});

특정 요소 전환

지금까지는 전체 뷰를 전환하기 위해 루트 요소에만 전환을 적용했습니다. 하지만 뷰 전환을 사용하여 페이지의 특정 부분에 애니메이션을 적용할 수도 있습니다.

예를 들어 이전 뷰의 콘텐츠가 새 뷰의 콘텐츠와 일치할 수 있습니다. 콘텐츠 제목 또는 이미지일 수 있습니다. 이전 보기에서는 썸네일 이미지, 새 보기에서는 동영상일 수도 있습니다.

먼저 view-transition-name 속성을 사용하여 전환할 요소를 지정해야 합니다. 뷰 전환이 작동하려면 각 view-transition-namedocument.startViewTransition()를 호출하기 전의 요소가 정확히 하나여야 하고 document.startViewTransition()의 콜백이 완료된 후의 요소도 정확히 하나여야 합니다.

이 예에는 앨범 아트, 제목, 아티스트를 표시하는 음악 플레이어가 있습니다. 대체 뷰에는 동일한 콘텐츠가 재정렬되어 표시되며 노래 가사가 추가됩니다.

위의 예에서는 전환된 요소가 이전 뷰와 새 뷰에 각각 하나씩 있으며 동일한 선택기를 공유합니다. 전환된 요소는 크기와 위치 사이에서 이동하는 것처럼 보입니다. 전환되지 않은 뷰 부분이 서서히 나타나고 서서히 사라집니다.

더 복잡한 예를 살펴보겠습니다. 예를 들어 블로그의 홈페이지에는 각 게시물의 헤드라인과 이미지가 표시되며, 블로그 게시물의 전체 페이지 보기에도 표시됩니다. 홈페이지에서 특정 게시물로 이동할 때 제목과 이미지가 새 위치로 전환되는 것처럼 표시하여 컨텍스트를 제공할 수 있습니다.

제목에 대해 이를 수행하려면 이전 뷰에서 고유하고, 새 뷰의 제목 요소와 공유되며, 새 뷰에서 고유한 제목 요소에 view-transition-name가 있어야 합니다. 홈페이지에는 여러 헤드라인과 이미지가 있으며 사용자가 어떤 항목을 클릭할지 알 수 없으므로 이는 어려운 문제입니다.

이 문제를 해결하는 방법에는 두 가지 옵션이 있습니다. 홈페이지의 각 게시물에 고유한 view-transition-name를 추가한 다음 각 전체 페이지 게시물에서 해당 이름을 일치시킬 수 있습니다. 게시물의 ID를 사용하여 이를 생성할 수 있습니다. 다른 옵션은 일반 view-transition-name를 사용하는 것입니다. 하지만 사용자가 게시물을 클릭한 후 document.startViewTransition()를 호출하기 전에만 적용해야 합니다.

전환 설계

뷰 전환은 사용자를 안내하고 추가 브랜드 또는 컨텍스트 힌트를 제공하는 데 사용할 수 있는 도구 모음입니다. 사이트에 적합한 전환을 찾기 위해 여러 기법을 사용할 수 있습니다.

원하는 효과에 따라 요소나 애니메이션을 조정해야 할 수도 있습니다. 이전 예에서는 부드러운 전환을 위해 여러 스타일이 조정되었습니다.

헤드라인에는 width: fit-content 규칙이 있습니다. 이는 텍스트가 줄바꿈되지 않거나 이전 뷰와 새 뷰에서 줄바꿈이 동일한 경우 유용한 스타일입니다. 그렇지 않으면 너비가 다른 요소 간에 전환이 발생하여 전환이 매끄럽지 않을 수 있습니다.

이전 보기와 새 보기에서 이미지의 가로세로 비율도 다릅니다. 이 예에서는 전환이 부드럽게 표시되도록 애니메이션과 object-fit 속성을 수정합니다.

prefers-reduced-motion 존중

사용자가 동작 감소를 요청하는 일반적인 이유는 뷰 전환으로 구현할 수 있는 전체 화면 애니메이션이 전정 기관 운동 장애가 있는 사람에게 불편함을 줄 수 있기 때문입니다. prefers-reduced-motion 미디어 쿼리를 사용하여 애니메이션을 사용 중지할 수 있습니다. 요소가 어떻게 연결되는지 전달하면서도 더 미묘한 대체 애니메이션을 제공할 수도 있습니다.

@media (prefers-reduced-motion) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

이해도 확인

document.startViewTransition()가 호출되기 전의 뷰를 나타내는 의사 요소의 이름은 무엇인가요?

::view-transition-previous
오답입니다.
::view-transition-prior
오답입니다.
::view-transition-old
정답입니다.
::view-transition-initial
오답입니다.

뷰 전환의 기본 애니메이션은 무엇인가요?

새 이미지가 페이드 인될 때 이전 이미지를 페이드 아웃
정답입니다.
왼쪽에서 오른쪽으로 슬라이드
오답입니다.
이전 항목을 흰색으로 페이드하고 새 항목으로 페이드
오답입니다.
별 모양 와이프
오답입니다.

페이지의 기본 view-transition-name는 무엇인가요?

document
오답입니다.
shadow-root
오답입니다.
root
정답입니다.
body
오답입니다.