DEV Community

Cover image for Lighthouse를 활용하여 LCP 점수 개선하기.
Heetae Kim
Heetae Kim

Posted on • Edited on

Lighthouse를 활용하여 LCP 점수 개선하기.

필자의 Lighthouse Performance 점수는 이렇다.

Image description

me: 🤦‍♂️

개선해야 할 항목들은 다음과 같다.

Image description

Lighthouse 점수가 웹 성능에 절대적인 성능으로 귀결되지는 않는다. 그렇지만 개발 이후 성능 최적화에 좋은 지표가 되므로 가장 중요한 LCP 점수를 높여 보려고 한다.

LCP(Largest Contentful Paint)

  • 최대 콘텐츠 렌더링 시간 즉, 뷰포트에서 가장 큰 콘텐츠 엘리먼트가 나타날 때 측정한다.
  • 페이지의 주요 내용이 화면에 렌더링이 완료되는 시기를 결정하는데 사용된다.

 

이미지 최적화

Largest Contentful Paint element - 12,350ms

현재 콘텐츠에 이미지를 포함하고 있으며, 이미지는 LCP에 큰 영향을 미칠 수 있기 때문에 이미지를 최적화하고 적절한 포맷을 사용하는 것이 중요하다고 한다.

적절한 포맷 사용

  • JPEG, PNG 대신 WebP 로 최신 포맷을 사용하여 개선 시도.

이미지 크기 최적화

  • 불필요하게 큰 이미지를 줄이고 필요한 크기만 사용.
  • 이미지 가로 크기를 1200px -> 400px 로 수정 (비율 유지)

지연 로드

  • 화면에 보이지 않는 이미지들은 lazy-loading 하여 불필요한 렌더링이 발생하지 않도록 시도. ```html

example image


**결과**
- Before
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7svr849j8j9kzeurn0p.png)

- After
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yeepe9p8ydx79g2ic994.png)

Load Delay는 `9,507ms` -> `6,060ms` 으로 약 `37%` 개선되었으며, 
Load Time도  `3,740ms` -> `2,380ms` 으로 약 `37%` 개선되었다.

 

## 폰트 최적화

**Enable text compression - Potential savings of 9,691 KiB**

다음으로는 웹 폰트 로딩이 페이지 렌더링을 차단하지 않도록 최적화를 수행하였다.

`font-display: swap` 속성을 사용하여 폰트 로딩 중에도 텍스트가 표시되도록 하였다.
```css


@font-face {
    font-family: "Noto Sans KR", sans-serif;
    src: url(https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300..600) format("woff2");
    font-display: swap;
  }


Enter fullscreen mode Exit fullscreen mode

swap은 웹폰트가 로드되기 전에 사용자에게 기본 시스템 폰트로 텍스트를 표시합니다. 그리고 웹폰트 로딩이 완료되면 텍스트가 웹폰트로 교체된다. 이 방식은 사용자 경험을 향상시키는 데 일반적으로 사용되는 값이라고 한다.

 

JavaScript 최적화

Minify JavaScript - Potential savings of 2,832 KiB

JavaScript 파일이 크거나 로딩이 차단되면 LCP에 악영향을 미칠 수 있다고 한다.
그래서 찾은 개선 방법으로 코드 분할(Code Spliting)과 지연 로딩(Lazy-Loading)이 있다고 한다.

코드 분할 및 지연 로드

  • 필자는 이미 이전에 현재 사용자가 보는 페이지에 따라 필요한 JavaScript 파일을 다운로드 받도록 하기 위해 React의 lazy함수를 통해 지연 코드 분할을 수행하였다. ```tsx

lazy(() => import('some-large-module').then(module => {
// Use the module
}));


### 사용하지 않는 모듈 제거
추가적으로 수행한 최적화 방법으로 사용하지 않는 JS 및 모듈 파일들을 제거하거나 최소화 하였다. 이유는 필요 없는 파일들을 다운 받는 과정에서 필수적인 다운로드가 blocking 으로 지연되면 LCP 역시 저하될 수 있기 때문이다.

무거운 라이브러리를 Spread로 import 하지 않고 필요한 모듈만 import 하여 가져와 사용하도록 수정하였다. -> [블로그 글 참고](https://dev.to/hxxtae/lighthousereul-hwalyonghan-tree-shaking-8ie)

 

## Vite 설정 파일 수정

이전 까지의 최적화를 수행하여도 LCP의 점수에는 큰 영향이 없었다. 그래서 ChatGPT한테 추가적인 방법을 물어보았더니 다음과 같은 방법을 제시해 주었다.

> `vite-plugin-compression`을 사용하여 Vite 설정을 통해 빌드된 파일을 미리 압축하는 방법으로 LCP를 단축 시킬 수 있다. 
> 이는 빌드된 파일을 `Gzip` 및 `Brotli` 형식으로 미리 압축하여 서버가 이를 효율적으로 제공할 수 있도록 한다.

### vite-plugin-compression 설치
```bash


