이미지 Largest Contentful Paint (LCP) 최적화

기운찬곰·2023년 5월 13일
2
post-thumbnail

Overview

요즘 프론트엔드 트렌드 하면 웹 성능과 최적화 방법에 대한 내용이 아닐까 싶습니다. 저 또한 관심이 많은 편인데요. 오늘은 그 중에서 LCP 라는 측정 지표에 대해 알아보면서 간단한 테스트를 진행해볼까 합니다.


Web Vitals 란?

LCP를 알아보기 전에 간단히 Wev Vitals에 대해 사전 지식으로 알아보도록 하겠습니다.

"Web Vitals는 웹에서 우수한 사용자 경험을 제공하는 데 필수적인 품질 신호에 대한 통합 지침을 제공하기 위한 Google의 이니셔티브" - 참고 : https://web.dev/vitals/

결국 Web Vitals이라는 건 구글 크롬팀이 소개한 웹 성능에 대한 지표(지침)이라고 볼 수 있습니다. 그 전까지 다양한 측정 지표가 있었지만 요즘에는 Web Vitals가 가장 대표적인 지표라고 볼 수 있겠습니다.

구글 Lighthouse을 활용하면 Web Vitals를 측정해볼 수 있습니다. 오... Velog 성능 좋네요.

성능 지표 중 주요항목으로는 6가지가 있습니다.

  • FCP (First Contentful Paint) : 첫번째 텍스트 또는 이미지가 표시되는 시간
  • TTI (Time to Interactive) : 사용자 인터렉션이 가능해질 때까지 걸리는 시간
  • SI (Speed Index) : 페이지 속도. 얼마나 빨리 표시되는지
  • TBT (Total Blocking Time) : FCP ~ Time to interactive 사이에서 메인 스레드를 블로킹하는 작업 시간
  • LCP (Largest Contentful Paint) : 가장 마지막 최대 텍스트 또는 이미지가 표시되는 시간
  • CLS (Comulative Layout Shift) : 누적 레이아웃 이동. 뷰포트 안에 보이는 요소의 이동을 측정. 사용자가 예상치 못한 레이아웃 이동을 경험하는 빈도를 수량화해서 보여준다.

그리고 별도로 중요한 3가지 지표는 Core Wev Vitals로 소개하고 있다. 그 중 하나가 오늘 소개할 LCP 이다. LCP는 그만큼 중요한 지표 중 하나이다.


Largest Contentful Paint (LCP)

LCP는 의미상으로 봐도 다른 지표보다 직관적으로 이해하기 쉬운 지표입니다.

"최대 콘텐츠풀 페인트(LCP) 메트릭은 페이지가 처음으로 로드를 시작한 시점을 기준으로 뷰포트 내에 있는 가장 큰 이미지 또는 텍스트 블록의 렌더링 시간을 보고합니다." - 참고 : https://web.dev/lcp/

우수한 사용자 경험을 제공하려면 2.5초 이내로 모든 로딩이 다 끝나야 합니다. 백분위수로 따지면 75번째 백분위수를 측정하는 것이 바람직한 임계값입니다.

LCP에 가장 큰 걸림돌은 이미지입니다. 비디오도 있을 수 있지만, 보통은 이미지를 많이 쓰니까요. 그 외에도 블로킹 리소스, 느린 서버 응답 시간 등이 부가적인 요소가 있을 수 있습니다. 제 체감상 불필요하게 큰 이미지가 제일 문제였던거 같습니다. 이미지 자체 크기를 최적화하는 것이 가장 좋은 해결방법이긴 합니다.


이미지 LCP 실습 프로젝트 구성

간단하게 실습을 통해 몇 가지 상황을 통해 이미지 LCP 측정을 해보고 분석하는 시간을 가져보려고 합니다. 그러기 위해서는 프로젝트를 만들어야 하는데... react 환경은 CSR라서 정확한 측정은 안될 거 같고, 완전히 정적인 페이지를 만들어야 될 거 같습니다.

