Cumulative Layout Shift (CLS) 문제 식별 및 수정

RUM 데이터, Chrome DevTools 및 타겟 CSS 및 HTML 수정을 사용하여 모든 Cumulative Layout Shift 문제를 찾고 수정하는 방법을 알아보세요

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-27

Cumulative Layout Shift (CLS) 문제 찾기 및 수정

이 페이지는 당사의 Cumulative Layout Shift (CLS) 시리즈의 일부입니다. CLS는 예상치 못한 콘텐츠 이동을 추적하여 페이지의 시각적 안정성을 측정합니다. 좋은 CLS 점수는 0.1 미만이며, 0.25를 초과하는 점수는 나쁨입니다. CLS가 처음이라면 수식, 임계값 및 세션 창 메커니즘에 대해 CLS 허브 페이지에서 시작하세요.

CLS는 가장 실적이 좋은 Core Web Vitals입니다. 2025 Web Almanac에 따르면, 전 세계 웹사이트의 72%가 CLS를 통과합니다. 아주 좋아 보이지만, 대부분의 개발자가 자신의 기기에서는 CLS 문제를 전혀 보지 못한다는 사실을 깨달을 때까지만 그렇습니다. 느린 연결을 사용하는 최초 방문자에게 레이아웃 이동이 발생하며, 캐시가 준비된 상태로 DevTools를 확인할 때쯤이면 모든 것이 정상으로 보입니다. 이것이 바로 CLS 디버깅을 까다롭게 만드는 이유입니다.

이 가이드는 제가 CLS 컨설팅 시 사용하는 정확한 단계별 프로세스를 기반으로 합니다. 먼저 CrUX 및 RUM 데이터를 확인하고, Chrome에서 검증한 다음 수정 사항을 작성합니다.

마지막 검토: Arjen Karel, 2026년 3월

CLS 팁: CLS는 누적 합계가 아닌 세션 창 단위로 측정됩니다. 브라우저는 레이아웃 이동을 세션(최대 5초, 이동 간 1초 간격)으로 그룹화하며, CLS 점수는 가장 나쁜 세션의 점수입니다. 페이지 로드 중 한 번의 집중적인 이동이 발생하면, 나머지 방문 기간 동안 완벽하게 안정적이더라도 CLS를 통과하지 못할 수 있습니다.

1단계: Search Console에서 CLS 확인

아무것도 변경하기 전에 실제로 CLS 문제가 있는지 확인하세요. Google Search Console에 로그인하여 Core Web Vitals로 이동한 다음 모바일과 데스크톱 모두 확인합니다.

Google이 "CLS 문제: 0.25 초과" 또는 "CLS 문제: 0.1 초과"로 URL에 플래그를 지정하는 경우, 실제 사용자가 사이트에서 레이아웃 이동을 겪고 있다는 것을 Chrome User Experience (CrUX) Report를 통해 확인한 것입니다.

원시 컴퓨팅 성능과 네트워크 속도가 중요한 LCP 및 INP와 달리, CLS 문제는 기기나 화면 크기에 따라 다를 수 있습니다. 크기가 지정되지 않은 이미지, 글꼴 교체, 삽입된 콘텐츠 등 유사한 문제가 모바일과 데스크톱에 영향을 미칠 때, 화면 크기 때문에 데스크톱이 훨씬 더 큰 CLS 값을 보고할 수 있습니다(보이는 뷰포트의 더 큰 부분이 영향을 받을 수 있기 때문입니다). Search Console은 URL을 그룹화하므로 어떤 페이지 유형이 영향을 받는지 알려주지만 어떤 요소가 이동하는지는 알려주지 않습니다. 이를 위해서는 RUM이 필요합니다.

Core Web Vitals CLS 문제를 보여주는 Google Search Console.

2단계: RUM 데이터를 통해 CLS 문제 식별

Search Console은 문제의 존재를 확인해주지만 해결에 필요한 정보는 거의 제공하지 않습니다. 어떤 요소가 어떤 페이지에서 어떤 조건 하에 이동하는지 찾아야 합니다. 이를 위해서는 RUM 도구가 필요합니다.

