[코어 웹 바이탈 최적화] LCP(Largest Contentful Paint, 최대 콘텐츠풀 페인트)
LCP(Largest Contentful Paint, 최대 콘텐츠풀 페인트)란?
로딩 성능을 측정하는 지표로서, 페이지가 처음으로 로드를 시작한 시점을 기준으로 뷰포트 내에 있는 가장 큰 이미지 또는 텍스트 블록의 렌더링 시간을 보고한다.
좋은 사용 경험을 제공하기 위해서는 페이지가 처음으로 로딩된 후 2.5초 이내에 LCP 가 발생해야 한다.
로딩 성능을 측정을 위해서 가장 큰 콘텐츠의 렌더링 시기를 파악하는 이유가 뭘까?
기본적으로 로딩 성능을 측정하기 위해서 load 또는 DOMContentLoaded 와 같은 메트릭을 사용하곤 했다.
웹 페이지가 로딩될때 load, DOMContentLoaded 이벤트가 발생하는데 해당 이벤트가 발생하는 시점으로 성능을 측정하려 했던 것이다.
load 이벤트는 HTML 상에 필요한 모든 리소스가 로드된 시점에 발생한다.
DOMContentLoaded 이벤트는 HTML과 CSS 파싱이 끝나는 시점에 발생한다.
개발자 도구의 Network 패널 하단에서도 load, DOMContentLoaded 메트릭을 확인할 수 있다.
그러나, load, DOMContentLoaded 메트릭으로는 제대로된 성능을 판단하기 어려워졌다.
SPA(Single Page Application)는 웹 페이지에 포함된 적은 양의 HTML로 load, DOMContentLoaded 이벤트가 일찍 발생할 수는 있지만, 해당 이벤트가 발생한 이후에 수많은 스크립트가 실행되는 ‘느린 로딩’이 발생할 수 있기 때문이다.
출처: 성능 최적화
즉, load, DOMContentLoaded 메트릭은 사용자가 화면에서 보는 것과 반드시 일치하지 않을 수 있다.
또한, FCP(First Contentful Paint, 최초 콘텐츠풀 페인트)이라는 메트릭은 로딩 경험의 ‘시작’ 부분만을 포착하기 때문에 로딩 성능을 측정하기에 부적절하다고 판단되었다.
이외에도 Lighthouse에서 제공하는 FMP(First Meaningful Paint, 유의미한 최초 페인트) 및 SI(Speed Index, 속도 인덱스)와 같은 메트릭이 있지만, 이러한 메트릭은 복잡하고 잘못된 경우가 많아서 페이지의 메인 콘텐츠가 로드된 시점을 식별하기에 부적절하다고 판단되엇다.
따라서, 페이지에서 가장 큰 요소가 렌더링된 시기를 확인하여 페이지의 메인 콘텐츠가 로드되는 시기를 측정하고자 했다.
좋은 LCP 점수는 무엇일까?
LCP가 2.5초 이내에 발생하는 것이 좋다.
LCP 측정을 위해 고려되는 요소는 무엇인가?
<img>
요소<svg>
요소 내부의<img>
(<svg>
요소는 현재 LCP 후보로 간주되지 않는다.)<video>
요소- url() 함수를 통해 로드된 배경 이미지가 있는 요소
- 텍스트 노드 또는 기타 인라인 수준 텍스트 하위 요소를 포함하는 블록 수준 요소
요소의 크기는 어떻게 결정될까?
LCP에 대해 보고된 요소의 크기는 일반적으로 ‘뷰포트’ 내에서 사용자에게 표시되는 크기이다.
만약 요소가 뷰포트 외부로 확장되거나, 잘려서 보이지 않는 등의 경우에는 해당 부분은 요소의 크기에 포함되지 않는다.
만약 기본 크기(Intrinsic size)에서 크기가 조정된 이미지 요소의 경우 보여지는 가시적 크기와 기본 크기 중 ‘더 작은 것’이 보고된다.
예를 들어 기본 크기보다 작게 축소한 이미지라면 축소된 만큼의 크기가 보고되겠고, 기본 크기보다 크게 확장한 이미지라면 확장한 이미지보다 더 작은 기본 크기가 보고될 것이다.
텍스트 요소의 경우 텍스트 노드의 크기만 고려된다(모든 텍스트 노드를 포함하는 가장 작은 직사각형). 또한, 모든 요소에 대해 CSS를 통해 적용된 여백, 안쪽 여백, 테두리는 고려되지 않는다고 한다.
LCP는 언제 보고될까?
브라우저가 첫 번째 프레임을 그리는 즉시 최대 콘텐츠 요소를 식별하는 PerformanceEntry를 디스패치한다.
그리고 이후 프레임이 렌더링된 후에는 최대 콘텐츠풀 요소가 변경될 때마다 또다른 PerformanceEntry를 디스패치한다.
우선 PerformanceEntry에 대해 간력히 알아보겠다.
PerformanceEntry란?
Web API 에서 제공하는 PerformanceEntry 객체는 performance timline 상의 단일 성능 수치를 캡슐화한다.
PerformanceEntry 객체를 생성하는 방법은 아래와 같다.
-
메소드를 통해 직접적으로 생성할 수 있다
performance.mark()
메소드 혹은performance.measure()
메소드를 사용하여 성능을 측정하고 싶은 특정 포인트에서 직접적으로 해당 객체를 생성해서 확인해볼 수 있다. -
로딩시 간접적으로 생성되기도 한다
이미지와 같이 리소스를 로딩할때 PerformanceEntry 객체가 생성된다.
PerformanceEntry 객체의 프로퍼티로는 name, entryType, startTime, duration 이 있다.
즉, 특정 entryType 에 대해 성능 메트릭이 처음으로 시작되는 시기(PerformanceEntry가 생성되는 시기), 성능 이벤트가 지속되는 시기를 파악할 수 있다.
참고: PerformanceEntry
정리하자면, PerformanceEntry 객체를 통해 최대 콘텐츠풀 요소를 감지할 수 있다.
정확한 분석을 위해 가장 최근에 디스패치된 PerformanceEntry를 사용한다.
처음에 최대 콘텐츠풀 요소로 간주되었다고 하더라도 이후에 다른 더 큰 요소가 렌더링 완료되는 즉시 다른 PerformanceEntry를 통해 더 큰 요소가 최대 콘텐츠풀 요소로 보고된다.
만약 현재 최대 콘텐츠풀 요소가 뷰포트에서 제거되더라도 이보다 더 큰 요소가 렌더링되지 않는 이상 해당 요소가 최대 콘텐츠풀 요소로 유지된다.
요소 레이아웃 및 크기 변경은 어떻게 처리되는가?
오직 뷰포트에서 요소의 처음 크기와 위치만 고려한다.
즉, 렌더링 이후에 요소의 크기나 위치를 변경해도 새 LCP 후보가 생성되지 않는다.
만약 처음에 화면 밖에서 렌더링된 이지미는 보고되지 않을 수 있다. 또한, 처음에 뷰포트에서 렌더링된 요소가 아래로 밀려 뷰에서 벗어나더라도 ‘초기’ 뷰포트 내에서의 크기를 보고한다.
LCP 측정 방법
LCP를 측정하는 도구는 아래와 같다.
앞선 포스팅[코어 웹 바이탈 최적화] 코어 웹 바이탈이란?에서 언급한 코어 웹 바이탈 측정 도구와 같다.
- Chrome User Experience Report
- PageSpeed Insights
- Search Console(Core Web Vitals Report)
- web-vitals Javascript 라이브러리
- Chrome DevTools
- Lighthouse 등
이중에서 나는 크롬 개발자 도구를 사용해보았다.
퍼포먼스 패널에서 LCP 요소를 바로 찾아주는데 우리 프로덕트의 LCP는 아래의 메인 이미지이다.
다행히 나이스한 LCP 기준점인 2.5(s)초 이내에 렌더링이 완료된다. 정확히는 62.8(ms) 밀리초, 즉 0.062초가 소요되었다.
LCP를 개선하는 방법
LCP는 주로 4가지 요인에 영향을 받는다고 한다.
- 느린 서버 응답 시간
- 렌더링 차단 Javascript 및 CSS
- 리소스 로드 시간
- 클라이언트 측 렌더링
다음 포스팅에서는 위 요소들을 어떻게 개선할 수 있는지 알아보겠다!
참고 Web Vitals, 성능 최적화, Largest Contentful Paint(최대 콘텐츠풀 페인트, LCP)
댓글남기기