DEV Community

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

Posted on • Edited on

2 1 1

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)

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs