사전 LCP
개념

LCP

gabury1고친 사람 github-actions[bot]

LCP 는 웹 페이지를 열었을 때 주된 내용이 화면에 뜨기까지 걸린 시간을 잽니다. 첫 화면에서 가장 큰 그림이나 글 덩어리가 그려진 순간을 끝으로 봅니다. 값이 짧을수록 사용자는 페이지가 빨리 떴다고 느낍니다.

쉽고 빠른 이해

LCP 는 사용자가 「페이지가 떴다」고 느끼는 순간을 시간 하나로 알려 줍니다. 뉴스 기사라면 대표 사진이나 본문 첫 단락이 화면에 그려진 때입니다.

이 값이 없으면 서버가 빨리 답했는데도 사용자가 빈 화면을 오래 보는 일을 놓칩니다. 응답은 금방 끝났어도 큰 사진은 한참 뒤에 뜰 수 있습니다.

어떻게 도나:

  1. 브라우저가 화면을 그릴 때마다 지금까지 그린 것 가운데 가장 큰 그림이나 글 덩어리를 고릅니다
  2. 더 큰 것이 그려지면 그것으로 바꿉니다
  3. 사용자가 누르거나 스크롤하면 바꾸기를 멈춥니다. 마지막으로 고른 것이 그려진 시각이 LCP 입니다

구글이 사용자 경험을 재려고 정한 기준에서는 2.5초 안에 뜨면 합격입니다.

이 값이 못 보는 것도 있습니다. 가장 큰 것 하나만 보므로 뜬 뒤에 버튼이 굼뜨거나 화면이 흔들려도 모릅니다.

LCP 를 줄이려고 손쓰면 치르는 값이 있습니다. 큰 그림을 먼저 받게 하면 다른 파일이 그만큼 뒤로 밀립니다.

상세

이 절은 LCP 라는 이름을 풀고, 브라우저가 어느 요소를 골라 언제 시계를 멈추는지를 휴대폰 화면 하나로 따라가 봅니다. 후보가 되는 요소, 크기를 재는 법, 후보가 바뀌는 과정을 차례로 봅니다.

그다음 기준값과, 그 시간이 어느 단계에서 쓰이는지를 봅니다. 마지막으로 재는 법과 줄이는 법, 이 값이 알려 주지 않는 것을 짚습니다.

식당에서 요리가 나오는 때

식당에서 주문을 하면 물과 수저가 먼저 놓입니다. 그래도 손님은 아직 기다리는 중입니다. 주문한 요리가 상에 올라와야 비로소 「나왔다」고 느낍니다.

웹 페이지도 같습니다. 로고와 메뉴 줄이 먼저 떠도 사용자는 아직 기다립니다. 읽으려던 기사의 사진이나 첫 단락이 떠야 페이지가 떴다고 느낍니다. LCP 는 그 순간이 오기까지 걸린 시간입니다.

이름이 말하는 것

LCP 는 Largest Contentful Paint 의 줄임말입니다. 우리말로 옮기면 최대 콘텐츠풀 페인트입니다.

페인트(paint)는 브라우저가 위치와 크기를 다 계산한 화면을 실제 픽셀로 칠하는 단계입니다. 「콘텐츠풀」은 내용이 담겼다는 뜻입니다. 배경색이나 테두리가 아니라 글자와 그림처럼 사용자가 읽고 보는 것을 말합니다.

「최대」는 그 가운데 화면을 가장 넓게 차지하는 하나라는 뜻입니다. 여기서 하나는 요소 하나입니다. 요소는 HTML(HyperText Markup Language) 태그 하나로 만들어진 화면 조각입니다. 사진 한 장을 넣는 <img> 태그 하나가 요소 하나입니다.

정리하면 LCP 는 사용자가 페이지를 열기 시작한 때부터 가장 큰 내용 요소가 칠해질 때까지의 시간입니다. 주소창에 주소를 넣거나 링크를 누른 때가 시작입니다.

가장 큰 요소를 고르는 까닭

로딩을 재는 방법은 LCP 전에도 있었습니다. FCP(First Contentful Paint)는 내용이 처음 하나라도 칠해진 때를 잽니다. 그런데 로딩 중임을 알리는 작은 아이콘 하나만 떠도 FCP 는 끝납니다.

반대로 페이지의 모든 파일을 다 받은 때를 재면 너무 늦습니다. 사용자는 이미 기사를 읽고 있습니다. 그래도 화면 아래쪽의 광고 스크립트를 기다리느라 시계가 안 멈춥니다.

