Core Web Vitals

Largest Contentful Paint 개선: 가장 느린 LCP 구간을 찾아 고치는 방법

가장 큰 이미지 자체보다 다운로드가 시작되기 전의 지연이 더 중요할 수 있습니다.

브라우저 화면에서 가장 큰 콘텐츠 블록이 강조되고 가는 선이 렌더링까지의 진행을 나타냅니다.

Largest Contentful Paint를 개선하려면 LCP를 결정하는 요소를 식별하고 무엇이 표시를 늦추는지 측정합니다. 이미지라면 HTML 대기, 요청 시작 전 지연, 다운로드, 렌더링 전 남은 대기로 나눕니다. 모든 이미지 최적화를 한꺼번에 적용하기보다 실제로 느린 구간을 고칩니다.

LCP는 75번째 백분위수에서 2.5초 이하면 좋음입니다. 이는 방문자에게 나타나는 결과를 말합니다. 느린 서버 때문인지, 늦게 발견된 사진 때문인지, JavaScript가 끝날 때까지 이미 받은 콘텐츠를 숨기는 페이지 때문인지는 알려 주지 않습니다.

전달 방식을 바꾸기 전에 요소를 찾습니다

조사할 뷰포트 크기에서 Chrome DevTools로 페이지 로딩을 기록합니다. LCP 이벤트와 연결된 요소를 봅니다. 로딩이 진행되며 더 큰 후보가 나올 수 있으므로 기록에 실제로 보이는 페이지와 비교합니다.

이미지와 텍스트 블록이 후보에 포함되며 배경 이미지와 영상에는 추가 규칙이 있습니다. LCP는 단순히 가장 큰 DOM 노드나 마지막 네트워크 요청이 아닙니다. 빈 공간이 많은 컨테이너가 크다는 이유만으로 의미 있는 콘텐츠가 되지는 않습니다.

관련 템플릿과 기기 크기에서 반복합니다. 모바일에서는 제목이, 데스크톱에서는 상품 이미지가 LCP를 결정할 수 있습니다. 실험이나 동의 상태도 보이는 내용을 바꿉니다. 다음 테스트가 같은 상황을 다루도록 요소와 함께 조건을 기록합니다.

web-vitals attribution 빌드를 사용하는 프로젝트에서는 다음 진단 모듈이 사용 가능한 이미지 URL과 구간 시간을 기록합니다.

js
import { onLCP } from 'web-vitals/attribution';

onLCP(({ value, attribution }) => {
  console.table({
    lcp: value,
    resource: attribution.url ?? 'Text or no image resource',
    ttfb: attribution.timeToFirstByte,
    loadDelay: attribution.resourceLoadDelay,
    loadDuration: attribution.resourceLoadDuration,
    renderDelay: attribution.elementRenderDelay
  });
});

이는 관찰 보조 도구이며 완전한 모니터링 서비스가 아닙니다. 호환 패키지가 설치되어 있고 빌드에서 import를 처리할 수 있어야 합니다. 현장 수집에는 신중하게 설계한 엔드포인트와 집계가 추가로 필요합니다. 적용할 때 라이브러리 버전과 attribution 인터페이스를 확인합니다.

네 구간으로 나누어 첫 수정 대상을 정합니다

Google의 LCP 최적화 가이드는 이미지 기반 LCP를 서로 다른 작업에 대응하는 구간으로 나눕니다. 텍스트 LCP에는 이미지 다운로드가 없을 수 있으므로 모델에 맞추려고 존재하지 않는 단계를 만들지 않습니다.

구간 진단 질문 조사 대상
Time to First Byte HTML은 언제 도착합니까? 리디렉션, 원본 작업, 캐시
리소스 로드 지연 이미지 요청은 언제 시작할 수 있습니까? 초기 마크업, CSS 발견, 우선순위
리소스 로드 기간 전송은 얼마나 걸립니까? 크기, 인코딩, 전달 경로
요소 렌더링 지연 받은 콘텐츠가 왜 보이지 않습니까? CSS, 글꼴, 메인 스레드, 숨김 상태