저는 바로 이러한 질문에 답하기 위해 CoreDash를 구축했습니다. 스크립트 태그 하나를 추가하면 모든 실제 방문자로부터 CLS 속성 데이터를 수집하기 시작합니다. CLS 디버깅의 핵심 데이터 포인트는 이동하는 요소, 즉 실제로 이동한 DOM 노드입니다. 이 정보 없이는 눈을 감고 디버깅하는 것과 같습니다.

이동하는 요소 찾기

요소별로 그룹화된 CLS 데이터를 살펴보는 것으로 시작하세요. CoreDash에서 CLS 페이지로 이동하여 "CLS by Element"로 정렬된 데이터 테이블을 봅니다. 이는 모든 방문자에게서 가장 많은 레이아웃 이동을 유발하는 요소를 보여줍니다. 가장 나쁜 요소를 클릭하여 해당 요소가 이동한 페이지의 모든 지표를 필터링하세요.

이동하는 요소별로 분류된 CLS 점수를 보여주는 CoreDash.

영향을 받는 페이지 찾기

가장 큰 영향을 미치는 이동 요소로 필터링한 후 URL 분석을 확인합니다. CLS 문제는 사이트 전체 또는 템플릿 전체에 걸쳐 발생할 수 있습니다. 이제 CLS가 이미지 갤러리가 있는 제품 페이지, 광고 슬롯이 있는 블로그 게시물, 히어로 애니메이션이 있는 랜딩 페이지 등 특정 페이지 유형에 집중되어 있는지 알 수 있습니다. 어떤 페이지가 실패하는지 알면 어디에 집중해야 할지 알 수 있습니다.

신규 방문자와 재방문자 비교

이것은 제가 수행하는 또 다른 빠른 확인 사항이며 대부분의 사람들이 생각하는 것보다 더 중요합니다. 글꼴 교체 CLS는 글꼴이 캐시되지 않았을 때만 발생합니다. width: auto로 인한 이미지 CLS는 이미지가 브라우저 캐시에 없을 때만 발생합니다. 처음 방문하는 사용자의 CLS가 훨씬 더 나쁘다면, 개발자인 여러분이 캐시를 비활성화하지 않는 한 자신의 기기에서는 결코 볼 수 없는 캐싱 의존적인 이동 문제를 다루고 있는 것입니다(팁: 항상 Chrome 캐시를 비활성화하세요... 하지만 그건 나중에 다룰 이야기입니다).

기기 유형 및 뷰포트 크기 확인

CLS는 일반적으로 LCP 및 INP와는 다른 모바일/데스크톱 패턴을 보입니다. 반응형 레이아웃은 특정 뷰포트 너비와 높이에서만 나타나는 이동을 유발할 수 있습니다. 데스크톱에서 문제를 일으킨 광고 슬롯이 모바일 뷰포트에는 아예 없을 수도 있습니다. 탐색 메뉴가 더 작은 중단점에서는 다르게 애니메이션될 수 있습니다. 기기 유형별로 CLS 데이터를 그룹화하여 어디서 발생하는지 파악하세요.

3단계: Chrome으로 CLS 디버깅

RUM 데이터를 통해 어떤 요소가 왜 이동하는지 알았습니다. 이제 로컬에서 문제를 재현하고 원인을 찾으세요.

Core Web Vitals Visualizer 사용

레이아웃 이동을 가장 빨리 보는 방법은 Core Web Vitals Visualizer Chrome 확장 프로그램을 사용하는 것입니다. 페이지를 로드하고 확장 프로그램 아이콘을 클릭한 다음 새로 고침합니다. 모든 레이아웃 이동이 색상이 지정된 오버레이로 강조 표시되어 무엇이 얼마나 이동했는지 정확히 보여줍니다. 즉각적인 시각적 답을 주기 때문에 성능 패널을 열기 전 첫 번째 단계로 이 방법을 사용합니다.

페이지에 레이아웃 이동이 강조 표시된 Core Web Vitals Visualizer.

Chrome에서 조건을 재현하고 네트워크 스크린샷 확인

CLS 문제는 캐시가 준비된 상태에서는 종종 보이지 않습니다. DevTools를 열고 네트워크 탭에서 캐시를 비활성화한 다음 연결을 "Slow 4G"로 제한합니다(제가 가장 좋아하는 방법으로, 경쟁 조건으로 인한 CLS를 보여줍니다). 이제 톱니바퀴 아이콘을 클릭하고 (DevTools가 열려 있는 동안) 캐싱을 비활성화합니다. 이는 처음 방문하는 사용자가 겪는 조건을 시뮬레이션합니다. 네트워크 탭으로 이동하여 스크린샷을 활성화합니다. 이제 페이지를 새로 고침하고 이동을 관찰하세요.