마침 react 최적화 실습하던 프로젝트가 있어서 해당 프로젝트 내에 public 폴더에 간단하게 html을 만들어서 정적 리소스를 불러오는 방식으로 실습을 진행하겠습니다.

참고로, 이미지로는 2.2MB 이미지를 다운받아 사용했습니다.

💻 깃허브 참고 : https://github.com/ckstn0777/react-playground

이렇게 만들고 나서 github pages를 사용해서 깃허브 페이지로 볼 수 있게 했습니다. 로컬에서 테스트하기에는 좀 부정확할 테니까요...


이미지 LCP 테스트 코드 작성

img 태그를 통해 이미지를 보여주는 경우와 CSS background-image를 통해 이미지를 보여주는 경우를 각각 만들어서 테스트를 진행해보겠습니다. 성능 차이가 있을까요? 🤔

아, 그리고 확실한 차이를 위해 slowfil.es 라는 곳에서 js를 요청해보도록 하겠습니다. js 말고도 css, image, font 를 불러올 수도 있고 임의 delay 설정도 가능합니다. 성능 테스트 하기 매우 좋을 거 같습니다.

이미지 태그를 사용한 경우

URL : https://ckstn0777.github.io/react-playground/LCP/img.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

	<script src="https://slowfil.es/file?type=js&delay=1000"></script>

    <title>IMG LCP</title>
  </head>
  <body>
    <h1>IMG LCP</h1>
    <p>
      <img src="./album.jpg" alt="album image" width="1920px" height="1200px" />
    </p>
  </body>
</html>

CSS background-image를 사용한 경우

URL : https://ckstn0777.github.io/react-playground/LCP/background-image.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

	<script src="https://slowfil.es/file?type=js&delay=1000"></script>

    <style>
      figure {
        background-image: url("./album.jpg");
        background-size: cover;
        width: 1920px;
        height: 1200px;
        margin: 0;
      }
    </style>

    <title>IMG CSS Background image LCP</title>
  </head>
  <body>
    <h1>IMG LCP</h1>

    <figure></figure>
  </body>
</html>

WebPageTest를 사용해서 측정하기

WebPageTest 사이트 : https://www.webpagetest.org/

웹 성능 측정을 위해서 Lighthouse 나 Performance를 사용할 수 있겠지만, 보다 상세한 결과를 보고 싶다면 웹 성능 측정을 전문적으로 하는 사이트나 프로그램을 통해 하는 것이 좋을거 같습니다.

그 중에서 WebPageTest는 특정 나라(지역), 기기 환경(Desktop or Mobile), 네트워크 상태(Cable, LTE, 4G...), 브라우저, 테스트 러너 수 등 세부적인 테스트 환경을 설정할 수 있습니다.

또한, 회원가입 시 Starter Plan으로하면 월 300번 테스트가 가능합니다. 월 300번은 아무래도 채울 거 같지는 않기 때문에 쓸만 한거 같습니다.

테스트를 원하는 사이트 주소를 적고, 테스트 설정을 한 후 Start Test 버튼을 클릭해줍니다. 특정은 대략 20~30초 정도 걸리는거 같습니다. 측정 결과를 보면 기본적인 web vitals 결과가 나옵니다. LCP는 큰 이미지 때문에 유독 안좋게 나온 것을 알 수 있습니다.

그리고 밑에 보면 상세 결과도 볼 수 있는데 그 중에서 저는 Filmstrip View가 가장 좋은거 같습니다.

Filmstrip View를 보면 필름처럼 화면이 언제 어떻게 바뀌고 그때의 네트워크, CPU 상태 등을 한눈에 알 수 있기 때문입니다.

그리고 여러 개 측정했으면 측정한 결과를 서로 비교해서 볼 수도 있습니다. 방법은 탭에 보면 Test History라는게 있는데 지금까지 측정한 히스토리를 볼 수 있습니다. 비교를 원하는 테스트 히스토리를 선택해주면 됩니다.

그러면 이렇게 비교해서 한눈에 확인해볼 수 있습니다.

확실히 img 태그를 사용할 때보다 CSS background-image 를 사용할 때 성능이 더 안 좋게 나온 것을 알 수 있습니다.