유용한 변경은 콘텐츠가 보이기까지 전체 경로를 줄입니다. 이미지 다운로드가 빨라져도 같은 긴 렌더링 작업을 기다린다면 다운로드 구간은 줄고 렌더링 대기는 늘어 전체 LCP가 거의 같을 수 있습니다. 이는 구체적인 진단이며 이미지 압축이 전혀 도움이 없다는 증거는 아닙니다.

원래 트레이스를 보관합니다. 전후 비교에서 어느 구간이 바뀌었는지, 같은 요소가 여전히 LCP를 결정하는지 보여야 합니다. 다른 후보가 선택되면 그 변화를 조사합니다. 설명 없이 서로 다른 리소스를 비교하지 않습니다.

HTML 도착 이전의 시간을 줄입니다

브라우저는 식별에 필요한 문서를 받기 전에는 일반 문서 리소스를 발견하지 못합니다. 탐색 요청의 리디렉션, 연결 설정, 최종 응답을 추적합니다. 애플리케이션이 빨라도 연속 리디렉션은 발견을 늦춥니다.

캐시된 응답과 캐시되지 않은 응답을 비교합니다. 준비된 홈페이지 캐시는 드문 URL의 느린 애플리케이션 실행을 가릴 수 있습니다. CDN이 HTML을 저장하는지 정적 파일만 저장하는지, 쿠키가 공개 캐시를 예상 밖으로 우회하는지 확인합니다.

시간을 줄이려고 개인화 페이지를 공개 캐시로 만들지 않습니다. 세션, 접근 권한, 콘텐츠 정확성이 유지되어야 합니다. 서버 응답 시간 가이드는 이 문제를 구분하고 캐시 적중이 피하는 작업을 측정하는 방법을 설명합니다.

서버 렌더링도 맥락이 필요합니다. 유용한 마크업은 클라이언트의 발견 작업을 줄이지만 비용이 큰 렌더링 과정은 TTFB를 늘릴 수 있습니다. 응답과 실제 페인트를 함께 측정합니다. 빠른 빈 껍데기가 목표는 아닙니다.

중요한 이미지를 즉시 발견할 수 있게 합니다

초기 HTML의 이미지 URL은 브라우저 리소스 발견 기능이 읽을 수 있습니다. JavaScript 실행 뒤 만들어지는 이미지는 그 의존성을 물려받습니다. CSS 배경 이미지는 스타일시트를 받고 처리한 뒤에야 URL이 발견될 수 있습니다.

디자인과 의미에 맞는다면 주요 콘텐츠에는 일반 이미지 요소를 우선합니다. 정확한 대체 텍스트와 크기를 지정합니다. 다른 미디어가 지연 로딩된다는 이유만으로 첫 화면 이미지를 loading="lazy"로 설정하지 않습니다.

다음 예시는 최대 960 CSS 픽셀 폭의 이미지와 더 좁은 모바일 레이아웃을 가정합니다. 파일은 예시 프로젝트 자산이며 실제 빌드가 제공해야 합니다.

html
<img
  src="/images/guide-960.webp"
  srcset="/images/guide-640.webp 640w,
          /images/guide-960.webp 960w,
          /images/guide-1600.webp 1600w"
  sizes="(max-width: 960px) 100vw, 960px"
  width="1600"
  height="900"
  fetchpriority="high"
  alt="A browser displaying a highlighted content panel"
>

브라우저는 sizes, 후보 폭, 기기 특성으로 리소스를 선택합니다. sizes는 실제 레이아웃과 일치해야 하며 이미지의 CSS 폭을 설정하는 속성은 아닙니다. 반쪽 열을 차지하는 이미지를 전체 뷰포트 폭이라고 설명하면 불필요하게 큰 파일을 받을 수 있습니다.

fetchpriority="high"는 해당 요청이 중요하다고 알립니다. 숨겨진 리소스를 발견 가능하게 만들지는 않습니다. 경쟁하는 여러 이미지에 적용하면 의도한 우선순위 효과가 약해집니다. 측정된 LCP 후보부터 적용하고 워터폴을 확인합니다.