Chrome 성능 패널 사용

대부분의 레이아웃 이동은 방법을 알면 쉽게 발견할 수 있지만 때로는 놓칠 수 있습니다. 이럴 때 Chrome DevTools(Ctrl+Shift+I)를 열고 상세한 디버깅을 위해 성능 패널로 이동해야 합니다. Ctrl+Shift+E를 눌러 새로 고침하고 기록합니다. 페이지가 로드된 후 위아래로 몇 번 스크롤합니다. 기록을 중지합니다.

"Layout Shifts" 트랙을 찾습니다. 각 이동은 색상이 지정된 블록으로 나타납니다. 이동을 클릭하여 다음을 확인합니다.

  • 이동하는 노드: 이동한 DOM 요소
  • 이동 점수: 영향 비율에 거리 비율을 곱한 값
  • hadRecentInput: 사용자 입력이 이동보다 먼저 발생했는지 여부(클릭 및 탭에는 500ms의 유예 기간이 있지만 스크롤에는 없음)

이동이 언제 발생하는지 주의 깊게 살펴보세요. 페이지 로드 중 발생하는 이동은 크기가 지정되지 않은 이미지, 글꼴 교체 또는 CSS 전환을 나타냅니다. 스크롤 중 발생하는 이동은 레이아웃 속성을 사용하는 스크롤 트리거 애니메이션을 나타냅니다.

스크롤 중 레이아웃 이동 항목을 보여주는 Chrome 성능 패널.

빠른 테스트: 모든 전환 비활성화

레이아웃 속성을 애니메이션화하는 CSS 전환은 로딩 단계에서만 이동하고 재현하기 어렵기 때문에 교활한 CLS 원인입니다. 이 스니펫을 콘솔에 붙여넣고 캐시를 비활성화한 상태에서 페이지를 강제 새로 고침한 다음 CLS를 비교해 보세요.

document.head.insertAdjacentHTML('beforeend',
  '<style>*{transition-property:none!important}</style>');

전환을 비활성화한 후 CLS가 떨어지면 원인을 찾은 것입니다. CSS 전환 디버깅 가이드를 사용하여 원인이 되는 특정 전환을 찾으세요.

Layout Instability API로 CLS 측정

Layout Instability API를 사용하면 JavaScript의 모든 레이아웃 이동에 직접 액세스할 수 있습니다. 이것은 RUM 도구가 내부적으로 사용하는 것과 동일한 API입니다.

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log('Layout shift:', {
        value: entry.value,
        sources: entry.sources?.map(s => ({
          node: s.node,
          previousRect: s.previousRect,
          currentRect: s.currentRect
        }))
      });
    }
  }
});
observer.observe({ type: 'layout-shift', buffered: true });

sources 배열은 어떤 요소가 이동했는지 보여줍니다. hadRecentInput은 클릭 및 탭에서 예상되는 이동을 필터링합니다. 프로덕션 측정의 경우 CoreDash 또는 다른 RUM 도구를 사용하세요.

4단계: CLS 문제 수정

어떤 요소가 왜 이동하는지 알게 되었습니다. 이제 수정할 시간입니다. CLS에는 LCP와 같은 순차적인 단계가 없습니다. 대신 레이아웃 이동에는 뚜렷한 원인 범주가 있습니다. 감사 중 제가 마주치는 빈도 순으로 가장 일반적인 원인들은 다음과 같습니다.

1. 크기가 지정되지 않은 이미지, 비디오 및 Iframe

이것은 웹에서 CLS의 가장 큰 원인입니다. 2025 Web Almanac에 따르면 모바일 페이지의 62%가 최소한 하나의 크기가 지정되지 않은 이미지를 가지고 있습니다. 해결책: <img>, <video><iframe> 태그에 항상 widthheight 속성을 포함하세요.

<img src="hero.jpg" width="800" height="450" alt="Description">

<style>
img {
    height: auto;
    max-width: 100%;
}
</style>