이미지 측정 결과 분석

img 태그 사용 시

LCP 결과 : 4.555 s

이미지 사용 시 img 태그를 가장 많이 사용할 것입니다. 특별한 일이 없으면 img 태그를 사용하는게 좋습니다. 왜냐면 프리로드 스캐너(preload-scanner)에 의해 빠르게 요청될 수 있기 때문입니다. 🤔

일단, 프리로드 스캐너를 이해하기 전에 먼저 블로킹 리소스를 사전에 알고 있어야 합니다. 저희는 이미지를 요청하기 전에 slowfil.es 라는 곳에서 임의로 딜레이를 주기 위한 스크립트를 요청하고 있었습니다. 바로 이 녀석이 블로킹 리소스입니다.

<script src="https://slowfil.es/file?type=js&delay=1000"></script>

async, defer, type="module" 같은 옵션이 없는 script 태그는 블로킹 리소스이며, HTML parsing 과정에서 이녀석을 만나면 다음 할 일을 못하게 됩니다. 즉, 차단 됩니다. 그래서 script 태그는 가급적 async나 defer 옵션을 붙여서 사용하거나 body 밑에 script를 사용하는 것이 좋습니다.

아무튼... 이 같은 실수를 저질렀음에도 아래 보게 되면 이미지는 스크립트와 동시에 요청되고 있는 것을 볼 수 있습니다. 분명 HTML 파서가 차단되었으면 img 태그도 아직 못 찾았을텐데 무슨 일일까요?

이런 마법같은 현상은 프리로드 스캐너라는 녀석이 해주고 있습니다. 프리로드 스캐너는 블로킹 리소스에 대해 HTML 파서가 차단당하거나 말거나 독립적으로 동작합니다. 그러면서 HTML을 한번 스캔해서 필요한 리소스를 찾아서 빠르게 불러올 수 있게 됩니다.

CSS background-image 사용 시

LCP 결과 : 6.901 s

img 태그 사용 시 결과와 차이가 많이 벌어졌습니다. 왜냐면 CSS background-image는 브라우저 프리로드 스캐너가 검색하지 않기 때문입니다. 프리로드 스캐너는 마크업을 스캔하고 CSS는 스캔하지 않습니다. 따라서 결과를 보면 slowfil.es 스크립트를 만나면 블로킹 되었다가 처리가 끝나면 그제서야 이미지를 요청하는 것을 알 수 있습니다.

이를 해결할 방법은 여러가지가 있겠지만, 여기서는 preload를 사용해보겠습니다.

"페이지에서 즉시 필요로 할 리소스를 명시할 수 있습니다. 이러한 리소스는 브라우저의 주요 렌더링 절차가 개입하기 전에 페이지 생명주기의 초기에서 불러오고자 하는 리소스입니다." - MDN 참고

사용법은 매우 간단합니다.

<link rel="preload" as="image" href="./album.jpg" />

그리고 나서 결과를 봤더니 LCP : 4.142s 가 나왔습니다.

이처럼 preload는 LCP 에 영향을 주는 이미지, 혹은 폰트가 중요한 경우라면 폰트를 빨리 불러오고 싶을 때 사용합니다. 참고로 재밌게도 Next.js에서는 font를 불러올 때 기본적으로 preload를 사용하는거 같습니다. 역시 Next.js는 기본 최적화가 참 잘되어있는거 같습니다.


마치면서

이번 시간에는 성능 측정에서 중요한 여러가지 재밌는 사실을 배우게 된 거 같아서 뿌듯합니다. 실제 실습해보고 성능 측정하고 결과를 분석해보는 재미도 있었습니다. 그리고 WebPageTest를 사용해본건 이번이 처음인데 꽤나 유용한 거 같습니다.

이미지 최적화와 양대 산맥인 폰트 최적화 실습도 조만간 곧 진행해보도록 하겠습니다.


참고 자료

profile
배움을 좋아합니다. 새로운 것을 좋아합니다.

0개의 댓글