이른 발견이 실제 지연을 해결할 때만 preload를 사용합니다

preload는 늦게 발견될 중요한 리소스에 유용합니다. 브라우저가 순서를 정하기 전에 화면의 모든 파일을 가져오라는 명령은 아닙니다.

정말 중요한 CSS 배경이라면 이미지 preload로 스타일시트가 URL을 드러내기 전에 요청을 시작할 수 있습니다. 다음 두 예시는 같은 URL을 사용해 의도한 요청을 재사용합니다.

html
<link rel="preload" as="image" href="/images/banner.webp"
      fetchpriority="high">
css
.banner {
  min-height: 18rem;
  background-image: url('/images/banner.webp');
  background-size: cover;
  background-position: center;
}

예시의 크기는 디자인 선택이며 성능 기준이 아닙니다. 정보 전달이 목적이고 대체 텍스트가 필요하다면 의미 있는 이미지 요소를 사용합니다.

반응형 이미지를 미리 가져온다면 preload 선택도 일치해야 합니다. 고정 URL을 지정했는데 실제 이미지가 다른 후보를 선택하면 대역폭이 낭비됩니다. 비슷한 이미지 참조가 하나의 전송이라고 가정하지 말고 URL, 리소스 유형, 자격 증명 동작을 확인합니다.

힌트 추가 후 필요한 요청이 빨리 시작했는지, 다른 중요한 작업이 밀렸는지 확인합니다. 사용되지 않은 preload 경고는 숨길 대상이 아니라 구현을 조사할 이유입니다.

콘텐츠 품질을 해치지 않고 이미지 바이트를 줄입니다

제때 발견된다면 선택된 이미지 크기와 전송량을 확인합니다. 표시 공간과 목표 픽셀 밀도에 맞는 후보를 내보냅니다. 고밀도 화면에는 CSS 폭보다 많은 이미지 픽셀이 필요할 수 있으므로 두 수치를 무조건 같게 만드는 것이 규칙은 아닙니다.

실제 이미지에서 형식과 압축 설정을 비교합니다. AVIF와 WebP는 유용할 수 있지만 콘텐츠, 요구 품질, 인코딩 선택에 따라 결과가 달라집니다. 작은 글자, 도표, 사진이 압축에 똑같이 반응하지는 않습니다.

표시 크기에서 결과를 봅니다. 상품 세부가 흐리거나 글자가 깨지고 아티팩트가 보이는 것은 파일이 작다는 이유만으로 허용되지 않습니다. 원본을 보관하고 내보내기 설정을 재현 가능하게 만들어 이후 편집이 개선을 되돌리지 않게 합니다.

이미지 CDN이나 CMS 변환 파이프라인은 후보 생성을 자동화할 수 있습니다. 그래도 생성된 마크업과 실제 요청을 검증합니다. 반응형이라는 기능 이름만으로 sizes가 테마와 일치한다고 입증되지는 않습니다. 이미지 최적화 가이드에서 형식과 반응형 마크업을 확인합니다.

이미지 절감 계산기는 바이트 변화 비교에 사용합니다. 입력한 값으로 전송 절감을 추정할 뿐 LCP가 몇 밀리초 좋아질지 알려 주지 않습니다. 병렬 로딩, 캐시, 다른 구간도 여전히 영향을 줍니다.

다운로드와 페인트 사이의 간격을 조사합니다

이미지가 도착한 뒤 훨씬 늦게 나타나면 렌더링을 막는 요인을 찾습니다. 스타일시트가 아직 필요하거나, JavaScript가 메인 스레드를 차지하거나, 애니메이션과 초기화 또는 클라이언트 상태가 끝날 때까지 컴포넌트가 숨겨져 있을 수 있습니다.

