누적 레이아웃 변경 (CLS)은 세 가지 코어 웹 바이탈 측정항목 중 하나입니다. 표시 영역에서 표시되는 콘텐츠의 양과 영향을 받는 요소가 이동한 거리를 결합하여 콘텐츠의 불안정성을 측정합니다.
레이아웃 변경은 사용자의 주의를 산만하게 할 수 있습니다. 페이지를 돌아다니면서 갑작스러운 요소가 바뀌면서 기사를 읽기 시작했는데, 그때 어디로 이동해야 하는지 다시 생각해봐야 한다고 가정해 보겠습니다. 이는 뉴스를 읽거나 '검색' 또는 '장바구니에 추가' 버튼을 클릭하려고 할 때를 비롯해 웹에서 매우 일반적입니다. 이러한 경험은 시각적으로 거슬리고 답답합니다. 이 오류는 다른 요소가 갑자기 페이지에 추가되거나 크기가 조절되어 표시된 요소가 강제로 이동해야 하는 경우 종종 발생합니다.
우수한 사용자 환경을 제공하려면 페이지 방문 중 최소 75% 에 대해 사이트의 CLS가 0.1 이하여야 합니다.
초 또는 밀리초 단위로 측정되는 시간 기반 값인 다른 코어 웹 바이탈과 달리 CLS 점수는 콘텐츠 이동 양과 이동 정도를 계산한 단위 없는 값입니다.
이 가이드에서는 레이아웃 변경의 일반적인 원인을 최적화하는 방법을 알아봅니다.
잘못된 CLS의 가장 일반적인 원인은 다음과 같습니다.
- 크기가 없는 이미지
- 크기가 없는 광고, 삽입, iframe
- 크기 없이 광고, 삽입, iframe과 같이 동적으로 삽입된 콘텐츠
- 웹 글꼴:
레이아웃 변경의 원인 파악
일반적인 CLS 문제의 솔루션을 살펴보기 전에 CLS 점수와 변화의 원인을 이해하는 것이 중요합니다.
실습 도구와 현장의 CLS 비교
개발자는 Chrome UX 보고서 (CrUX)에서 측정된 CLS가 Chrome DevTools 또는 다른 실험실 도구를 사용하여 측정하는 CLS와 일치하지 않기 때문에 잘못되었다고 생각하는 경우가 많습니다. Lighthouse와 같은 웹 성능 실험실 도구는 페이지의 전체 CLS를 표시하지 않을 수 있습니다. 일반적으로 일부 웹 성능 측정항목을 측정하고 안내를 제공하기 위해 페이지를 간단히 로드하기 때문입니다. 그러나 Lighthouse 사용자 흐름을 사용하면 기본 페이지 로드 감사 이상으로 측정할 수 있습니다.
CrUX는 웹 바이탈 프로그램의 공식 데이터 세트입니다. 실험실 도구에서 일반적으로 측정하는 초기 페이지 로드 시뿐만 아니라 페이지의 전체 수명 전반에 걸쳐 CLS를 측정합니다.
레이아웃 변경은 페이지 로드 중에 매우 흔하게 발생합니다. 시스템에서 페이지를 렌더링하는 데 필요한 모든 리소스를 가져올 때이지만 초기 로드 후에도 레이아웃 변경이 발생할 수 있기 때문입니다. 많은 로드 후 이동은 사용자 상호작용의 결과로 발생하므로 CLS 점수에서 제외됩니다. 이러한 상호작용으로부터 500밀리초 이내에 발생하는 한 예상된 변동으로 간주됩니다.
그러나 조건을 충족하는 상호작용이 없는 경우(예: 사용자가 페이지를 스크롤하는 동안 지연 로드 콘텐츠가 완전히 로드되는 경우) 로드 후 예상치 못한 변화가 포함될 수 있습니다. 로드 후 CLS의 다른 일반적인 원인은 전환 간 상호작용(예: 500밀리초의 유예 기간보다 오래 걸리는 단일 페이지 앱)으로 인해 발생합니다.
PageSpeed Insights의 '실제 사용자가 경험하는 문제 알아보기' 섹션에 URL의 사용자 인식 CLS와 '성능 문제 진단' 섹션에 실험실 기반 로드 CLS가 표시됩니다. 이러한 값 간의 차이는 로드 후 CLS의 결과일 가능성이 높습니다.
로드 CLS 문제 식별
PageSpeed Insights의 CrUX와 Lighthouse CLS 점수가 비슷하다면 일반적으로 Lighthouse에서 로드 CLS 문제를 감지했다는 의미입니다. 이 경우 Lighthouse는 자세한 정보를 확인하기 위해 두 가지 감사를 제공할 수 있습니다. 하나는 누락된 너비와 높이로 인해 CLS를 일으키는 이미지를 위한 것이고 다른 하나는 CLS 기여도와 함께 페이지 로드 중에 변경된 모든 요소에 관한 감사입니다. 이러한 감사를 보려면 다음 이미지와 같이 필터링합니다.
DevTools의 성능 패널에서도 환경 섹션의 레이아웃 변경이 강조표시됩니다. Layout Shift
레코드의 Summary 뷰에는 CLS 점수는 물론 영향을 받는 지역을 보여주는 직사각형 오버레이가 포함되어 있습니다. 이렇게 하면 새로고침 성능 프로필을 사용하여 사용자 환경을 복제할 수 있으므로 로드 CLS 문제를 식별하는 데 특히 유용합니다.
로드 후 CLS 문제 식별
CrUX와 Lighthouse CLS 점수의 불일치는 로드 후 CLS를 나타내는 경우가 많습니다. 이러한 변동은 현장 데이터가 없으면 추적하기 까다로울 수 있습니다. 필드 데이터 수집에 관한 자세한 내용은 필드의 CLS 요소 측정을 참고하세요.
웹 바이탈 Chrome 확장 프로그램을 사용하면 사용자가 페이지와 상호작용하는 동안 헤드업 디스플레이 또는 콘솔에서 변경된 요소에 관한 세부정보와 함께 CLS를 모니터링할 수 있습니다.
확장 프로그램을 사용하는 대신 Console에 붙여넣은 Performance Observer를 사용하여 레이아웃 변경을 기록하면서 웹페이지를 탐색할 수 있습니다.
교대근무 모니터링을 설정한 후에는 로드 후 CLS 문제를 복제해 볼 수 있습니다. CLS는 사용자가 페이지를 스크롤하는 동안, 지연 로드 콘텐츠가 예약된 공간 없이 완전히 로드될 때 발생하는 경우가 많습니다. 사용자가 포인터를 콘텐츠 위에 놓을 때 콘텐츠가 이동하는 것도 로드 후 CLS의 또 다른 일반적인 원인입니다. 이러한 상호작용 중 콘텐츠 변경은 500밀리초 이내에 발생하더라도 예상치 못한 활동으로 간주됩니다.
자세한 내용은 레이아웃 변경 디버그를 참고하세요.
CLS의 일반적인 원인을 확인한 후 Lighthouse의 기간 사용자 흐름 모드를 사용하여 레이아웃 변경으로 인해 일반적인 사용자 흐름이 중단되지 않도록 할 수도 있습니다.
필드의 CLS 요소 측정
현장에서 CLS를 모니터링하는 것은 CLS가 발생하는 상황을 확인하고 가능한 원인을 좁히는 데 매우 유용할 수 있습니다. 대부분의 실험실 도구와 마찬가지로 필드 도구는 변한 요소만 측정하지만 보통 원인을 파악하기에 충분한 정보를 제공합니다. CLS 필드 측정을 사용하여 해결해야 할 우선순위가 가장 높은 문제를 확인할 수도 있습니다.
web-vitals
라이브러리에는 이러한 추가 정보를 수집할 수 있는 기여 분석 함수가 있습니다. 자세한 내용은 필드에서 성능 디버그를 참고하세요.
다른 RUM 제공업체도 이와 비슷하게 이 데이터를 수집하고 표시하기 시작했습니다.
CLS의 일반적인 원인
이 섹션에서는 CLS의 일반적인 이유와 이를 방지하는 전략을 설명합니다.
크기가 없는 이미지
이미지 및 동영상 요소에 항상 width
및 height
크기 속성을 포함하거나 CSS aspect-ratio
를 사용하여 필요한 공간을 예약합니다.
이렇게 하면 이미지가 로드되는 동안 브라우저가 문서에 올바른 공간을 할당할 수 있습니다.
width
, height
, aspect-ratio
웹 초기에 개발자는 width
및 height
속성을 <img>
태그에 추가하여 브라우저가 이미지를 가져오기 전에 페이지에 충분한 공간이 할당되도록 했습니다. 이렇게 하면 리플로우 및 레이아웃 재배치가 최소화됩니다.
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">
이 예에서 width
와 height
는 단위를 포함하지 않습니다. 이러한 '픽셀' 크기는 브라우저가 640x360 영역을 확보하도록 합니다. 이미지는 실제 크기가
이와 일치하는지 여부와 관계없이 이 공간에 맞게 늘어납니다.
반응형 웹 디자인이 도입되었을 때 개발자는 width
및 height
대신 CSS를 사용하여 이미지 크기를 조절하기 시작했습니다.
img {
width: 100%; /* or max-width: 100%; */
height: auto;
}
그러나 이미지 크기가 지정되지 않았으므로 브라우저에서 다운로드를 시작하고 크기를 확인할 수 있을 때까지 이미지를 위한 공간을 할당할 수 없습니다. 이미지가 로드될 때 텍스트가 페이지 아래로 이동하여 이미지를 위한 공간을 확보하므로 혼란스럽고 불편한 사용자 환경을 만들 수 있습니다.
이미지 크기 설정 권장사항
최신 브라우저는 이미지의 width
및 height
속성을 기반으로 이미지의 기본 가로세로 비율을 설정하므로 이미지에 이러한 속성을 설정하고 스타일 시트에 이전 CSS를 포함하여 레이아웃 변경을 방지할 수 있습니다.
<!-- set a 16:9 aspect ratio as 640x360 pixels -->
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">
그러면 브라우저에서 요소의 기존 width
및 height
속성에 기반하여 기본 가로세로 비율을 추가하므로 레이아웃 계산을 시작할 때 이미지를 위해 남겨둘 공간을 결정할 수 있습니다.
주요 브라우저에서는 HTML이 처리될 때 기본 가로세로 비율을 계산하므로 브라우저마다 값을 약간 다르게 표시합니다. 발생 이유에 관한 자세한 내용은 너비 및 높이 프레젠테이션 힌트를 참고하세요.
예를 들어 Chrome은 요소 패널의 스타일 섹션에 다음과 같은 가로세로 비율을 표시합니다.
img[Attributes Style] {
aspect-ratio: auto 640 / 360;
}
Safari는 HTML 속성 스타일 소스를 사용하여 유사하게 동작합니다. Firefox는 계산된 aspect-ratio
를 Inspector(검사기) 패널에 전혀 표시하지 않지만 레이아웃에 사용합니다.
위 코드의 auto
부분은 이미지 다운로드 후 이미지 크기가 기본 가로세로 비율을 재정의하게 하므로 중요합니다. 이미지 크기가 다르면 이미지가 로드된 후에도 여전히 레이아웃이 약간 변경되지만 HTML이 잘못된 경우 이미지 가로세로 비율이 제공되더라도 계속 사용됩니다. 실제 가로세로 비율이 기본값과 다르더라도 제공된 크기가 없는 이미지의 0x0 기본 크기보다 레이아웃 이동이 더 적습니다.
가로세로 비율과 반응형 이미지의 원리를 자세히 알아보려면 미디어 가로세로 비율을 사용한 버벅거림 없는 페이지 로드를 참고하세요.
이미지가 컨테이너에 있으면 CSS를 사용하여 이미지 크기를 컨테이너의 너비에 맞출 수 있습니다. 이미지 높이에 고정 값을 사용하지 않도록 height: auto;
를 설정합니다.
img {
height: auto;
width: 100%;
}
반응형 이미지는 어떨까요?
반응형 이미지로 작업할 때 srcset
는 브라우저가 선택할 수 있는 이미지와 각 이미지의 크기를 정의합니다. <img>
의 너비 및 높이 속성을 설정하려면 각 이미지에 동일한 가로세로 비율을 사용하세요.
<img
width="1000"
height="1000"
src="puppy-1000.jpg"
srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w"
alt="Puppy with balloons"
/>
이미지의 가로세로 비율도 아트 디렉션에 따라 변경될 수 있습니다. 예를 들어 좁은 표시 영역의 경우 이미지를 잘라낸 장면을 포함하고 데스크톱에 전체 이미지를 표시할 수 있습니다.
<picture>
<source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" />
<source media="(min-width: 800px)" srcset="puppy-800w.jpg" />
<img src="puppy-800w.jpg" alt="Puppy with balloons" />
</picture>
이제 Chrome, Firefox, Safari에서 picture
요소의 source
하위 요소에서 width
및 height
설정을 지원합니다.
<picture>
<source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" width=480 height=400/>
<source media="(min-width: 800px)" srcset="puppy-800w.jpg" width=800 height=400/>
<img src="puppy-800w.jpg" alt="Puppy with balloons" width=800 height=400/>
</picture>
광고, 삽입, 기타 늦게 로드된 콘텐츠
레이아웃 변경을 일으킬 수 있는 콘텐츠 유형은 이미지만이 아닙니다. 광고, 삽입, iframe 및 동적으로 삽입된 기타 콘텐츠는 모두 그 다음에 콘텐츠를 표시함으로써 아래로 이동하여 CLS를 증가시킬 수 있습니다.
광고는 웹에서 레이아웃 변경에 가장 크게 기여하는 요인 중 하나입니다. 광고 네트워크와 게시자는 동적 광고 크기를 지원하는 경우가 많으며, 큰 광고가 작은 광고보다 더 많은 수익을 창출하는 경우가 많습니다. 하지만 광고가 갑자기 로드되어 표시된 콘텐츠를 페이지 아래로 밀어내는 것은 사용자 환경에 좋지 않습니다.
삽입 가능한 위젯을 사용하면 YouTube 동영상, Google 지도의 지도, 소셜 미디어 게시물과 같은 이식 가능한 웹 콘텐츠를 페이지에 포함할 수 있습니다. 그러나 이러한 위젯은 로드하기 전에 콘텐츠가 얼마나 큰지 인식하지 못하는 경우가 많습니다. 따라서 삽입을 제공하는 플랫폼은 항상 위젯을 위한 공간을 예약하지 않으며, 이로 인해 최종적으로 로드될 때 레이아웃이 변경됩니다.
이를 처리하는 기술은 모두 유사합니다. 주요 차이점은 삽입된 콘텐츠를 제어할 수 있는 정도입니다. 광고 파트너와 같은 서드 파티는 삽입된 콘텐츠에 관한 유용한 정보를 제공하거나 이러한 삽입으로 인해 발생하는 레이아웃 변경을 제어하지 않는 경우가 많습니다.
콘텐츠 지연 로드를 위한 공간 예약
지연 로드 콘텐츠를 콘텐츠 흐름에 배치할 때 초기 레이아웃에서 콘텐츠 흐름을 예약하여 레이아웃 변경을 피할 수 있습니다.
min-height
스타일 지정을 추가하여 공간을 예약하거나 광고와 같은 반응형 콘텐츠의 경우 브라우저에서 새 aspect-ratio
CSS 속성을 자동으로 사용하는 것과 비슷한 방식으로 사용하면 됩니다.
미디어 쿼리를 사용하는 폼 팩터 간에 광고 또는 자리표시자 크기의 미묘한 차이를 고려해야 할 수도 있습니다.
광고와 같이 높이가 고정되지 않을 수 있는 콘텐츠의 경우 레이아웃 변경을 완전히 제거하는 데 필요한 정확한 공간을 예약하지 못할 수 있습니다. 더 작은 광고가 게재되는 경우 게시자는 레이아웃 변경을 방지하기 위해 더 큰 컨테이너의 스타일을 지정하거나 이전 데이터를 기반으로 가장 적합한 광고 슬롯 크기를 선택할 수 있습니다. 이 방식의 단점은 페이지의 빈 공간이 증가한다는 것입니다.
대신 초기 크기를 사용할 가장 작은 크기로 설정하고 더 큰 콘텐츠의 경우 일정 수준의 이동을 허용할 수 있습니다. 앞에서 제안된 대로 min-height
를 사용하면 빈 요소의 기본 크기 0픽셀에 비해 레이아웃 변경의 영향을 줄이는 동시에 필요에 따라 상위 요소를 늘릴 수 있습니다.
예를 들어 광고가 반환되지 않는 경우 자리표시자를 표시하여 예약된 공간이 축소되지 않도록 합니다. 요소를 위해 따로 설정한 공간을 제거하면 콘텐츠 삽입만큼이나 많은 CLS가 발생할 수 있습니다.
지연 로드 콘텐츠를 표시 영역의 아래쪽에 배치
표시 영역 상단에 동적으로 삽입된 콘텐츠는 일반적으로 표시 영역 하단에 삽입된 콘텐츠보다 더 많이 레이아웃 변경을 일으킵니다. 그러나 표시 영역의 아무 곳에나 콘텐츠를 삽입해도 여전히 약간의 변동이 발생합니다. 삽입된 콘텐츠의 공간을 예약할 수 없다면 페이지의 뒷부분에 배치하여 영향을 줄이는 것이 좋습니다.
오버레이 배너 콘텐츠
배너와 양식이 예기치 않게 페이지에 나타나는 것도 예기치 않은 레이아웃 변경의 일반적인 원인입니다.
이러한 종류의 콘텐츠를 위한 공간을 예약할 수 없다면 대신 기존 콘텐츠에 오버레이하여 문서 흐름의 일부가 되지 않도록 할 수 있습니다. 이 접근 방식을 사용해야 하는 경우에 대한 조언은 쿠키 알림 권장사항을 참조하세요.
사용자 상호작용이 예상되는 레이아웃 변경을 트리거하도록 허용
경우에 따라 콘텐츠를 동적으로 추가하는 것은 사용자 환경에서 중요한 부분입니다. 예를 들어 항목 목록에 더 많은 제품을 로드하거나 실시간 피드 콘텐츠를 업데이트하는 경우가 있습니다. 이러한 경우에 예기치 않은 레이아웃 변경을 방지할 수 있는 몇 가지 방법이 있습니다.
- 고정 크기 컨테이너 내에서 기존 콘텐츠를 새 콘텐츠로 대체하거나 전환 후 캐러셀을 사용하여 이전 콘텐츠를 삭제합니다. 전환이 완료될 때까지 링크와 컨트롤을 사용 중지하여 새 콘텐츠가 로드되는 동안 실수로 클릭이나 탭을 하지 않도록 해야 합니다.
- 사용자가 더 로드하기 또는 새로고침 버튼을 사용하여 새 콘텐츠 로드를 시작할 수 있게 하세요. 그러면 예기치 않은 전환이 발생하지 않습니다. 새 콘텐츠가 즉시 표시되도록 사용자 상호작용 전에 미리 가져오는 것이 좋습니다. 참고로 사용자 입력 500밀리초 이내의 레이아웃 변경은 CLS에 포함되지 않습니다.
- 콘텐츠를 화면 밖으로 원활하게 로드하고 사용자에게 사용 가능하다는 알림을 오버레이합니다 (예: 맨 위로 스크롤 버튼 사용).
애니메이션
CSS 속성 값을 변경하면 브라우저가 이러한 변경사항에 반응해야 할 수 있습니다. box-shadow
및 box-sizing
와 같은 일부 값은 레이아웃 재배치, 페인트, 합성을 트리거합니다. top
및 left
속성을 변경하면 이동 중인 요소가 자체 레이어에 있더라도 레이아웃이 변경됩니다. 이러한 속성을 사용하여 애니메이션을 적용하지 마세요.
다른 CSS 속성은 레이아웃 재실행을 트리거하지 않고도 변경할 수 있습니다. 여기에는 transform
애니메이션을 사용하여 요소를 변환, 크기 조정, 회전, 왜곡하는 작업이 포함됩니다.
translate
를 사용하여 합성된 애니메이션은 다른 요소에 영향을 줄 수 없으므로 CLS에 포함되지 않습니다. 합성되지 않은 애니메이션도 레이아웃이 재배치되지 않습니다. 레이아웃 변경을 트리거하는 CSS 속성에 관한 자세한 내용은 고성능 애니메이션을 참고하세요.
웹 글꼴
웹 글꼴 다운로드 및 렌더링은 일반적으로 웹 글꼴을 다운로드하기 전에 다음 두 가지 방법 중 하나로 처리됩니다.
- 대체 글꼴이 FOUT (스타일 지정이 없는 텍스트) 플래시를 사용하여 웹 글꼴로 교체됩니다.
- '표시되지 않는' 텍스트는 FOIT (Flash of Invisible Text)를 사용하여 웹 글꼴을 사용할 수 있고 텍스트가 표시될 때까지 대체 글꼴을 사용하여 표시됩니다.
두 접근 방식 모두 레이아웃 변경을 일으킬 수 있습니다. 텍스트가 보이지 않더라도 여전히 대체 글꼴을 사용하여 배치되므로 웹 글꼴이 로드되면 텍스트 블록과 주변 콘텐츠가 표시되는 글꼴과 같은 방식으로 옮겨집니다.
다음 도구를 사용하면 이러한 텍스트 변경을 최소화할 수 있습니다.
font-display: optional
은 초기 레이아웃 시점에 사용할 수 있는 경우에만 웹 글꼴을 사용하도록 합니다.- 웹 글꼴과 유사한 대체 글꼴을 사용합니다. 예를 들어
font-family: "Google Sans", sans-serif;
를 사용하면"Google Sans"
가 로드되는 동안 브라우저에서sans-serif
대체 글꼴을 사용합니다. 대체 글꼴을 지정하지 않으면 (font-family: "Google Sans"
만 사용) Chrome에서 기본 serif 글꼴이 사용되므로 더 일치도가 떨어집니다. - 새로운
size-adjust
,ascent-override
,descent-override
,line-gap-override
API를 사용하여 대체 글꼴과 웹 글꼴 간의 크기 차이를 최소화하세요. 자세한 내용은 개선된 글꼴 대체를 참고하세요. - Font Loading API는 글꼴 로드 시간을 줄일 수 있습니다.
<link rel=preload>
를 사용하여 중요한 웹 글꼴을 최대한 빨리 로드합니다. 미리 로드된 글꼴은 첫 번째 페인트를 위해 준비될 가능성이 높으며 레이아웃 변경을 일으키지 않습니다.
자세한 내용은 글꼴 권장사항을 참고하세요.
페이지에서 bfcache를 사용할 수 있도록 설정하기
CLS 점수를 낮게 유지하는 매우 효과적인 방법은 웹페이지에서 뒤로-앞으로 캐시 (bfcache)를 사용할 수 있도록 하는 것입니다.
bfcache는 사용자가 페이지에서 나갈 때 잠시 동안 브라우저의 메모리에 페이지를 유지하므로, 다시 돌아와도 페이지가 종료했을 때 그대로 복원됩니다. 즉, 페이지가 로드되는 동안 발생하는 변경 없이 완전히 로드된 페이지를 즉시 사용할 수 있습니다.
이는 여전히 초기 페이지 로드에 레이아웃이 변경된다는 의미일 수 있지만 사용자가 동일한 레이아웃 변경이 반복적으로 발생하지 않도록 할 수 있습니다. 이렇게 하면 다른 방법으로 확인하는 데 어려움을 겪을 수 있는 레이아웃 변경의 영향을 줄일 수 있습니다.
뒤로 및 앞으로 탐색은 콘텐츠 페이지, 카테고리 페이지 또는 검색결과로 돌아갈 때와 같이 많은 사이트에서 일반적입니다.
bfcache는 기본적으로 모든 브라우저에서 사용되지만, 일부 사이트에서는 여러 가지 이유로 이를 사용할 수 없습니다. bfcache 사용을 방해하는 문제를 테스트하고 식별하는 방법에 관한 자세한 내용은 bfcache 도움말을 참고하세요.