CSS의 width: auto에 주의하세요. 이 단일 선언은 브라우저의 종횡비 계산을 재정의하며, HTML에서 너비와 높이를 설정했더라도 레이아웃 이동을 유발합니다. 저는 수십 개의 사이트에서 이것을 보았습니다. 개발자가 마크업에서 모든 것을 올바르게 수행했지만 img { width: auto; height: auto; max-width: 100%; }와 같은 전역 CSS 규칙이 모든 것을 무효화했습니다. 전체 설명은 자동 크기 조정 이미지로 인한 레이아웃 이동 수정을 참조하세요. 모든 이미지 및 미디어 CLS 원인(비디오, iframe, 아트 디렉션, 반응형 이미지, 지연 로딩, 자리 표시자)을 다루는 전체 가이드는 이미지 및 미디어가 레이아웃 이동을 일으키는 방법을 참조하세요.

2. 웹 글꼴 교체

웹 글꼴이 로드되고 대체 글꼴을 교체할 때 크기 차이로 인해 레이아웃 이동이 발생합니다. 2025 Web Almanac에 따르면 11%의 페이지만 웹 글꼴을 미리 로드합니다. 즉, 대다수의 사이트가 글꼴 교체 CLS에 취약하다는 것을 의미합니다.

해결책은 두 부분으로 나뉩니다. 첫째, 메트릭 재정의를 사용하여 대체 글꼴을 웹 글꼴 치수와 일치시킵니다.

<style>
@font-face {
    font-family: 'My Font Fallback';
    src: local('Arial');
    size-adjust: 105.2%;
    ascent-override: 93%;
    descent-override: 24%;
    line-gap-override: 0%;
}

@font-face {
    font-family: 'My Font';
    src: url('/fonts/myfont.woff2') format('woff2');
    font-display: swap;
}

body {
    font-family: 'My Font', 'My Font Fallback', sans-serif;
}
</style>

대체 글꼴 생성기(Fallback Font Generator)를 사용하여 글꼴 페어링에 대한 올바른 재정의 값을 계산하세요. 둘째, 전송 속도를 높이세요: 글꼴을 직접 호스팅하고, 중요한 글꼴 파일을 미리 로드하며, 서브세팅이 적용된 WOFF2를 사용하세요. 전체 전략은 반응형 웹 글꼴 로딩웹 글꼴 로드 중 텍스트가 계속 표시되도록 보장을 참조하세요.

3. CSS 애니메이션 및 전환

2025 Web Almanac에 따르면 모바일 페이지의 40%가 합성되지 않은(non-composited) 애니메이션을 실행합니다. 이들은 매 프레임마다 레이아웃 재계산을 트리거하는 width, height, top, left, marginpadding과 같은 속성을 애니메이션화합니다.

가장 흔한 원인은 transition: all입니다. 개발자가 transition: all .3s ease를 작성하면 레이아웃 속성을 포함한 모든 속성 변경이 애니메이션화됩니다. 페이지 로드 중, 스타일이 지정되지 않은 상태에서 스타일이 지정된 상태로 전환되는 요소는 간헐적으로 발생하며 일관되게 재현하기 거의 불가능한 레이아웃 이동을 생성합니다. 저는 이 패턴을 항상 봅니다.

해결책: 레이아웃을 트리거하는 속성을 합성된 속성으로 교체합니다.

  • top/bottom 대신 transform: translateY() 사용
  • left/right 대신 transform: translateX() 사용
  • width/height 대신 transform: scale() 사용
  • 높이 변경과 결합된 visibility 대신 opacity 사용
  • 절대 transition: all을 사용하지 마세요. transition: background-color .2s ease와 같이 정확한 속성을 지정하세요.

transformopacity는 전적으로 합성기 스레드에서 실행되며 레이아웃을 절대 트리거하지 않습니다. 전체 디버깅 프로세스는 CSS 전환으로 인한 레이아웃 이동을 참조하세요.

4. 광고, 임베드 및 동적으로 삽입된 콘텐츠

광고는 늦게 로드되어 콘텐츠를 아래로 밀어냅니다. 쿠키 동의 배너가 나타나서 페이지를 이동시킵니다. AJAX 요청은 먼저 공간을 확보하지 않고 새로운 콘텐츠를 삽입합니다. 이것들은 모두 동일한 문제입니다. 렌더링 시점에 브라우저가 알지 못했던 무언가가 페이지에 나타나는 것입니다.