불필요한 표시 의존성을 제거합니다. 첫 슬라이드를 일반 마크업으로 표현할 수 있다면 중요한 이미지가 별도의 캐러셀 로직을 기다릴 이유는 없습니다. 로딩 오버레이가 준비된 내용을 가리는지, 등장 애니메이션이 사용자 도움 없이 지표만 늦추는지 봅니다.

렌더링 차단 CSS는 신중하게 검사합니다. 모든 스타일시트를 없애거나 모든 스타일을 뒤로 미루는 것이 목표가 아닙니다. 첫 화면에는 번쩍임과 이동을 막는 올바른 스타일이 필요합니다. 미사용 또는 비핵심 자산을 찾되 실제 첫 뷰포트의 필수 규칙은 유지합니다.

네트워크가 끝나도 메인 스레드 작업이 렌더링을 늦출 수 있습니다. 해당 시점의 큰 스크립트, hydration, 동기 초기화를 찾습니다. 렌더링 차단 리소스 가이드는 혼동하기 쉬운 발견과 실행 의존성을 구분합니다.

텍스트 LCP는 글꼴과 텍스트 가시성을 조사합니다. 글꼴 요청은 제목 표시 시점에, 대체 글꼴 메트릭은 레이아웃에 영향을 줍니다. 모든 글꼴 preload를 답으로 생각하지 않습니다. 더 시급한 첫 화면 리소스와 경쟁할 수 있습니다.

실제로 제공하는 모바일과 콘텐츠 변형을 확인합니다

긴 제목과 짧은 제목, 대표 이미지가 있는 기사와 없는 기사를 검사합니다. 보이는 레이아웃을 바꾼다면 실제 동의 상태, 광고 구성, 언어도 포함합니다. 공유 코드라도 콘텐츠에 따라 다른 LCP 후보를 만들 수 있습니다.

좁은 뷰포트가 데스크톱 이미지를 잘라내거나 숨겨도 마크업과 스타일이 맞지 않아 계속 다운로드될 수 있습니다. 반대로 시작 후 스크립트가 모바일 자산을 고르면 요청이 늦을 수 있습니다. 완성된 화면뿐 아니라 실제 요청을 봅니다.

번역 페이지에서는 글꼴 문자 지원과 줄바꿈이 후보와 렌더링 의존성을 바꿀 수 있습니다. 영어 페이지 개선이 모든 언어의 개선을 입증한다고 생각하지 말고 같은 진단 절차를 적용합니다.

비교 가능한 기록으로 가설 하나를 검증합니다

수정 전에 가설을 적습니다. 예를 들어 초기화 뒤 컴포넌트가 LCP 이미지를 삽입해 발견이 늦어진다는 설명입니다. 이를 검증하는 최소한의 변경을 하고 같은 상황을 다시 기록합니다.

리소스 시작, 전송 완료, 페인트, 전체 LCP를 비교합니다. 같은 뷰포트, 제한 조건, 캐시 상태에서 반복합니다. 실패와 오류도 남깁니다. 중요한 기능이 로드되지 않게 된 페이지는 잘못된 이유로 빨라 보일 수 있습니다.

배포 후에는 수집 기간에 걸친 실제 사용자 데이터를 확인합니다. 기기, 연결, 지역, 탐색 방식이 달라 현장 LCP가 실험실과 다를 수 있습니다. 실험실 개선은 유용한 근거지만 현장 결과의 대체물은 아닙니다.

유지보수하기 쉬운 결과를 만듭니다

어떤 요소가 중요하며 어떻게 발견되고 어떤 최적화가 의도되었는지 기록합니다. 짧은 구현 메모로 이미지 플러그인이 지연 로딩을 다시 넣거나, 재설계가 슬롯만 바꾸고 sizes를 그대로 두는 일을 예방할 수 있습니다.

대표 페이지, 의도한 이미지 후보, 예상 발견 경로, 저장한 트레이스를 검토 절차에 남깁니다. 다른 지표가 제한 요인이 되면 Core Web Vitals 참고 가이드를 활용합니다. 다음 작업은 또 다른 일반 최적화 스위치가 아니라 다음으로 측정된 지연에서 나와야 합니다.

관련 가이드