가장 큰 요소는 대개 그 페이지의 주된 내용입니다. 기사의 대표 사진, 상품 페이지의 상품 사진, 블로그 글의 첫 단락이 그렇습니다. 그래서 그 요소가 뜬 때는 사용자가 「떴다」고 느끼는 때와 가깝습니다.

후보가 되는 요소

모든 요소가 LCP 후보가 되지는 않습니다. 그림이나 글을 담은 요소만 후보입니다.

글을 담은 요소 가운데 후보는 블록 요소입니다. 블록 요소는 제목이나 문단처럼 가로 한 줄을 통째로 차지하는 요소입니다. 기사 제목 <h1> 과 본문 문단 <p> 가 그렇습니다.

후보 요소 흔한 예
<img> 이미지 기사의 대표 사진
SVG(Scalable Vector Graphics) 안의 <image> 벡터 그림 안에 넣은 사진
<video> 의 포스터 이미지나 첫 프레임 재생 전에 보이는 영상 첫 화면
CSS(Cascading Style Sheets) url() 로 붙인 배경 이미지 첫 화면을 덮는 큰 배너
글자를 담은 블록 요소 제목, 본문 첫 단락

후보는 그림 아니면 글입니다. CSS 그러데이션처럼 색만 칠한 배경은 후보가 아닙니다. 버튼의 테두리나 빈 상자도 후보가 아닙니다.

크기를 재는 법

크기를 재는 기준은 뷰포트입니다. 뷰포트는 브라우저 창에서 페이지가 보이는 사각형입니다. 스크롤해야 보이는 부분은 뷰포트 밖입니다. 거기 걸친 넓이는 세지 않습니다.

보이는 넓이만 셉니다. 잘려서 안 보이는 부분은 빠집니다. CSS 로 준 바깥 여백(margin), 안쪽 여백(padding), 테두리(border)도 빠집니다.

이미지는 하나를 더 봅니다. 원본 이미지의 가로×세로 픽셀보다 크게 늘려 그렸다면 원본의 픽셀 치수를 씁니다. 화면에 보이는 크기와 원본 픽셀 치수 가운데 작은 쪽을 쓰는 셈입니다.

글자는 글자들을 다 감싸는 가장 작은 사각형을 잽니다. 아래는 휴대폰 화면 하나에서 두 후보의 넓이를 견준 것입니다. 단위는 픽셀입니다.

뷰포트     400 × 800      // 320,000
제목 글    360 × 80       // 28,800
대표 사진  400 × 300      // 120,000

대표 사진이 제목보다 네 배쯤 넓습니다. 그래서 이 페이지의 LCP 요소는 대표 사진입니다. 제목이 먼저 떠도 LCP 는 사진이 그려질 때까지 안 끝납니다.

후보가 바뀌는 과정

브라우저는 페이지를 한 번에 그리지 않습니다. 받은 것부터 먼저 그립니다. 그래서 그리는 도중에는 「지금까지 가장 큰 요소」가 몇 번 바뀝니다.

첫 화면을 칠하고 나면 브라우저는 그때까지 가장 큰 요소를 첫 후보로 고릅니다. 그 뒤 더 큰 요소가 칠해질 때마다 새 후보로 바꿉니다. 이미 그린 요소의 크기나 위치가 바뀌는 것은 새 후보로 치지 않습니다.

사용자가 화면을 누르거나, 스크롤하거나, 키를 누르면 브라우저는 후보 바꾸기를 멈춥니다. 그 뒤에 새로 뜨는 내용은 사용자가 움직여서 불러온 것일 수 있기 때문입니다. 그때까지의 마지막 후보가 그려진 시각이 그 방문의 LCP 입니다.

앞의 휴대폰 화면으로 따라가 보면 이렇습니다.

flowchart TD
    A["0.4초 · 제목 글이 칠해진다"] --> B["후보 · 제목 글"]
    B --> C["1.8초 · 대표 사진이 칠해진다"]
    C --> D["후보 · 대표 사진으로 바뀜 · 더 넓다"]
    D --> E["2.6초 · 사용자가 스크롤한다"]
    E --> F["후보 바꾸기를 멈춘다 · LCP 1.8초"]

제목이 0.4초에 떴지만 LCP 는 0.4초가 아닙니다. 더 넓은 사진이 1.8초에 칠해져 후보가 바뀌었기 때문입니다. 2.6초의 스크롤 뒤로는 무엇이 떠도 후보가 바뀌지 않습니다.

기준값

LCP 는 시간이라 초나 밀리초로 적습니다. 기준값은 셋으로 갈립니다.

