Cumulative Layout Shift를 개선하려면 예상하지 못한 레이아웃 변경을 일으키는 요소를 찾고 콘텐츠가 도착하기 전에 필요한 공간을 확보해야 합니다. 미디어 크기, 광고 슬롯, 삽입 콘텐츠, 배너와 글꼴 교체부터 확인합니다. 첫 화면이 안정적이어도 나중에 움직일 수 있으므로 초기 로드 이후의 사용 과정도 기록합니다.
75번째 백분위수에서 CLS가 0.1 이하면 양호합니다. CLS는 예상치 못한 시각적 이동을 나타내는 단위 없는 값이며 지연 시간을 초로 표시한 값이 아닙니다. 다운로드 속도를 높이면 일부 이동 기회를 줄일 수 있지만, 예측 가능한 배치가 더 직접적인 해결책입니다.
움직인 요소를 따라가기 전에 계산 방식 이해하기
개별 레이아웃 변경 점수는 영향 비율과 거리 비율을 곱한 값입니다. 영향 비율은 불안정한 요소의 이전 및 이후 가시 영역을 합친 면적을 뷰포트 면적으로 나눈 값입니다. 거리 비율은 가장 큰 수평 또는 수직 이동 거리를 뷰포트의 긴 변으로 나눕니다. CLS는 변경 사이의 간격이 1초 미만이고 전체 길이가 최대 5초인 세션 창으로 변경을 묶습니다. 합계가 가장 큰 창이 최종 값에 반영됩니다.
따라서 오래 열려 있는 페이지의 모든 변경이 끝없이 누적되는 것은 아닙니다. 다만 초기 로드가 안정적이었어도 나중에 발생한 큰 변경 묶음이 결과를 결정할 수 있습니다.
사용자 입력 직후의 일부 변경은 제외됩니다. 그렇다고 이전 클릭과 연결되는 모든 늦은 변경이 제외되지는 않습니다. 측정에서 제외된다고 편안하거나 접근성이 좋다는 뜻도 아닙니다. 점수와 관계없이 읽던 위치와 사용자의 제어권을 유지해야 합니다.
브라우저가 보여 주는 이동 요소가 원인 요소와 같지는 않습니다. 광고 때문에 내려간 제목은 피해 요소이며, 실제로 고쳐야 할 대상은 커진 광고입니다. 같은 시점에 주변에서 무엇이 달라졌는지 확인합니다.
전체 평가의 맥락은 Core Web Vitals 입문 안내를 참고합니다. 단일 기록의 CLS와 여러 방문의 p75를 구분합니다.
로드와 로드 이후의 동작 기록하기
Chrome DevTools의 Performance 패널에서 대표적인 이용 과정을 기록합니다. 레이아웃 변경 이벤트와 시각적 증거를 함께 확인합니다. Rendering 도구의 변경 영역 강조 기능은 재현 중 움직임을 찾는 데 도움이 됩니다.
첫 방문, 동의 선택, 늦게 도착하는 광고, 삽입 콘텐츠까지의 스크롤, 캐시되지 않은 글꼴 로드를 포함합니다. 여러 화면 너비도 시험합니다. 데스크톱에서 맞는 예약 공간이 모바일에서는 잘못 늘어나거나 줄어들 수 있습니다.
보이는 모든 움직임이 CLS 이벤트인 것은 아닙니다. 스크롤은 화면에 보이는 영역을 바꾸며, transform은 문서 흐름을 같은 방식으로 바꾸지 않고 요소를 움직일 수 있습니다. 단순한 인상보다 기록된 이벤트를 기준으로 판단합니다.
원인과 영향을 받은 대상을 따로 적습니다. 제목 자체가 잘못되었다고 하기보다 미디어 컨테이너가 커지면서 다음 제목을 밀었다고 기록하면 담당자가 실제로 수정할 수 있습니다.
Google의 CLS 최적화 안내는 초기 로드와 이후 변경을 구분합니다. 모든 항목이 사이트에 존재한다고 가정하지 말고 자신의 사례를 찾는 데 활용합니다.
이미지와 동영상의 자리를 미리 확보하기
이미지의 width와 height 속성을 사용하면 다운로드 전에 가로세로 비율을 계산할 수 있습니다. 반응형 CSS를 함께 사용할 수 있으며, 속성에는 검사 통과용 임의 숫자가 아닌 실제 비율을 넣어야 합니다.
다음 예시는 컨테이너에 맞게 줄어드는 가로형 이미지 공간을 확보합니다. 파일은 프로젝트 자산을 가정한 예시입니다.
<img class="article-image"
src="/images/diagram.webp"
width="1600" height="900"
loading="lazy"
alt="A page layout with space reserved for media">.article-image {
display: block;
max-width: 100%;
height: auto;
}지연 로드는 중요한 초기 화면 밖에 있는 이미지에만 적절합니다. LCP 이미지에 그대로 복사하지 않습니다. 공간 확보는 안정성 문제이고, 로드 시점은 리소스가 준비되는 시점을 결정합니다.
아트 디렉션을 적용한 이미지는 분기점마다 비율이 다를 수 있습니다. 예약 공간이 실제 선택된 이미지와 일치하는지 확인합니다. 모바일 세로 이미지에 데스크톱 가로 비율을 강제하면 잘림이나 나중의 크기 수정이 생길 수 있습니다.
이미지 주변도 확인해야 합니다. 캡션, 테두리와 조작 버튼이 뒤늦게 높이를 더할 수 있습니다. 전체 미디어 구성요소가 예측 가능해야 합니다. 이미지 최적화 안내는 반응형 리소스 선택과 이 배치 결정을 연결합니다.
광고가 결정되기 전에 슬롯 크기 정하기
최초 레이아웃 시점에는 최종 광고 소재를 모를 수 있습니다. 화면 너비별 지원 크기를 정하고 초기 배치에서 공간을 확보합니다. CSS 높이를 추측하지 말고 광고 설정과 일치시켜야 합니다.
다음 수치는 구현 패턴을 보여 주는 예시이며 특정 광고 네트워크의 권장 크기가 아닙니다.
.ad-slot {
min-height: 250px;
display: grid;
place-items: center;
}
@media (min-width: 64rem) {
.ad-slot {
min-height: 280px;
}
}최소 높이는 작은 광고가 오거나 광고가 없더라도 그 공간을 유지할 때만 아래 콘텐츠가 올라오는 것을 막습니다. 미충전 응답 뒤 슬롯을 자동으로 접으면 피하려던 변경이 발생할 수 있습니다.
예약 공간과 빈 공간 사이에는 디자인상의 절충이 있습니다. 특히 첫 화면에서는 이를 의도적으로 결정합니다. 형식을 제한하거나 위치를 바꾸거나 중립적인 컨테이너를 유지할 수 있습니다. 예상 밖 광고를 맞추기 위해 위쪽 슬롯을 늘릴 때는 밀려나는 콘텐츠를 고려합니다.
적절한 시험 환경에서 로딩, 채워짐, 비어 있음, 실패 상태를 모두 확인합니다. 항상 같은 크기를 반환하는 모의 광고만으로 실제 서비스의 안정성을 입증할 수 없습니다.
삽입 콘텐츠가 초기화되는 동안 크기 유지하기
동영상 플레이어나 소셜 게시물은 작은 자리표시자를 더 큰 대화형 요소로 교체할 수 있습니다. 외부 코드가 실행되기 전에 예상 크기를 정하고 로딩 및 실패 중에도 유지합니다.
이 래퍼는 표시 비율이 16:9인 구성요소를 가정하며, 즉시 로드하지 않고도 공간을 확보합니다.
.video-frame {
position: relative;
aspect-ratio: 16 / 9;
background: #0c1222;
}
.video-frame > iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}모든 삽입물이 동영상 비율을 갖지는 않습니다. 게시물이나 대화형 차트는 내용에 따라 높이가 달라집니다. 제공자가 지원하는 크기 조절 방식, 현실적인 초기 공간, 확장이 현재 읽기 위치를 방해하지 않는 배치를 사용합니다.
가벼운 미리보기 화면을 사용하면 요청할 때까지 무거운 플레이어 로드를 미룰 수 있습니다. 교체 전후의 크기를 유지하고 키보드 활성화를 지원하며 외부 콘텐츠가 실패했을 때 이해할 수 있는 상태를 보여 줍니다.
서드 파티 스크립트 안내는 크기가 안정된 뒤에도 남는 실행 비용을 설명합니다. 안정성이 좋아졌다고 반응성까지 해결되었다고 볼 수는 없습니다.
배너와 비동기 패널이 기존 내용을 밀지 않게 하기
동의 제어, 공지와 추천 영역은 첫 배치 뒤 도착하는 경우가 많습니다. 주변을 렌더링하기 전에 위치를 결정합니다. 공간 예약이나 신중하게 설계한 오버레이는 본문 위에 예상 밖 블록을 삽입하는 일을 피하게 합니다.
오버레이에도 사용성 요구가 있습니다. 중요한 내용을 계속 가리거나 키보드 포커스를 잘못 가두거나 확대된 글자에서 닫을 수 없어서는 안 됩니다. 좁은 화면과 확대를 확인합니다. 고정 높이가 모든 번역에 맞지는 않습니다.
추천 영역에도 현실적인 로딩 상태가 필요합니다. 결과보다 훨씬 짧은 스켈레톤은 변경을 막지 못합니다. 줄과 이미지 구조를 비슷하게 만들거나 확장이 현재 작업을 방해하지 않는 곳에 배치합니다.
초기 CSS로 표현할 수 있는 크기를 늦은 JavaScript 측정으로 정하지 않습니다. 첫 레이아웃과 스크립트 사이에 경쟁이 생깁니다. 안정된 규칙으로 시작하고 콘텐츠가 실제로 요구할 때 동작을 추가합니다.
대체 글꼴과 웹 글꼴의 치수 맞추기
다운로드한 글꼴이 대체 글꼴을 바꾸면 글자 폭, 상승부, 하강부와 줄 간격이 달라질 수 있습니다. 제목이 한 줄 더 생기면 그 아래까지 이동합니다.
font-display: swap은 다운로드 중 텍스트를 보여 주지만 안정된 치수를 보장하지 않습니다. font-display: optional은 일부 상황에서 늦은 교체를 피하지만, 해당 방문에서는 대체 글꼴이 계속 보일 수 있습니다.
적절한 대체 글꼴을 선택하고 필요하면 size-adjust, ascent-override, descent-override, line-gap-override를 사용합니다. 값은 해당 글꼴 조합에 맞게 구해야 합니다. 다른 사이트의 백분율을 그대로 적용하면 차이가 더 커질 수 있습니다.
실제로 사용하는 문자 체계를 시험합니다. 한국어, 히브리어와 라틴 문자는 서로 다른 파일과 대체 경로를 사용할 수 있습니다. 짧은 영어 제목만으로 긴 번역이나 혼합 문자를 검증할 수 없습니다.
초기에 꼭 필요하며 그렇지 않으면 늦게 도착하는 글꼴만 미리 로드합니다. 모든 굵기를 미리 로드하면 중요한 이미지와 경쟁할 수 있습니다. 요청과 레이아웃을 함께 확인해 새로운 로딩 문제를 만들지 않습니다.
반복적인 레이아웃 변경 없이 애니메이션 구현하기
너비, 높이, top 등 배치 속성을 애니메이션하면 반복 계산과 이웃 요소 이동을 일으킬 수 있습니다. transform과 opacity는 주변 문서 흐름을 바꾸지 않는 전환에 더 적합한 경우가 많습니다.
그렇다고 중요한 콘텐츠에 불필요한 애니메이션을 넣어도 된다는 뜻은 아닙니다. CLS에 포함되지 않는 움직임도 주의를 흩트릴 수 있습니다. 동작 줄이기 설정을 존중하고 포커스와 클릭 영역을 보이는 위치에 맞춥니다.
아코디언에서는 사용자 예상과 주변 제어 위치를 고려합니다. 활성화와 펼쳐진 내용의 관계를 명확히 하고, 나중에 무관한 콘텐츠가 들어와 페이지를 미는 일을 피합니다.
새로고침이 놓친 상황을 필드 데이터로 찾기
로드 테스트는 광고 갱신이나 늦은 삽입물 도착 전에 끝날 수 있습니다. 필드 CLS가 더 나쁘면 필드 데이터가 틀렸다고 판단하기 전에 긴 이용 과정을 재현합니다.
RUM은 변경과 관련된 템플릿이나 구성요소를 찾는 데 도움이 됩니다. 브라우저 API 범위와 iframe 관찰 가능성이 CrUX와 달라 최상위 JavaScript가 모든 변경을 보지 못할 수 있습니다. 억지로 일치시키지 말고 차이를 문서화합니다.
뒤로 가기도 확인합니다. 뒤로/앞으로 캐시에서 복원되는 경우는 일반 새로고침과 다릅니다. 복원 가능성을 유지하면서 최초 로드의 문제도 수정합니다.
공통 원인을 우선합니다. 여러 페이지가 공유하는 미디어 래퍼를 고치는 편이 각 글을 수작업으로 조정하는 것보다 유용합니다. 누락 이미지, 긴 캡션과 로드 실패 같은 예외도 시험합니다.
점수와 함께 실제 배치 검증하기
변경 뒤 원래 상황을 반복하고 같은 이벤트를 확인합니다. 콘텐츠가 제자리에 있고 예약 공간이 잘림, 넘침이나 불필요한 스크롤을 만들지 않는지 검사합니다.
화면 크기, 내용 길이와 로딩 상태를 비교합니다. 키보드, 확대와 번역도 확인합니다. 고정 상자가 내용을 잘라서 안정적으로 보이는 것은 올바른 해결이 아닙니다.
측정 CLS와 조건을 변경 기록에 남깁니다. 배포 후 새 방문이 수집 기간에 들어오면서 필드 결과를 관찰합니다. 로컬 기록이 안정되었다고 Search Console이 즉시 바뀐다고 약속하지 않습니다.
늦은 콘텐츠를 구성요소 검토 항목에 포함하기
각 구성요소가 예약하는 공간, 콘텐츠가 없을 때의 동작, 상호작용 시작 뒤 높이 변경 가능성을 기록합니다. 레이아웃 안정성을 반복되는 긴급 수정이 아니라 설계 특성으로 만듭니다.
Core Web Vitals 검사 도구로 값을 해석하고 Core Web Vitals 안내에서 다음 문제를 찾습니다. 안정된 구성요소는 모두 로드된 화면뿐 아니라 정상, 지연, 실패 상태에서도 예측 가능하게 동작합니다.