이 모든 것들에 대한 해결책은 공간을 확보하는 것입니다. 광고 슬롯의 경우 예상 광고 크기와 일치하는 min-height를 설정하세요.

<style>
.ad-slot {
    min-height: 250px;
    contain: layout style;
}
@media (min-width: 600px) {
    .ad-slot { min-height: 90px; }
}
</style>

contain: layout style 선언은 광고 컨테이너를 페이지의 나머지 부분에서 격리합니다. 쿠키 배너의 경우 콘텐츠를 밀어내는 대신 position: fixed를 사용하여 오버레이하세요. AJAX 콘텐츠의 경우 min-height로 공간을 확보하세요. 정확히 추측할 필요는 없습니다. 50px의 오차는 공간을 확보하지 않아 발생하는 400px의 이동보다 훨씬 적은 CLS를 유발합니다.

YouTube, Google Maps채팅 위젯과 같은 서드파티 임베드의 경우 파사드(facade) 패턴을 사용하세요. 정적 자리 표시자를 보여주고 사용자가 상호 작용할 때만 실제 임베드를 로드합니다. 제로 CLS, 제로 낭비 리소스입니다.

5. 스크롤 트리거 레이아웃 이동

이것은 Lighthouse가 결코 잡아내지 못하는 CLS 원인입니다. Lighthouse는 페이지를 스크롤하지 않으므로 스크롤 트리거 레이아웃 이동은 실험실 테스트에서 완전히 보이지 않습니다. 이를 찾는 유일한 방법은 RUM 데이터를 사용하거나 수동으로 스크롤하면서 성능 패널 추적을 기록하는 것입니다.

가장 흔한 예는 top 속성을 애니메이션화하는 스크롤 시 숨기기(hide-on-scroll) 헤더입니다. 대부분의 개발자가 모르는 사실이 있습니다. Layout Instability 사양에서 스크롤은 제외되는 입력이 아닙니다. 클릭과 탭에는 500ms의 유예 기간이 주어집니다. 스크롤은 그렇지 않습니다. 스크롤로 인해 발생하는 모든 레이아웃 이동은 CLS 점수에 반영됩니다.

해결책: 모든 스크롤 트리거 애니메이션에 top 대신 transform: translateY()를 사용하세요. 패럴랙스(parallax) 효과, 축소되는 탐색 모음 및 스크롤에 연결된 진행률 표시줄에도 동일하게 적용됩니다. 스크롤 시 이동하는 경우 transform으로 애니메이션화하세요. 비디오 예제가 포함된 전체 연습은 스크롤 트리거 애니메이션이 CLS를 유발하는 방법을 참조하세요.

빠른 수정 체크리스트

CLS 원인 감지 방법 수정
크기가 지정되지 않은 이미지/비디오 Lighthouse "크기가 지정되지 않은 이미지" 감사 widthheight 추가; CSS에서 width: auto 제거
웹 글꼴 교체 RUM: 첫 방문 시에만 CLS가 나쁨 글꼴 메트릭 재정의; WOFF2 미리 로드; 글꼴 직접 호스팅
CSS 전환 모든 전환을 나열하는 콘솔 스니펫 transition: all을 특정 속성으로 교체; transform/opacity 사용
지연 로드되는 광고 광고 컨테이너 요소를 보여주는 RUM 속성 광고 슬롯에 min-height 설정; contain: layout style
쿠키 동의 배너 첫 방문 시 CLS 급증; 속성 데이터의 배너 콘텐츠를 밀어내는 대신 position: fixed 오버레이 사용
스크롤 애니메이션 스크롤하는 동안의 성능 패널 추적; 현장 CLS > 실험실 CLS top/left/heighttransform으로 교체

관련 가이드

모든 Core Web Vitals에 대한 전체 개요는 Core Web Vitals 허브를 방문하거나 궁극의 Core Web Vitals 체크리스트를 사용하여 전체 사이트를 감사하세요.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Lighthouse 점수가 전부가 아닙니다.

실사용자는 4G 회선 Android 폰을 씁니다. 그 사용자들이 실제로 겪는 걸 분석합니다.

필드 데이터 분석
Cumulative Layout Shift (CLS) 문제 식별 및 수정Core Web Vitals Cumulative Layout Shift (CLS) 문제 식별 및 수정