누적 레이아웃 이동(CLS)
누적 레이아웃 이동의 측정 대상, 영향도×거리 공식, 세션 창, 기준값, 일반 원인과 수정·디버깅 방법을 설명합니다.
언어
누적 레이아웃 이동(CLS)은 페이지 사용 중 보이는 콘텐츠의 예기치 않은 움직임을 측정하는 핵심 웹 바이탈입니다. 이동별 영향 비율과 거리 비율을 곱한 단위 없는 점수이며 2021년 6월부터 전체 합이 아닌 가장 큰 세션 창을 사용합니다. 필드 데이터 75번째 백분위수에서 0,1 이하면 좋음입니다. 크기 없는 이미지·광고·iframe·임베드, 웹 글꼴, 폴드 위 삽입이 주요 원인이며 공간 예약, 글꼴 메트릭 조정, transform 애니메이션으로 해결합니다.
요약 — 누적 레이아웃 이동(CLS)은 페이지를 읽거나 누르는 동안 요소가 저절로 움직이는 정도를 측정합니다. 늦게 로드된 이미지가 글을 아래로 밀거나 클릭하려는 순간 버튼이 움직이는 현상입니다. 점수는 0부터 시작하며 0,1 이하면 좋음입니다. 대부분은 요소가 로드되기 전에 차지할 공간을 확보하지 않아 발생합니다.
CLS란?
용어를 몰라도 이런 현상을 겪어 봤을 것입니다. 글을 읽는데 위쪽 광고나 이미지가 로드되면서 페이지 전체가 아래로 튀거나, “취소”를 누르려는 순간 배너가 나타나 “확인”을 누르게 됩니다. 이런 예기치 않은 움직임이 레이아웃 이동이며, 누적 레이아웃 이동은 Google이 그 심각성을 수치화한 지표입니다.
CLS는 Google이 추적하는 페이지 경험 지표인 세 가지 핵심 웹 바이탈 중 하나입니다. 나머지는 주요 콘텐츠의 로딩 속도를 보는 Largest Contentful Paint와 탭에 얼마나 빨리 반응하는지 보는 Interaction to Next Paint입니다. CLS는 페이지가 가만히 유지되는지를 나타내는 시각적 안정성 지표입니다.
점수 계산 방식(개략)
CLS는 시간이 아니라 점수입니다. CLS 0,05는 50밀리초를 뜻하지 않으며 단위가 없는 수치입니다. 화면에서 움직인 영역이 크고 이동 거리가 멀수록 점수는 높아지고 나빠집니다.
기준은 간단합니다.
- 0,1 이하 — 좋음.
- 0,1~0,25 — 개선 필요.
- 0,25 초과 — 나쁨.
좋은 예외도 있습니다. 버튼을 누르거나 메뉴를 연 직후처럼 사용자가 행동해서 일어난 이동은 예상한 것이므로 불이익에 포함되지 않습니다. 예기치 않은 움직임만 계산됩니다.
Evidence for this claim CLS uses the largest session window of unexpected layout shifts, with gaps under one second and a maximum five-second window; recent discrete input can exclude a shift. Scope: Current CLS session-window and recent-input rules. Confidence: high · Verified: web.dev: Cumulative Layout Shift발생 원인과 해결법
거의 모든 레이아웃 이동은 같은 이유에서 시작합니다. 무언가 로드되면서 페이지가 미리 확보하지 않은 공간을 차지하기 때문입니다. 주요 원인은 다음과 같습니다.
- 크기가 지정되지 않은 이미지와 동영상. 브라우저는 이미지가 도착하기 전 높이를 모르므로 로드될 때 아래 텍스트를 밀어냅니다. 항상
width와height또는 CSSaspect-ratio를 지정해 자리를 확보하세요. - 광고, 임베드, iframe. 같은 문제이므로 공간을 미리 예약하세요.
- 웹 글꼴. 사용자 지정 글꼴이 대체 글꼴과 바뀔 때 텍스트 줄바꿈이 달라질 수 있습니다.
- 뒤늦게 나타나는 요소. 쿠키 배너, “추천 콘텐츠” 상자처럼 이미 보고 있는 콘텐츠 위에 삽입되는 요소입니다.
기억할 원칙은 간단합니다. 나중에 나타날 요소라면 정확한 크기의 빈자리를 미리 남겨 표시될 때 다른 요소가 움직이지 않게 하세요.
실제 공식, “세션 창” 규칙, 실험실과 필드 CLS가 다른 이유, 전체 원인·해결 목록은 고급 탭에서 확인하세요.
요약 — CLS는 시각적 안정성을 측정하는 핵심 웹 바이탈입니다. 각 이동 점수는
impact fraction × distance fraction이며, 최종 지표는 모든 이동의 평생 합계가 아니라 가장 큰 세션 창입니다. 이동 간격은 ≤ 1 s, 전체 창은 ≤ 5 s이며 이 정의는 June 2021 이전과 다릅니다. 필드 데이터의 75th 백분위수에서 좋음은 ≤ 0,1, 개선 필요는 ≤ 0,25, 나쁨은 > 0,25입니다. 현재 뷰포트에 보이는 이동만 계산하고 불연속 입력 뒤 500밀리초 안의 이동은 제외하지만 스크롤은 제외되지 않습니다. 원인은 크기 없는 이미지·동영상·광고·iframe·임베드, 웹 글꼴, 기존 콘텐츠 위 삽입이며 해결책은 공간 예약,font-display/size-adjust,transform전용 애니메이션입니다. Lighthouse는 상호작용이나 전체 수명을 재현하지 않아 실험실 점수가 거의 0일 수 있으므로 Google이 실제로 측정하는 필드 데이터(CrUX)를 확인해야 합니다.
CLS가 측정하는 것
Google은 CLS를 사용자가 예기치 않은 레이아웃 이동을 얼마나 자주 겪는지 수치화하는 안정적인 사용자 중심 핵심 웹 바이탈로 설명합니다. 핵심은 사용자가 행동해서가 아니라 콘텐츠가 저절로 움직이는 예기치 않은 이동입니다.
CLS는 로딩을 보는 Largest Contentful Paint, 반응성을 보는 Interaction to Next Paint와 함께 핵심 웹 바이탈을 구성합니다. LCP와 INP는 밀리초로 측정하지만 CLS는 단위 없는 비율 점수입니다. CLS 0,05를 50밀리초로 해석하면 안 됩니다.
공식: 영향도 × 거리
Google은 이동별 점수를 다음과 같이 정의합니다.
layout shift score = impact fraction × distance fraction- 영향 비율은 “measures how unstable elements impact the viewport area between two frames” (번역) 두 프레임 사이에서 불안정한 요소가 차지한 전후 가시 영역을 합쳐 뷰포트에서 차지하는 비율을 측정합니다.
- 거리 비율은 “the greatest horizontal or vertical distance any unstable element has moved in the frame divided by the viewport’s largest dimension (width or height, whichever is greater).” (번역) 불안정한 요소의 최대 수평·수직 이동 거리를 뷰포트의 더 큰 치수로 나눈 값입니다.
두 차원은 독립적으로 중요합니다. 작은 요소가 화면 대부분을 가로질러 이동하는 경우와 큰 요소가 조금 움직이는 경우는 점수가 크게 다를 수 있습니다. web.dev 예시에서 영향 비율 0.75와 거리 비율 0.25를 곱하면 레이아웃 이동 점수는 0.1875입니다.
Three cards form the equation. Impact fraction is 0.75: the visible viewport area affected between two frames. Distance fraction is 0.25: the farthest movement divided by the viewport's largest dimension. Multiplying them produces a unitless individual layout-shift score of 0.1875. CLS ultimately keeps the largest session-window total, not a lifetime sum of every shift.
© Patrick Stox LLC · CC BY 4.0 ·
세션 창: 가장 자주 잘못 설명되는 부분
CLS에서 가장 많이 틀리는 핵심은 페이지 수명 동안 일어난 모든 이동의 합이 아니라는 것입니다. 과거에는 합계였지만 June 2021에 바뀌었습니다.
현재 정의는 “CLS measures the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifecycle of a page.” (번역) 페이지 전체 수명에서 발생한 예기치 않은 이동 중 가장 큰 묶음을 측정합니다. 이 묶음인 세션 창은 “one or more individual layout shifts occur in rapid succession with less than 1-second in between each shift and a maximum of 5 seconds for the total window duration.” (번역) 각 이동 사이가 1초 미만이고 전체가 최대 5초인 연속 이동입니다. CLS는 합계나 평균이 아니라 가장 큰 창의 점수입니다.
Evidence for this claim CLS uses the largest session window of unexpected layout shifts, with gaps under one second and a maximum five-second window; recent discrete input can exclude a shift. Scope: Current CLS session-window and recent-input rules. Confidence: high · Verified: web.dev: Cumulative Layout Shift이전 합계 방식은 오래 살아 있는 페이지를 조용히 불리하게 만들었습니다. 단일 페이지 앱이나 무한 스크롤 피드는 각각의 이동이 작고 멀리 떨어져 있어도 오래 열려 있다는 이유만으로 점수가 누적됐습니다. Chrome Speed Metrics 팀은 페이지 지속 시간을 벌하지 않도록 최대 세션 창을 채택했고, 작은 보조 이동을 고쳤더니 평균이 오히려 나빠지는 역설을 피하려 평균 대신 최댓값을 선택했습니다. 변경 후 더 나빠진 오리진은 없었고 대부분은 같았으며 느린 UI와 무한 스크롤 페이지 일부가 개선됐습니다. 오래된 글에서 “모든 이동의 합”이라고 하면 현재 정의가 아닙니다.
포함되는 것과 제외되는 것
다음 세 가지 예외가 실제 점수 포함 여부를 결정합니다.
- 폴드 아래는 포함되지 않습니다. 현재 뷰포트에 보이는 콘텐츠 이동만 계산합니다. 사용자가 보지 않은 긴 페이지 아래쪽 이동은 영향이 없으므로 보통 뷰포트 안 문제를 먼저 고치는 편이 효율적입니다.
- 사용자 입력 뒤 500밀리초는 제외됩니다. “Layout shifts that occur within 500 milliseconds of user input will have the
hadRecentInputflag set, so they can be excluded from calculations.” (번역) 사용자 입력 직후 이동에는 최근 입력 플래그가 붙어 계산에서 빠집니다. Google은 상호작용과 가까워 관계가 분명한 이동은 일반적으로 괜찮다고 설명합니다. 아코디언이나 메뉴가 열리는 움직임은 예상된 것입니다. - 스크롤은 예외가 아닙니다. 500밀리초 제외는 탭·클릭·키 누름 같은 불연속 이벤트에만 적용됩니다. 스크롤·핀치 줌 같은 연속 제스처는 제외 창을 만들지 않으므로 스크롤 중 콘텐츠가 움직여도 계산됩니다.
기준값과 점수 출처
“To provide a good user experience, sites should strive to have a CLS score of 0.1 or less,” (번역) 좋은 사용자 경험을 위해 CLS는 영점일 이하를 목표로 해야 하며, “the 75th percentile of page loads, segmented across mobile and desktop devices.” (번역) 모바일과 데스크톱을 나눈 페이지 로드의 칠십오 번째 백분위수에서 측정합니다. 전체 구간은 다음과 같습니다.
Evidence for this claim CLS is good at 0.1 or less and poor above 0.25, assessed at the 75th percentile of page loads. Scope: Current web.dev CLS field thresholds. Confidence: high · Verified: web.dev: Cumulative Layout Shift- 좋음: ≤ 0,1
- 개선 필요: 0,1 – 0,25
- 나쁨: > 0,25
0,1 기준은 임의로 정한 것이 아닙니다. Google 연구에서는 “levels of shift from 0.15 and higher were consistently perceived as disruptive, while shifts of 0.1 and lower were noticeable but not excessively disruptive.” (번역) 0,15 이상은 일관되게 방해로 느껴졌고 0,1 이하는 눈에 띄지만 지나치게 방해되지는 않았습니다. 광고·소셜 같은 제삼자 임베드가 흔히 이동을 만들기 때문에 더 엄격한 기준은 실제 웹에서 비현실적이라는 점도 반영됐습니다.
“필드 데이터의 75th 백분위수”는 매우 중요하며 가장 큰 측정 함정으로 이어집니다.
실험실과 필드: 수치가 다른 이유
Lighthouse 같은 실험실 도구는 CLS를 거의 0,0으로 표시하지만 필드 데이터와 Google에서는 훨씬 나쁘게 나오는 일이 흔합니다. 어느 도구가 거짓말하는 것이 아니라 범위가 다릅니다. 실험실 실행은 짧고 스크립트화된 단일 로드라서 스크롤·클릭·장기 체류 없이 초기 로드 이동만 봅니다. 필드 데이터(CrUX)는 이동 기간 동안 다양한 사용자·기기·탐색의 실제 방문을 집계하며 CLS는 메뉴 열기, 스크롤 중 지연 로드, 늦은 광고 등 페이지 전체 수명을 대상으로 합니다. 짧은 실험실 실행은 구조적으로 대부분을 볼 수 없습니다.
실무 원칙은 특정 이동을 디버깅할 때는 실험실 데이터, 실제 점수를 알 때는 필드 데이터를 쓰는 것입니다. Google은 **Chrome User Experience Report(CrUX)**의 필드 데이터를 순위에 사용하며 PageSpeed Insights와 Search Console에 표시합니다. Lighthouse가 0,0이고 PageSpeed Insights가 0,18이면 실제 사용자를 반영하는 필드 값을 기준으로 삼고, 실제 방문처럼 상호작용해 실험실에서 재현하세요. iframe 이동은 CrUX에는 반영될 수 있지만 Lighthouse를 포함한 많은 도구에서 부모 문서 점수로 전파되지 않습니다. Layout Instability API 기반 RUM도 같은 사각지대가 있어 자체 모니터링으로는 더 나쁜 CrUX 수치를 완전히 설명하지 못할 수 있습니다.
일반적인 원인
제가 자주 보는 순서로 정리하면 다음과 같습니다.
- 치수가 없는 이미지와 동영상. 높이가 예약되지 않아 미디어가 로드될 때 아래 콘텐츠가 움직입니다.
- 공간을 확보하지 않은 광고, 임베드, iframe. 광고 크기는 동적이고 임베드는 로드 전에 높이를 알리지 않습니다.
- 기존 콘텐츠 위에 동적으로 삽입되는 콘텐츠. 쿠키 배너, 알림 바, 관련 위젯, 늦게 뜨는 프로모션이 화면 내용을 아래로 밉니다.
- 웹 글꼴(FOIT/FOUT). 사용자 글꼴과 대체 글꼴의 메트릭이 다르면 교체 순간 텍스트가 다시 흐릅니다.
- 레이아웃을 유발하는 속성의 애니메이션.
top,left,margin,box-shadow,box-sizing을 애니메이션하면 매 프레임 레이아웃을 다시 계산합니다.
해결법
해결책은 각 원인과 정확히 대응합니다.
- 이미지·동영상 — 공간을 예약하세요.
width와height속성으로 브라우저가 종횡비와 상자 크기를 계산하게 하고, 반응형에는img { height: auto; width: 100%; }for responsive behavior, or use the CSSaspect-ratio속성을 사용합니다. 대부분 사이트에서 효과가 가장 큰 CLS 수정입니다. - 광고·임베드·iframe — 역시 공간을 예약하세요. 컨테이너에
min-height나aspect-ratio를 쓰세요. Google Publisher Tag 지침은 “Setting a fixed height and width directly on the ad slotdivis the most effective way to do this.” (번역) 광고 슬롯 div에 고정 높이와 너비를 직접 지정하는 것이 가장 효과적이라고 합니다. 여러 크기 슬롯은 가장 큰 구성 크기를 예약하고 늦게 로드되는 콘텐츠는 가능한 한 폴드 아래로 내립니다. - 동적 콘텐츠 — 흐름 중간에 삽입하지 마세요. 최종 크기와 맞는 자리표시자를 확보하거나 콘텐츠를 오버레이하세요. 스켈레톤은 최종 치수와 정확히 같을 때만 도움이 됩니다. 몇 픽셀만 작아도 이동합니다. 예고 없는 삽입보다 “더 보기” 같은 사용자 작동 로드를 권합니다.
- 글꼴 — 메트릭을 맞추세요.
font-display: optional은 CLS 위험이 사실상 영인 유일한 값입니다.swap은 보이지 않는 텍스트를 줄이지만 교체 때 이동할 수 있습니다.size-adjust,ascent-override,descent-override,line-gap-override로 대체 글꼴을 웹 글꼴에 맞추고 중요 글꼴을 미리 로드하세요. - 애니메이션 —
transform만 사용하세요.top/left/margin대신transform의 이동·크기·회전을 사용하면 합성 단계에서 처리돼 레이아웃을 유발하지 않습니다.
순위에서 CLS의 비중
CLS는 Google 페이지 경험 신호의 입력 중 하나입니다. Google은 순위 시스템이 핵심 웹 바이탈을 사용한다고 말하지만 현재 검색 문서에는 정확한 CLS 가중치, 동률 결정 규칙, 순위 보장이 없습니다. 따라서 “동률 결정 요소” 같은 구체적 메커니즘은 문서화된 사실이 아니라 근사로 보세요. 제 일관된 조언은 “좋음” 구간에 들어가면 다음 문제로 이동하라는 것입니다. 0,08을 0,02로 낮춘다고 대부분의 사이트에서 의미 있는 순위·매출 상승이 생기지는 않으며 단일 점수만으로 수익 결과를 설명하기도 어렵습니다. CLS는 통과해야 할 기본 조건이지만 LCP, INP, 실제 콘텐츠보다 SEO 프로그램의 중심이 되어서는 안 됩니다.
혼란을 크게 줄이는 운영상 참고 사항 두 가지가 있습니다.
- CrUX는 약 28일 늦습니다. 이동 28일 창이므로 오늘 배포한 수정은 PageSpeed Insights나 Search Console에 완전히 반영되기까지 몇 주 걸립니다. 다음 날 숫자가 그대로여도 당황하지 마세요.
- 귀속된 요소가 근본 원인이 아닐 수 있습니다. Layout Shift Attribution API는 움직인 요소를 알려 주지만 web.dev는 “it’s possible that these elements are only indirectly related to the ‘root cause’ of layout instability.” (번역) 이 요소가 불안정성의 근본 원인과 간접적으로만 관련될 수 있다고 설명합니다. 움직인 텍스트는 위쪽의 크기 없는 이미지가 늦게 로드된 피해자일 수 있습니다. 이동 시작 시각과 같은 창에서 완료된 네트워크 요청, 이미지·글꼴 도착, 크기 변경, 클래스·스타일 변경을 맞춰 보고 귀속 노드는 증거가 아니라 단서로 취급하세요.
AI 요약
고급 버전을 압축하면 다음과 같습니다.
- CLS = 시각적 안정성이며 보이는 콘텐츠의 예기치 않은 움직임을 측정하는 핵심 웹 바이탈입니다. Largest Contentful Paint, Interaction to Next Paint와 함께 쓰입니다.
- 시간이 아닌 단위 없는 점수입니다. 0,05는 비율이지 50밀리초가 아닙니다.
- 이동별 공식:
impact fraction × distance fraction— 움직인 뷰포트 비율과 가장 큰 뷰포트 치수에 대한 이동 거리의 곱입니다. - 지표는 가장 큰 세션 창입니다. 이동 사이 ≤ 1 s, 전체 창 ≤ 5 s이며 평생 합계가 아닙니다. 장기 페이지를 벌하지 않도록 June 2021에 바뀌었고 평균보다 최댓값을 택했습니다.
- 기준(필드 데이터 75th 백분위수): 좋음 ≤ 0,1 · 개선 필요 ≤ 0,25 · 나쁨 > 0,25.
- 제외: 폴드 아래 이동과 불연속 입력 뒤 500밀리초 안의 이동은 제외되지만 스크롤은 제외되지 않습니다.
- 원인: 크기 없는 이미지·동영상·광고·iframe·임베드, 기존 콘텐츠 위 삽입, 웹 글꼴, 레이아웃 유발 속성 애니메이션.
- 해결:
width/height또는aspect-ratio, 동적 콘텐츠 공간 예약, 정확한 스켈레톤,font-display와size-adjust,transform전용 애니메이션. - 실험실 ≠ 필드. Lighthouse는 상호작용과 전체 수명을 실행하지 않아 거의 0이 나올 수 있습니다. Google은 필드 데이터(CrUX/PageSpeed Insights)를 사용하며 iframe 이동은 실험실과 RUM에서 부모 점수에 전파되지 않는 경우가 많습니다.
- 순위: 페이지 경험 내에서 Google 순위 시스템이 사용하는 입력이지만 문서화된 가중치나 동률 결정 규칙은 없습니다. “좋음”에 도달한 뒤 다음 문제로 이동하세요. CrUX는 약 28일 늦고 귀속된 요소가 근본 원인이 아닐 수 있습니다.
공식 문서
Google과 Chrome 팀의 1차 출처 문서입니다.
핵심 CLS 문서
- 누적 레이아웃 이동(CLS) — 캐노니컬 정의, 영향도 × 거리 공식, 세션 창, 기준,
hadRecentInput예외(Milica Mihajlija, Philip Walton). - 누적 레이아웃 이동 최적화 — 이미지, 광고·임베드, 삽입 콘텐츠, 글꼴, 애니메이션의 공식 원인·해결 가이드.
- 레이아웃 이동 디버깅 — Chrome DevTools, Layout Shift Regions 오버레이, LayoutShiftAttribution API로 이동을 찾는 법(Katie Hempenius, Barry Pollard).
배경과 측정
- 웹 도구에서 누적 레이아웃 이동의 진화 — June 2021에 전체 합계에서 최대 세션 창으로 바꾼 이유(Chrome Speed Metrics Team의 Annie Sullivan, Hongbo Song).
- 핵심 웹 바이탈 기준값 정의 방법 — 0,1 / 0,25 구간의 사용자 연구와 달성 가능성 데이터.
- 웹 바이탈 측정 시작하기 — 실험실과 필드 데이터, 실험실 CLS가 인위적으로 낮을 수 있는 이유.
- 글꼴 권장사항 — 글꼴 관련 CLS를 위한
font-display, 메트릭 재정의, 사전 로드.
광고와 검색
- 레이아웃 이동 최소화 — 광고 슬롯 공간 예약에 관한 Google Publisher Tag 지침.
- 핵심 웹 바이탈과 Google 검색결과 이해하기 — CLS를 포함한 CWV가 검색에 반영되는 방식.
출처 인용문
Google과 Chrome 팀의 공개 발언입니다. 각 링크는 출처의 인용 구절로 이동합니다.
Google — CLS란?
- “Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It’s an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts.” (번역) CLS는 예기치 않은 레이아웃 이동의 빈도를 수치화하는 안정적인 사용자 중심 시각 안정성 지표입니다. 인용문으로 이동
- “CLS measures the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifecycle of a page.” (번역) 페이지 전체 수명에서 발생한 예기치 않은 이동 중 가장 큰 점수 묶음을 측정합니다. 인용문으로 이동
Google — 공식
- “layout shift score = impact fraction * distance fraction” (번역) 레이아웃 이동 점수는 영향 비율과 거리 비율의 곱입니다. 인용문으로 이동
- “The impact fraction measures how unstable elements impact the viewport area between two frames.” (번역) 영향 비율은 두 프레임 사이에서 불안정 요소가 뷰포트에 미친 영향을 측정합니다. 인용문으로 이동
- “The distance fraction is the greatest horizontal or vertical distance any unstable element has moved in the frame divided by the viewport’s largest dimension (width or height, whichever is greater).” (번역) 거리 비율은 요소의 최대 이동 거리를 뷰포트의 가장 큰 치수로 나눈 값입니다. 인용문으로 이동
Google — 세션 창
- “A burst of layout shifts, known as a session window, is when one or more individual layout shifts occur in rapid succession with less than 1-second in between each shift and a maximum of 5 seconds for the total window duration.” (번역) 세션 창은 이동 사이가 일 초 미만이고 전체가 최대 오 초인 연속 레이아웃 이동 묶음입니다. 인용문으로 이동
Google — 기준과 사용자 입력
- “To provide a good user experience, sites should strive to have a CLS score of 0.1 or less… a good threshold to measure is the 75th percentile of page loads, segmented across mobile and desktop devices.” (번역) 좋은 사용자 경험을 위해 기기별 페이지 로드의 칠십오 번째 백분위수에서 CLS 영점일 이하를 목표로 해야 합니다. 인용문으로 이동
- “Layout shifts that occur within 500 milliseconds of user input will have the
hadRecentInputflag set, so they can be excluded from calculations.” (번역) 사용자 입력 직후 레이아웃 이동은 최근 입력 플래그가 설정되어 계산에서 제외될 수 있습니다. 인용문으로 이동 - “Layout shifts that occur in response to user interactions (such as clicking or tapping a link, pressing a button, or typing in a search box) are generally fine, as long as the shift occurs close enough to the interaction that the relationship is clear to the user.” (번역) 상호작용에 가깝게 발생해 관계가 분명한 이동은 일반적으로 괜찮습니다. 인용문으로 이동
Google — 기준 선택 방식
- “levels of shift from 0.15 and higher were consistently perceived as disruptive, while shifts of 0.1 and lower were noticeable but not excessively disruptive.” (번역) 영점일오 이상은 일관되게 방해로 인식됐고 영점일 이하는 눈에 띄지만 지나치게 방해되지는 않았습니다. 인용문으로 이동
Google — 광고 슬롯 공간 확보
- “Setting a fixed height and width directly on the ad slot
divis the most effective way to do this.” (번역) 광고 슬롯 div에 고정 높이와 너비를 직접 지정하는 것이 가장 효과적입니다. 인용문으로 이동
Google — 귀속 요소와 근본 원인
- “elements listed as sources are the elements that shifted during the layout shift. However, it’s possible that these elements are only indirectly related to the ‘root cause’ of layout instability.” (번역) 출처로 표시된 요소는 실제로 움직인 요소지만 불안정성의 근본 원인과는 간접적으로만 관련될 수 있습니다. 인용문으로 이동
CLS 원인 → 해결 체크리스트
위에서 아래로 진행하세요. 처음 두 항목이 실제 CLS 대부분을 해결합니다.
- 모든
<img>와<video>에width+height또는 CSSaspect-ratio가 있으며 반응형 레이아웃에는img { height: auto; width: 100%; }를 사용합니다. - 광고 슬롯, iframe, 임베드가 공간을 예약합니다.
min-height/aspect-ratio를 쓰고 여러 크기 광고 슬롯은 가장 큰 구성 크기를 확보합니다. - 가능한 경우 늦게 로드되는 콘텐츠를 폴드 아래에 배치해 남은 이동이 점수에 포함되지 않게 합니다.
- 삽입 콘텐츠(쿠키 배너, 프로모션, 관련 위젯)는 오버레이하거나 미리 공간을 확보하며 기존 콘텐츠 위에 끼워 넣지 않습니다.
- 스켈레톤 자리표시자는 최종 콘텐츠와 치수가 정확히 같습니다. 몇 픽셀 차이도 이동을 만듭니다.
- **웹 글꼴은 허용되는 곳에서
font-display: optional**을 쓰거나swap과size-adjust/ascent-override로 대체 글꼴 메트릭을 맞추고 중요 글꼴을 미리 로드합니다. - 애니메이션은
transform만 사용하며top,left,margin,box-shadow,box-sizing은 사용하지 않습니다. - Lighthouse뿐 아니라 PageSpeed Insights / Search Console / CrUX의 필드 데이터를 확인했습니다.
- 초기 로드뿐 아니라 스크롤, 메뉴 열기, 지연 로드를 실행해 상호작용 중 이동을 재현했습니다.
- 실험실 도구가 부모 점수에 전파하지 못할 수 있는 광고·iframe 이동을 필드에서 확인했습니다.
CLS 치트 시트
수치
| 구간 | CLS(필드 75th 백분위수) |
|---|---|
| 좋음 | ≤ 0,1 |
| 개선 필요 | > 0,1~0,25 |
| 나쁨 | > 0,25 |
한 줄 정의
- 이동별
layout shift score = impact fraction × distance fraction. - CLS = 가장 큰 세션 창. 이동 사이 ≤ 1 s, 전체 ≤ 5 s이며 페이지 수명 전체 합계가 아닙니다(pre-June-2021 방식).
- 시간 아닌 단위 없는 점수입니다.
제외 항목
- 현재 뷰포트 밖인 폴드 아래 이동.
- 불연속 입력(탭·클릭·키 누름) 뒤 500밀리초 이내 이동 —
hadRecentInput. - 제외되지 않음: 스크롤이나 핀치 같은 연속 제스처 중 이동.
원인 → 해결
| 원인 | 해결 |
|---|---|
| 치수 없는 이미지·동영상 | width + height 속성 또는 CSS aspect-ratio |
| 광고 / iframe / 임베드 | min-height / aspect-ratio로 공간 확보, 광고 슬롯 div에 고정 크기 |
| 폴드 위 삽입 콘텐츠 | 오버레이하거나 공간을 미리 확보하고 사용자 행동으로 실행 |
| 웹 글꼴(FOIT/FOUT) | font-display: optional/swap + size-adjust 메트릭 재정의, 사전 로드 |
| 레이아웃 유발 애니메이션 | top/left/margin 대신 transform 사용 |
측정 시 주의점
- Lighthouse(실험실)는 약 0을 표시할 수 있습니다. 상호작용이나 전체 수명을 실행하지 않습니다. Google은 CrUX / PageSpeed Insights 필드 데이터를 순위에 사용합니다.
- CrUX는 약 28일 늦습니다. 수정 반영에는 몇 주가 걸립니다.
- iframe 이동은 실험실 도구에서 부모 점수로 전파되지 않는 경우가 많습니다.
- 귀속 요소는 움직인 요소이지 반드시 근본 원인은 아닙니다.
CLS 측정·디버깅 도구
필드 데이터(Google이 순위에 사용)
- PageSpeed Insights — 페이지·오리진 수준 CrUX 필드 CLS와 Lighthouse 실험실 실행을 함께 보여 줘 차이를 빠르게 확인합니다.
- Search Console — 핵심 웹 바이탈 보고서 — 사이트 전체 URL 그룹별 필드 CLS와 상태를 표시합니다.
- CrUX(Chrome User Experience Report) — 기반 필드 데이터셋이며 CrUX 대시보드와 BigQuery에서 이력을 볼 수 있습니다.
실험실 데이터(디버깅용)
- Chrome DevTools — Performance 패널 — 트레이스를 기록하고 Layout Shifts 트랙에서 이동 요소와 점수를 봅니다. Live Metrics는 상호작용 중 CLS를 실시간 갱신합니다.
- Layout Shift Regions 오버레이 — DevTools → Settings → More tools → Rendering → Layout Shift Regions에서 켜면 다시 로드할 때 이동 영역이 깜박입니다.
- Lighthouse — 빠른 실험실 CLS이지만 초기 로드 이동만 포착합니다.
- WebPageTest — 필름스트립과 트레이스를 포함한 실험실 CLS.
RUM(자체 필드 데이터)
- web-vitals JavaScript 라이브러리 —
onCLS()로 실제 방문자의 CLS를 보고합니다(~2 KB). - PerformanceObserver (
layout-shift) — 라이브러리가 감싸는 원시 API이며 LayoutShiftAttributionsources에서 이동 요소를 확인합니다.
도구 자체의 점수
이 페이지의 지표를 실제로 적용한 사례입니다. 잘 알려진 페이지 속도·모니터링 서비스의 실제 사용자 모바일 CLS를 Chrome UX Report 필드 데이터로 비교했습니다.
어떤 CLS 수정을 먼저 해야 할까요?
What is causing the visible layout shift?
실제 문제를 숨기는 CLS 실수
깨끗한 Lighthouse 실행을 증거로 보기
Lighthouse는 동의 배너, 광고, 상호작용 기반 이동이 발생하기 전에 끝날 수 있습니다. 실험실 실행은 디버깅에 쓰되 CrUX나 자체 실제 사용자 모니터링을 확인한 뒤 해결됐다고 판단하세요.
DevTools가 움직였다고 표시한 요소만 수정하기
움직인 요소는 피해자인 경우가 많습니다. 위쪽에서 늦게 로드된 항목이 원인일 수 있으므로 트레이스를 재생하고 움직임 직전에 삽입되거나 크기가 바뀐 요소를 확인하세요.
추정한 고정 높이로 공간 확보하기
반응형 콘텐츠가 더 높거나 낮으면 고정 자리표시자가 두 번째 이동을 만들 수 있습니다. 비율을 아는 콘텐츠에는 고유 치수나 aspect-ratio를 사용하세요.
레이아웃 속성 애니메이션
top, left, 여백을 바꾸면 주변 콘텐츠도 움직일 수 있습니다. 문서 흐름을 바꿀 필요가 없는 효과에는 transform을 사용하세요.
증상별 CLS 진단
필드 CLS는 나쁘지만 실험실 점수는 거의 영
가능한 원인: 긴 세션의 상호작용 뒤 또는 일부 사용자에게만 이동이 발생합니다. 해결: 실제 여정을 Performance 패널로 기록하고 RUM에 web-vitals 귀속 정보를 추가합니다. 확인: 문제 상호작용과 이동 요소가 트레이스나 RUM 기록에 나타납니다.
사용자 글꼴이 도착할 때 텍스트가 움직임
가능한 원인: 대체 글꼴과 웹 글꼴의 메트릭이 다릅니다. 해결: 필요한 경우 중요 글꼴만 미리 로드하고 글꼴 메트릭 재정의로 대체 글꼴을 맞춥니다. 확인: 캐시를 끄고 재생했을 때 Layout Shifts 트랙에 교체 이동이 더 이상 기록되지 않습니다.
배너나 광고가 페이지를 아래로 밈
가능한 원인: 콘텐츠 도착 전 슬롯 치수가 예약되지 않았습니다. 해결: 안정적인 컨테이너를 확보하거나 보이는 콘텐츠를 밀지 않는 위치에 메시지를 배치합니다. 확인: 네트워크를 제한해도 슬롯 면적이 유지됩니다.
테스트에서는 개선됐지만 PageSpeed Insights에는 반영되지 않음
가능한 원인: CrUX는 즉시 배포를 확인하는 도구가 아니라 이동 필드 데이터셋입니다. 해결: 실험실과 RUM에서 먼저 검증한 뒤 필드 창이 교체되길 기다립니다. 확인: 공개 CrUX 집계보다 먼저 자체 출시 후 필드 분포가 개선됩니다.
브라우저에서 레이아웃 이동 포착하기
문제를 재현하기 전에 DevTools Console에 붙여 넣으세요. 최근 사용자 입력과 연결된 이동을 제외하고 점수와 브라우저가 귀속한 요소를 출력합니다.
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.hadRecentInput) continue;
console.table({
value: entry.value,
time: Math.round(entry.startTime),
elements: entry.sources?.map((source) => source.node),
});
}
});
observer.observe({ type: 'layout-shift', buffered: true });귀속 노드는 단서이지 원인의 자동 증거가 아닙니다. 같은 트레이스에서 해당 시각의 네트워크 요청, 글꼴 로드, DOM 삽입과 비교하세요.
CLS 수정 효과 입증하기
공간 예약 테스트
테스트: 캐시를 끄고 연결을 제한한 뒤 다시 로드하면서 Performance 패널 Layout Shifts 트랙을 기록합니다. 예상 결과: 미디어나 임베드가 로드 전후 같은 면적을 유지합니다. 실패 해석: 컨테이너 치수가 여전히 늦게 도착하는 콘텐츠에 의존합니다. 관찰 기간: 트레이스에서 즉시. 롤백 조건: 새 자리표시자가 잘림, 과도한 빈 공간, 반응형 분기점의 새 이동을 만듭니다.
글꼴 교체 테스트
테스트: 캐시를 끄고 텍스트와 Layout Shifts 트랙을 보며 다시 로드합니다. 예상 결과: 대체 글꼴에서 웹 글꼴로 바뀔 때 측정 가능한 이동이 없습니다. 실패 해석: 메트릭이 여전히 다르거나 중요 글꼴이 너무 늦게 도착합니다. 관찰 기간: 반복 실험실 실행에서 즉시. 롤백 조건: 텍스트가 더 오래 숨겨지거나 최종 타이포그래피가 크게 틀어집니다.
필드 확인
테스트: 변경한 템플릿의 출시 후 onCLS() 데이터를 이전 기준선과 비교한 뒤 CrUX를 봅니다. 예상 결과: 주요 여정의 나쁜 꼬리가 늘지 않으면서 실제 사용자 p75가 개선됩니다. 실패 해석: 늦거나 상호작용 기반인 다른 원인이 남았습니다. 관찰 기간: 트래픽이 들어오는 동안 RUM, 28일 이동 창 동안 CrUX. 롤백 조건: 출시 뒤 CLS 또는 사용자 상호작용 오류가 지속적으로 악화됩니다.
추적할 만한 CLS 지표
실제 사용자 CLS p75
지표: 중요한 템플릿·기기 유형별 75th 백분위수 CLS. 의미: 대부분 방문이 시각 안정성 목표를 충족하는지 보여 줍니다. 수집: CrUX, PageSpeed Insights, web-vitals RUM. 기준/현실적 범위: 0,1 이하는 좋음, 0,1–0,25는 개선 필요, 0,25 초과는 나쁨. 주기: RUM에서 출시를 관찰하고 이동 필드 추세를 매월 검토합니다.
나쁜 방문 비율
지표: CLS가 0,25를 넘는 실제 방문 비율. 의미: 괜찮은 p75 뒤에 해로운 꼬리가 숨었는지 보여 줍니다. 수집: onCLS() 이벤트를 템플릿과 여정별로 구간화합니다. 기준/현실적 범위: 사이트 기준선을 만들고 나쁨 구간을 줄이되 트래픽 구성 때문에 보편 목표는 오해를 부릅니다. 주기: 트래픽이 많은 템플릿은 매주, 레이아웃 출시 후 검토합니다.
원인별 이동 귀속
지표: 요소나 컴포넌트별 레이아웃 이동 항목. 의미: 반복 구현 중 불안정성을 가장 많이 만드는 대상을 찾습니다. 수집: web-vitals 귀속 빌드 또는 PerformanceObserver. 기준/현실적 범위: 보편 범위는 없으며 총 영향과 영향받은 방문으로 컴포넌트를 비교합니다. 주기: 템플릿·컴포넌트 출시 때마다 검토합니다.
시간을 들일 가치가 있는 자료
공식 심층 자료
- 누적 레이아웃 이동(CLS) — 캐노니컬 참고 문서.
- 누적 레이아웃 이동 최적화 — 공식 수정 가이드.
- 레이아웃 이동 디버깅 — DevTools 작업 흐름.
- 웹 도구에서 누적 레이아웃 이동의 진화 — 이를 만든 팀이 설명하는 June 2021 세션 창 변경.
실무자 자료
- 누적 레이아웃 이동(CLS) 문제를 해결하는 방법 — Smashing Magazine의 Barry Pollard가 글꼴 설명자와 “움직인 요소가 근본 원인은 아니다”라는 문제를 깊이 다룹니다.
- 실전 누적 레이아웃 이동 — Nic Jansma의 iframe 귀속 공백, 5개 요소 귀속 표본, 도구 간 불일치를 다룬 측정 안내.
- 누적 레이아웃 이동 측정·최적화 — DebugBear.
- 거의 완전한 누적 레이아웃 이동 가이드 — SPA 탐색 이동과 연속 제스처 예외를 포함한 Jess Peck의 엣지 케이스 설명.
- 레이아웃 이동 원인 — CLS culprit 패널의 Chrome DevTools 문서.
- 누적 레이아웃 이동(CLS) 수정 방법 — 갤러리 이미지, 지연 위젯, 쿠키 배너 등 WordPress 원인을 다루는 Kinsta 안내.
- Layout Instability API — 사용자 RUM과 정확한
hadRecentInput의미에 필요한 WICG 사양.
제 작업에서의 위치
- CLS는 제 핵심 웹 바이탈 글 전반에서 “기본 통과 조건”으로 다룹니다. 추적하고 좋음 구간에 들어간 뒤 LCP, INP, 콘텐츠와 균형을 맞추세요. Google은 정확한 CLS 가중치나 동률 결정 규칙을 공개하지 않으므로 관찰할 입력이지 게임 전체가 아닙니다.
인용할 만한 통계
- 0,1 기준은 인지 연구에 근거합니다. Google 사용자 연구에서 0,15 이상은 일관되게 방해로 인식됐고 0,1 이하는 눈에 띄지만 지나치게 방해되지는 않았습니다. 출처
- CLS는 통과하기 가장 쉬운 핵심 웹 바이탈입니다. 제 엔터프라이즈 감사에서는 대다수 사이트가 CLS 기준을 넘고(흔히 ~80%+) 세 지표를 모두 통과하는 곳은 절반을 조금 넘습니다. 병목은 대개 CLS가 아닙니다.
- June 2021 변경은 도움이 됐고 해를 끼치지 않았습니다. 가장 큰 세션 창으로 바꾼 뒤 더 나빠진 오리진은 없었고 대부분은 같았으며 무한 스크롤·느린 UI 일부가 개선됐습니다. 출처
- 치수 없는 미디어는 여전히 흔합니다. Web Almanac 업계 크롤에서는 명시적 치수 없이 이미지를 제공하는 페이지 비중이 계속 높습니다. 가장 흔하면서 고치기 쉬운 CLS 원인입니다.
- 전 세계 웹사이트의 72%가 이제 좋은 CLS를 달성합니다(2025 Web Almanac / HTTP Archive 데이터). CLS는 통과하기 가장 쉬운 핵심 웹 바이탈이지만 모바일 페이지의 62%는 여전히 명시적 치수가 없는 이미지를 하나 이상 제공합니다. 출처: HTTP Archive / Web Almanac
- 비즈니스 영향: Rakuten 24는 CLS가 높은 사용자보다 낮은 사용자에서 방문자당 매출이 53,37% 증가했다고 보고했습니다. 자주 인용되는 사례 연구일 뿐 다른 사이트에서 특정 CLS 수치가 특정 결과를 만든다는 증거는 아닙니다. 출처: corewebvitals.io 사례 연구
동영상
- Google 검색 센터 / Chrome 개발자 채널(YouTube) — Layout Shifts 트랙과 Layout Shift Regions 오버레이 DevTools 시연을 포함한 핵심 웹 바이탈 및 Debug layout shifts 안내. 채널
테스트: 누적 레이아웃 이동
시각적 불안정성 측정과 해결에 관한 다섯 문제입니다. 답을 고른 뒤 확인하세요.
변경 내역
2026년 8월 9일에 업데이트됨.
편집 요약 및 기록된 변경 세부 정보입니다.변경 세부 정보
-
변경 세부 정보는 현재 영어로 제공됩니다.
전체 비교를 사용할 수 없음 — 이 수정에 대한 이전 스냅샷이 보관되지 않았습니다.
2026년 7월 17일에 업데이트됨.
편집 요약 및 기록된 변경 세부 정보입니다.변경 세부 정보
-
변경 세부 정보는 현재 영어로 제공됩니다.
-
변경 세부 정보는 현재 영어로 제공됩니다.
-
변경 세부 정보는 현재 영어로 제공됩니다.
전체 비교를 사용할 수 없음 — 이 수정에 대한 이전 스냅샷이 보관되지 않았습니다.