상태 캐싱을 통한 더 빠른 SPA 뷰 전환

웹 기능: content-visibility

비활성 뷰의 렌더링된 상태를 삭제하는 대신 캐시하여 단일 페이지 애플리케이션 (SPA)에서 뷰 간에 즉시 탐색할 수 있도록 합니다.

개요

기존에는 사용자가 SPA에서 탭이나 뷰 사이를 이동할 때 개발자가 이전 뷰를 삭제하거나 display: none를 사용하여 숨겼습니다. 두 접근 방식 모두 사용자가 해당 뷰로 돌아갈 때 브라우저가 전체 레이아웃을 다시 만들거나 다시 계산하고 페인트해야 합니다.

비활성 뷰에 content-visibility: hidden를 사용하면 브라우저가 레이아웃 흐름에서 요소의 콘텐츠를 삭제하고 페인팅을 중지하지만 캐시된 렌더링 상태는 메모리에 유지합니다. 사용자가 다시 전환하면 뷰가 거의 즉시 복원됩니다.

CPU와 RAM의 장단점

이 접근 방식은 엄청난 성능 이점을 제공하지만 신중하게 관리해야 하는 특정 장단점이 있습니다.

  • CPU 절감: 대폭 절감됩니다. 브라우저는 숨겨진 뷰의 레이아웃 및 페인트 패스를 완전히 건너뜁니다.
  • RAM 비용: 높음. 브라우저는 숨겨진 뷰의 모든 DOM 노드, 이벤트 리스너, 상태를 메모리에 보관합니다.

이러한 절충이 위험해지는 경우

  • 뷰 수가 적고 예측 가능한 간단한 애플리케이션 (예: 탭 인터페이스 3~5개)에는 이 전략을 사용합니다.
  • 수십 개의 고유한 보고서를 생성하거나 무한한 동적 경로를 사용하는 매우 동적인 애플리케이션에서는 모든 뷰를 무조건 캐시하지 마세요. 이렇게 하면 결국 심각한 메모리 비대화가 발생하고 저사양 기기에서 브라우저가 비정상 종료될 수 있습니다.
  • 필수: 애플리케이션이 매우 동적인 경우 메모리 기준점에 도달하면 이전 뷰를 삭제하는 제거 전략(예: 가장 오래전에 사용한 캐시)을 구현해야 합니다(MUST).

구현

1. 뷰 컨테이너 구성

현재 활성 상태가 아닌 뷰에 content-visibility: hidden를 설정합니다.

.spa-view.inactive {
  /* MANDATORY: Use hidden to cache the rendering state of inactive views */
  content-visibility: hidden;
  
  /* Optional: Prevent hidden views from taking up physical space in layout flow */
  position: absolute;
}

2. 집중 관리

뷰를 전환할 때는 접근성을 유지하기 위해 키보드 포커스를 올바르게 관리해야 합니다.

function switchToView(viewId) {
  // Hide all views
  document.querySelectorAll('.spa-view').forEach(view => {
    view.classList.add('inactive');
    view.setAttribute('aria-hidden', 'true');
  });
  
  // Show the target view
  const activeView = document.getElementById(viewId);
  activeView.classList.remove('inactive');
  activeView.setAttribute('aria-hidden', 'false');
  
  // MANDATORY: Move focus to the new view to ensure a logical tab-order
  activeView.focus();
}

대체 전략

content-visibility 속성은 단계적으로 저하됩니다. 이를 지원하지 않는 브라우저의 경우:

  • 속성이 무시됩니다.
  • 대체 브라우저가 모든 뷰를 동시에 렌더링하지 않도록 하려면 CSS에서 display: none에 대한 대체를 제공해야 합니다.
@supports not (content-visibility: hidden) {
  .spa-view.inactive {
    display: none;
  }
}