화면 밖 콘텐츠 렌더링을 건너뛰어 초기 로드 시간을 개선합니다.
게시일: 2020년 8월 5일
content-visibility
속성을 사용하면 사용자 에이전트가 레이아웃 및 페인팅을 비롯한 요소의 렌더링 작업을 필요할 때까지 건너뛸 수 있습니다. 렌더링을 건너뛰므로 콘텐츠의 상당 부분이 화면 밖에 있는 경우 content-visibility
속성을 사용하면 초기 사용자 로드 속도가 훨씬 빨라집니다. 또한 화면의 콘텐츠와 더 빠르게 상호작용할 수 있습니다. 꽤 멋진 기능이네요.
CSS 포함
CSS 격리의 핵심적이고 중요한 목표는 페이지의 나머지 부분과 예측 가능한 DOM 하위 트리 격리를 제공하여 웹 콘텐츠의 렌더링 성능을 개선하는 것입니다.
기본적으로 개발자는 페이지의 어떤 부분이 콘텐츠 집합으로 캡슐화되었는지 브라우저에 알릴 수 있으므로 브라우저는 하위 트리 외부의 상태를 고려하지 않고도 콘텐츠에 관해 추론할 수 있습니다. 어떤 콘텐츠(하위 트리)에 격리된 콘텐츠가 포함되어 있는지 알면 브라우저가 페이지 렌더링을 위한 최적화 결정을 내릴 수 있습니다.
CSS 포함에는 네 가지 유형이 있으며, 각각 contain
CSS 속성의 잠재적 값으로, 공백으로 구분된 값 목록으로 결합할 수 있습니다.
size
: 요소의 크기 제약 조건을 사용하면 요소의 상속 항목을 검사하지 않고도 요소의 상자를 배치할 수 있습니다. 즉, 요소의 크기만 필요한 경우 하위 요소의 레이아웃을 건너뛸 수 있습니다.layout
: 레이아웃 포함은 하위 요소가 페이지에 있는 다른 상자의 외부 레이아웃에 영향을 미치지 않음을 의미합니다. 이렇게 하면 다른 상자를 배치하는 것만을 원한다면 자손의 레이아웃을 건너뛸 수 있습니다.style
: 스타일 격리는 하위 요소 외에도 영향을 줄 수 있는 속성이 요소 외부로 유출되지 않도록 합니다 (예: 카운터). 이렇게 하면 다른 요소의 스타일만 계산하려는 경우 하위 요소의 스타일 계산을 건너뛸 수 있습니다.paint
: 페인트 컨테이너는 포함 상자의 자손이 경계 밖에 표시되지 않도록 합니다. 요소를 넘칠 수 있는 요소는 없으며 요소가 화면 밖에 있거나 보이지 않는 경우 그 하위 요소도 보이지 않습니다. 이렇게 하면 요소가 화면 밖에 있으면 자손의 페인팅을 건너뛸 수 있습니다.
content-visibility
를 사용하여 렌더링 작업 건너뛰기
브라우저 최적화는 적절한 세트가 지정된 경우에만 시작될 수 있으므로 사용할 포함 값을 파악하기 어려울 수 있습니다. 값을 조작하여 가장 효과적인 방법을 확인하거나 content-visibility
를 사용하여 필요한 포함을 자동으로 적용할 수 있습니다. content-visibility
를 사용하면 개발자의 노력을 최소화하면서 브라우저가 제공할 수 있는 최대 성능 향상을 얻을 수 있습니다.
콘텐츠 공개 상태 속성은 여러 값을 허용하지만 auto
은 즉시 성능을 향상하는 값입니다. content-visibility: auto
가 있는 요소는 layout
, style
, paint
컨테이너닝을 얻습니다. 요소가 화면 밖에 있으면(그리고 사용자와 관련이 없는 경우, 하위 트리에 포커스나 선택 항목이 있는 요소가 관련 요소일 수 있음) 이 요소는 size
포함을 얻고 콘텐츠의 페인팅 및 히트 테스트를 중지합니다.
무슨 의미인가요? 즉, 요소가 화면 밖에 있으면 하위 요소가 렌더링되지 않습니다. 브라우저는 콘텐츠를 고려하지 않고 요소의 크기를 결정하고 여기서 중지됩니다. 요소의 하위 트리의 스타일 지정 및 레이아웃과 같은 대부분의 렌더링은 건너뜁니다.
요소가 뷰포트에 접근하면 브라우저는 더 이상 size
컨테이너를 추가하지 않고 요소의 콘텐츠를 페인팅하고 히트 테스트를 시작합니다. 이렇게 하면 사용자가 볼 수 있을 때 렌더링 작업이 완료됩니다.
접근성 관련 참고사항
content-visibility: auto
의 기능 중 하나는 화면 밖 콘텐츠가 문서 객체 모델 및 접근성 트리에서 계속 사용할 수 있다는 점입니다(visibility: hidden
와 달리). 즉, 콘텐츠가 로드될 때까지 기다리거나 렌더링 성능을 희생하지 않고도 페이지에서 콘텐츠를 검색하고 탐색할 수 있습니다.
하지만 반대로 display: none
또는 visibility: hidden
와 같은 스타일 기능이 있는 랜드마크 요소는 뷰포트에 들어갈 때까지 브라우저에서 렌더링되지 않으므로 화면 밖에 있을 때도 접근성 트리에 표시됩니다. 이러한 요소가 접근성 트리에 표시되어 혼란을 야기하지 않도록 하려면 aria-hidden="true"
도 추가해야 합니다.
예: 여행 블로그
여행 블로그에는 일반적으로 몇 장의 사진과 설명 텍스트가 포함된 일련의 이야기가 있습니다. 일반적인 브라우저에서 여행 블로그로 이동하면 다음과 같은 일이 발생합니다.
- 페이지의 일부가 필요한 리소스와 함께 네트워크에서 다운로드됩니다.
- 브라우저는 콘텐츠가 사용자에게 표시되는지 고려하지 않고 페이지의 모든 콘텐츠의 스타일을 지정하고 배치합니다.
- 모든 페이지와 리소스가 다운로드될 때까지 브라우저는 1단계로 돌아갑니다.
2단계에서 브라우저는 모든 콘텐츠를 처리하여 변경되었을 수 있는 항목을 찾습니다. 새 업데이트의 결과로 이동되었을 수 있는 요소와 함께 새 요소의 스타일과 레이아웃을 업데이트합니다. 이것은 렌더링 작업입니다. 시간이 걸립니다.
이제 블로그의 개별 스토리에 content-visibility: auto
를 추가하면 어떻게 되는지 생각해 보겠습니다. 일반적인 루프는 동일합니다. 브라우저가 페이지의 청크를 다운로드하고 렌더링합니다. 그러나 차이점은 2단계에서 실행하는 작업량에 있습니다.
content-visibility를 사용하면 현재 사용자에게 표시되는 모든 콘텐츠 (화면에 있음)의 스타일과 레이아웃이 지정됩니다. 그러나 화면 밖에 완전히 있는 스토리를 처리할 때는 브라우저가 렌더링 작업을 건너뛰고 요소 상자 자체의 스타일과 레이아웃만 지정합니다.
이 페이지를 로드하면 마치 화면에 전체 화면 스토리와 각 오프스크린 스토리의 빈 상자가 포함된 것처럼 보입니다. 이렇게 하면 로드 렌더링 비용이 50% 이상 감소하여 성능이 훨씬 향상됩니다. 이 예에서는 렌더링 시간이 232ms에서 30ms로 향상되었습니다. 성능이 7배 향상되었습니다.
이러한 혜택을 누리기 위해 어떤 작업을 해야 하나요? 먼저 콘텐츠를 섹션으로 분할합니다.
그런 다음 섹션에 다음 스타일 규칙을 적용합니다.
.story {
content-visibility: auto;
contain-intrinsic-size: 1000px; /* Explained in the next section. */
}
contain-intrinsic-size
로 요소의 자연 크기 지정
content-visibility
의 잠재적 이점을 실현하려면 브라우저에서 크기 제한을 적용하여 콘텐츠의 렌더링 결과가 요소의 크기에 영향을 주지 않도록 해야 합니다. 즉, 요소가 비어 있는 것처럼 레이아웃됩니다. 요소에 일반 블록 레이아웃에서 지정된 높이가 없으면 높이가 0이 됩니다.
스크롤바의 크기가 변경되어 높이가 0이 아닌 각 스토리에 의존하므로 이는 이상적이지 않을 수 있습니다.
다행히 CSS는 다른 속성인 contain-intrinsic-size
를 제공합니다. 이 속성은 요소가 크기 포함의 영향을 받는 경우 요소의 자연스러운 크기를 효과적으로 지정합니다. 이 예에서는 섹션의 높이와 너비를 추정하여 1000px
로 설정합니다.
즉, 'intrinsic-size' 크기의 단일 하위 요소가 있는 것처럼 레이아웃이 생성되므로 크기가 지정되지 않은 div가 여전히 공간을 차지합니다.
contain-intrinsic-size
는 렌더링된 콘텐츠 대신 자리표시자 크기 역할을 합니다.
contain-intrinsic-size
의 auto
키워드를 사용하면 브라우저가 마지막으로 렌더링된 크기(있는 경우)를 기억하고 개발자가 제공한 자리표시자 크기 대신 이를 사용합니다. 예를 들어 contain-intrinsic-size: auto 300px
를 지정하면 요소는 각 측정기준에서 300px
내적 크기로 시작하지만 요소의 콘텐츠가 렌더링되면 렌더링된 내적 크기를 유지합니다.
이후 렌더링 크기 변경사항도 기억됩니다. 실제로 이는 content-visibility: auto
가 적용된 요소를 스크롤한 다음 화면 밖으로 다시 스크롤하면 이상적인 너비와 높이를 자동으로 유지하고 자리표시자 크기로 되돌리지 않음을 의미합니다. 이 기능은 시간이 지남에 따라 사용자가 페이지를 탐색할 때 크기 추정을 자동으로 개선할 수 있는 무한 스크롤러에 특히 유용합니다.
content-visibility: hidden
로 콘텐츠 숨기기
콘텐츠가 화면에 표시되는지 여부와 관계없이 콘텐츠를 렌더링되지 않은 상태로 유지하면서 캐시된 렌더링 상태의 이점을 활용하려면 어떻게 해야 하나요? content-visibility: hidden
를 입력합니다.
content-visibility: hidden
속성은 content-visibility: auto
가 화면 밖에서 하는 것과 동일한 렌더링되지 않은 콘텐츠 및 캐시된 렌더링 상태의 모든 이점을 제공합니다. 그러나 auto
와 달리 화면에 자동으로 렌더링되지는 않습니다.
이렇게 하면 더 많은 제어 기능을 사용할 수 있으므로 요소의 콘텐츠를 숨기고 나중에 빠르게 표시할 수 있습니다.
요소의 콘텐츠를 숨기는 다른 일반적인 방법과 비교해 보세요.
display: none
: 요소를 숨기고 렌더링 상태를 소멸합니다. 즉, 요소의 숨기기를 해제하는 것은 동일한 콘텐츠로 새 요소를 렌더링하는 것만큼 비용이 듭니다.visibility: hidden
: 요소를 숨기고 렌더링 상태를 유지합니다. 그렇다고 해서 문서에서 요소가 실제로 삭제되지는 않습니다. 요소 (및 하위 트리)가 여전히 페이지에서 도형 공간을 차지하고 여전히 클릭할 수 있기 때문입니다. 또한 숨겨져 있을 때도 필요할 때마다 렌더링 상태를 업데이트합니다.
반면 content-visibility: hidden
는 렌더링 상태를 유지하면서 요소를 숨기므로 변경해야 할 사항이 있는 경우 요소가 다시 표시될 때만 변경사항이 적용됩니다(즉, content-visibility: hidden
속성이 삭제됨).
content-visibility: hidden
의 유용한 사용 사례로는 고급 가상 스크롤러 구현, 레이아웃 측정이 있습니다. 단일 페이지 애플리케이션(SPA)에도 적합합니다. 비활성 앱 뷰는 content-visibility: hidden
를 적용하여 DOM에 그대로 두어 표시되지 않도록 할 수 있지만 캐시된 상태는 유지할 수 있습니다. 이렇게 하면 뷰가 다시 활성화되었을 때 빠르게 렌더링할 수 있습니다.
다음 페인트에 대한 상호작용(INP)에 미치는 영향
INP는 페이지가 사용자 입력에 안정적으로 반응하는 능력을 평가하는 측정항목입니다. 응답성은 렌더링 작업을 비롯하여 기본 스레드에서 발생하는 과도한 작업의 영향을 받을 수 있습니다.
특정 페이지에서 렌더링 작업을 줄일 수 있을 때마다 기본 스레드가 사용자 입력에 더 빠르게 응답할 수 있는 기회를 제공하게 됩니다. 여기에는 렌더링 작업이 포함되며, 적절한 위치에 content-visiblity
CSS 속성을 사용하면 렌더링 작업을 줄일 수 있습니다. 특히 대부분의 렌더링 및 레이아웃 작업이 완료되는 시작 중에 유용합니다.
렌더링 작업을 줄이면 INP에 직접적인 영향을 미칩니다. 사용자가 content-visibility
속성을 올바르게 사용하여 화면 밖 요소의 레이아웃과 렌더링을 지연하는 페이지와 상호작용하려고 하면 기본 스레드가 중요한 사용자에게 표시되는 작업에 응답할 수 있습니다. 이렇게 하면 경우에 따라 페이지의 INP가 개선될 수 있습니다.
결론
content-visibility
및 CSS Containment 사양을 사용하면 CSS 파일에서 실적이 크게 향상됩니다. 이러한 속성에 관한 자세한 내용은 다음을 참고하세요.