LCP 판정 이름 뜻
2.5초 이하 good 빨리 떴다
2.5초 초과 4초 이하 needs improvement 손볼 만하다
4초 초과 poor 오래 기다렸다

방문 한 번의 값으로 판정하지 않습니다. 같은 페이지라도 기기와 네트워크에 따라 방문마다 LCP 가 다르기 때문입니다. 방문들의 LCP 를 짧은 것부터 줄 세웠을 때 75% 지점에 오는 값, 곧 75백분위 값을 봅니다.

75백분위가 2.5초 이하라는 말은 방문 넷 중 셋이 2.5초 안에 떴다는 뜻입니다. 휴대폰과 데스크톱은 화면 크기와 네트워크가 달라서 따로 잽니다.

시간이 쓰이는 단계

LCP 는 시간 하나지만 앞에서부터 잘라 보면 어디서 늦었는지 보입니다. LCP 요소가 이미지일 때를 기준으로 네 토막으로 나눠 봅니다.

flowchart TD
    A["1 · 서버가 HTML 의 첫 바이트를 보낸다"] --> B["2 · 브라우저가 LCP 이미지를 알아채고 요청한다"]
    B --> C["3 · 이미지를 내려받는다"]
    C --> D["4 · 다 받은 이미지가 칠해지기를 기다린다"]

첫 토막은 서버 몫입니다. 요청을 보낸 뒤 응답의 첫 바이트가 오기까지의 시간을 TTFB(Time to First Byte)라고 부릅니다. TTFB 가 1초면 2.5초 안에 들 여유는 1.5초만 남습니다.

둘째 토막은 브라우저가 이미지를 언제 알아채느냐입니다. 이미지가 HTML 에 바로 적혀 있으면 HTML 을 읽는 즉시 요청합니다. 스크립트가 실행된 뒤에야 이미지 태그를 넣는 페이지라면 스크립트를 다 받고 돌릴 때까지 요청조차 못 합니다.

셋째 토막은 파일 용량과 거리에 달렸습니다. 사진 파일의 용량이 크거나 서버가 멀면 오래 걸립니다.

넷째 토막은 이미지를 다 받고도 못 칠하는 시간입니다. 화면을 그리기 전에 꼭 받아야 하는 스타일시트나 스크립트가 남아 있으면 이미지는 기다립니다. LCP 요소가 글자라면 따로 받을 파일이 없어서 둘째와 셋째 토막이 거의 없습니다.

재는 법

LCP 는 두 곳에서 잽니다. 방문자의 브라우저에서 재거나, 개발자가 띄운 시험용 브라우저에서 잽니다.

브라우저는 새 후보를 정할 때마다 페이지 안의 자바스크립트에 알려 줍니다. 받는 통로가 PerformanceObserver 입니다. 아래 코드는 알림이 올 때마다 마지막 후보의 시각을 찍습니다.

JavaScript
new PerformanceObserver((list) => {
  const es = list.getEntries();
  const last = es[es.length - 1];
  console.log(last.startTime); // 1800
}).observe({
  type: "largest-contentful-paint",
  buffered: true,
});

값은 밀리초입니다. 앞의 휴대폰 화면이라면 사진이 칠해진 1.8초, 곧 1800 이 찍힙니다. buffered: true 는 관찰을 시작하기 전에 이미 생긴 후보도 받겠다는 뜻입니다.

방문자의 브라우저에서 잰 값을 서버로 모으는 방식이 실사용자 모니터링(Real User Monitoring, RUM)입니다. 후보가 여럿 오므로 서버로 보낼 때는 맨 마지막 것 하나만 보냅니다. 실제 사용자의 기기와 네트워크가 담기므로 기준값 판정은 이 값으로 합니다.

시험용 도구는 Lighthouse 처럼 페이지를 한 번 열어 보고 LCP 를 냅니다. 개발 중에 바로 돌려 볼 수 있습니다. 대신 개발자의 기기와 네트워크 한 벌로 잰 값이라 방문자가 겪는 값과 다를 수 있습니다.

줄이는 법

줄이는 법은 앞의 네 토막을 하나씩 짧게 하는 것입니다. 어느 토막이 긴지 먼저 보고 그 토막에 손을 씁니다.

늦는 토막 손쓰는 법
1 · 서버 응답 응답을 캐시해 둠 · 오래 걸리는 쿼리를 줄임
2 · 이미지 발견 이미지를 HTML 에 바로 적음 · 서버가 내용을 채운 HTML 을 보냄 · <link rel="preload"> 로 미리 알림
3 · 내려받기 사진 파일의 용량을 줄임 · 가까운 서버에서 내줌
4 · 칠하기 전 대기 첫 화면에 필요 없는 스크립트를 뒤로 미룸