npm install vite-plugin-compression --save-dev


Enter fullscreen mode Exit fullscreen mode

Vite 설정 파일 수정 (vite.config.js)



// vite.config.js
import compression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [
    react(),
    compression({ algorithm: 'gzip' }), // Gzip 압축 활성화
    compression({ algorithm: 'brotliCompress', ext: '.br' }) // Brotli 압축 활성화
  ]
});


Enter fullscreen mode Exit fullscreen mode

위 설정을 저장한 후 프로젝트를 빌드하면 Gzip 및 Brotli 형식으로 압축된다.

 

최종결과

Image description

결과는 드라마틱 하지 않았지만 전반적으로 개선된 것을 확인할 수 있다.

FCP : 6.8s -> 5.1s
LCP : 12.4s -> 8.7s
TBT : 30ms -> 0ms
CLS : 0.001
SI : 7.5s -> 5.5s

그럼 왜 점수가 많이 오르지 않을까? 이 사실을 같은 항해99 멤버인 원민님에게 답을 얻을 수 있었다.

일반적으로 개발 환경에서는 디버깅을 쉽게 할 수 있도록 여러가지 추가적인 리소스를 요청하는데 이것이 Lighthouse 점수에 계산되기 때문이다.

여기에서 말하는 리소스라는 것은 개발 과정에서 발생한 오류를 추적할 수 있는 로그 같은 로직적인 부분일 수 있고, 디버깅 시 정확한 코드 위치를 판단할 수 있는 소스맵 같은 파일일 수도 있다.

그래서 프로덕션 빌드 시 이와 같은 파일들은 사용자에게 제공할 필요가 없고 성능 최적화를 위해 리소스들이 모두 빠지게 되므로 프로덕션 환경에서는 개발 환경 보다 성능 상 이점을 누릴 수 있을 것이며 Lighthouse Performance 점수 또한 높을 것이다.

Image description

Lighthouse 점수를 개선해야 한다면, 최종 사용자 입장에서 볼 수 있는 프로덕션 환경에서 개선하는 것이 더 적절하다고 할 수 있다.

 

마무리

LCP를 개선하는 과정을 통해서 얻은 내용을 정리하면 이렇다.

  • Lighthouse 실행 시점 마다 점수의 격차가 크다.
  • 최적화된 이미지를 저장하고, 불러오고, 보여주는 것이 LCP에 영향이 크다.
  • vite.config.js 에서 크기가 큰 모듈들을 코드 분할하여 불필요한 JS를 제거해 주는 것으로도 LCP 향상에 도움이 된다.
  • Lighthouse 측정은 프로덕션 환경에서 진행하는 것을 권장한다.
  • LCP는 데이터가 불러오는 속도에 영향을 많이 받기 때문에 SSR 방식도 고려하면 좋을 것 같다.

앞서 말했던 것 처럼 LCP 점수가 절대적이거나 중요한 것은 아니다. 하지만 높은 점수는 사용자에게 좋은 경험을 제공하는 것은 분명하다.

그리고 LCP 시간은 2.5s 이하면 좋다고 한다. 앞으로 최적화를 진행할 때 기준을 두고 진행하면 좋을 것 같다.

긴 글 읽어주셔서 감사합니다.


[참고한 글]
Lighthouse를 기반으로 LCP 성능 개선하기
Light House에서 LCP 측정항목 개선해서 성능점수 올리기
라이트하우스와 함께한 성능 개선 고군분투기
내가 프로젝트에서 최적화를 진행했던 방법들 (With React+Vite)

Top comments (0)