표의 첫째부터 셋째 줄까지가 백엔드와 맞닿습니다. 첫째 줄은 서버 응답 그 자체라서 손쓴 만큼 TTFB 가 줄어듭니다.

서버 사이드 렌더링(Server-Side Rendering, SSR)은 서버가 내용을 채운 HTML 을 처음부터 보내는 방식입니다. 이미지 태그와 본문이 첫 응답에 이미 들어 있으니 둘째 토막이 줄어듭니다. 브라우저가 스크립트를 받아 돌린 뒤에야 내용을 만드는 방식이면 그 기다림이 LCP 에 더해집니다.

CDN(Content Delivery Network)은 사용자와 가까운 여러 서버에 파일을 두고 내주는 망입니다. 큰 사진이 먼 원래 서버 대신 가까운 서버에서 오면 셋째 토막이 줄어듭니다.

하나 피할 것이 있습니다. 지연 로딩(lazy loading)은 화면에 보일 때가 되어서야 이미지를 받는 기법입니다. 첫 화면 아래의 사진에는 맞지만 LCP 사진에 걸면 요청이 그만큼 늦어집니다.

앞당기기에도 한계가 있습니다. 브라우저가 한꺼번에 받을 수 있는 양이 정해져 있기 때문입니다. LCP 사진을 앞당기면 다른 파일이 그만큼 뒤로 밀립니다. 여러 파일을 다 「먼저」로 올리면 서로 다투다 아무것도 안 빨라집니다.

LCP 가 알려 주지 않는 것

LCP 는 코어 웹 바이탈(Core Web Vitals)의 세 지표 가운데 하나입니다. 코어 웹 바이탈은 구글이 웹 페이지의 사용자 경험을 재려고 고른 묶음입니다. 셋은 저마다 다른 불편을 봅니다.

지표 재는 것 단위
LCP 가장 큰 내용이 뜨기까지 걸린 시간 시간
INP(Interaction to Next Paint) 누른 뒤 화면이 반응하기까지 걸린 시간 시간
CLS(Cumulative Layout Shift) 화면이 밀려난 정도 없음

LCP 가 빨라도 뜬 뒤에 버튼이 굼뜨면 INP 가 나쁩니다. 뜬 뒤에 내용이 밀려 흔들리면 CLS 가 나쁩니다. 그래서 셋을 함께 봅니다.

LCP 는 가장 큰 요소 하나만 봅니다. 그보다 작은 「구매」 버튼이 한참 늦게 떠도 LCP 는 모릅니다. 사용자에게 중요한 요소가 가장 큰 요소가 아닌 페이지에서는 그 요소가 늦게 뜬 것이 LCP 에 안 잡힙니다.

LCP 는 브라우저 안에서만 뜻이 있습니다. 휴대폰 앱의 네이티브 화면이나 API(Application Programming Interface) 서버 자체에는 붙지 않습니다. 백엔드 개발자가 이 값을 만나는 곳은 서버가 보내는 HTML 의 응답 시간, 그리고 그 페이지가 받아 가는 큰 파일입니다.

관련 항목

LCP 후보를 가르는 요소와 크기 기준

뷰포트 · 이미지 · 배경 이미지 · 블록 요소 · 포스터 이미지 · 픽셀 · SVG

LCP 와 함께 사용자 경험을 재는 지표

코어 웹 바이탈 · CLS · INP · FID · FCP · TTFB · Web Vitals · Speed Index

LCP 를 재고 모으는 도구와 방식

PerformanceObserver · Largest Contentful Paint API · 실사용자 모니터링 · Lighthouse · CrUX · PageSpeed Insights · 백분위수

LCP 시간이 지나가는 브라우저의 그리기 단계

브라우저 · 렌더링 · 렌더 파이프라인 · 페인트 · 렌더 차단 리소스 · 크리티컬 렌더링 패스 · HTML · CSS

LCP 를 앞당기는 기법

서버 사이드 렌더링 · CDN · 프리로드 · fetchpriority · 이미지 최적화 · WebP · HTTP 캐싱 · 코드 분할 · 지연 로딩

LCP 가 속하는 상위 분류

성능 · 프론트엔드 · 사용자 경험 · 검색 엔진 최적화

다른 이름: Largest Contentful Paint · 최대 콘텐츠풀 페인트 · 최대 콘텐츠 페인트