light house 지표에 따른 리액트 최적화

JONGEE KIM·2024년 1월 26일
1

리액트 최적화

목록 보기
1/2
post-thumbnail

회사에서 제작한 청소년 금연 관련 admin을 리팩토링 하는 과정에서 light house 지표 성능 최적화를 진행해보고 싶어졌습니다.

최적화를 진행하기 전 성능 지표는 61점으로 낮은 수준으로 LCP와 FCP가 각각 3.4초인 것을 확인할 수 있었습니다.

LCP(Largest Contentful Paint, 최대 콘텐츠풀 페인트)란?

로딩 성능을 측정하는 지표로서, 사용자가 웹 페이지를 로드할 때 뷰포트 내에 있는 가장 큰 이미지 또는 텍스트 블록이 브라우저 화면에서 얼마나 빨리 렌더링 되는지 측정하는 지표이다.
좋은 사용 경험을 제공하기 위해서는 페이지가 처음으로 로딩된 후 2.5초 이내에 LCP 가 발생해야 한다.

FCP(First Contentful Paint)란?

첫 번째 콘텐츠가 렌더링 되기 시작하는 시점을 측정하는 지표

LCP는 주로 하기 4가지 요인에 의해 영향을 받는다고 합니다.

  • 느린 서버 응답 시간
  • 렌더링 차단 Javascript 및 CSS
  • 리소스 로드 시간
  • 클라이언트 측 렌더링

1. Lazy Loading과 Suspense를 이용한 code spliting


코드 스플리팅은 큰 번들을 여러 작은 청크(chunk)로 분할하는 프로세스입니다. 이는 초기 로딩 속도를 개선하는 데 도움을 줍니다. React.lazy()는 동적 import를 사용하여 컴포넌트를 로드합니다. 동적 import를 사용하면 컴포넌트를 비동기적으로 로드할 수 있습니다.

const Component = React.lazy(() => import('./Component'));

function App() {
  return (
    <div>
      {/* Suspense 컴포넌트로 Component를 감싸고, 로딩 중에 표시할 UI를 정의합니다. */}
      <React.Suspense fallback={<div>loading</div>}>
        <Component />
      </React.Suspense>
    </div>
  );
}

export default App;

router에 정의된 대시보드 컴포넌트를 모두 lazy Loading을 이용해 코드 스플리팅을 진행하였고, LCP가 3.4초에서 2.7초로, FCP 또한 3.4초에서 2.5초로 줄어든 것을 확인할 수 있었습니다.

2. 자바스크립트 번들에서 중복 모듈 삭제


yarn-deduplicate 명령어를 통해 번들 사이즈를 줄일 수 있습니다.

구글 light house 지표가 자바스크립트 번들에 존재하는 중복모듈이 3KiB이라고 알려주고 있습니다. (1 키비바이트는 1.024 킬로바이트이다.)

// yarn-deduplicate 설치
$ yarn global add yarn-deduplicate

// cd 프로젝트_경로
$ yarn-deduplicate yarn.lock

적용하고 청크파일에서 3KiB가, yarn.lock 파일에서 1601줄의 코드가 줄어든 것을 확인할 수 있었습니다.

yarn-deduplicate 참고 글
yarn global 실행 시 command not found 해결 방법

3. Fontsource로 웹폰트 직접 호스팅


기존에는 Google Fonts를 이용해 웹폰트를 호스팅하였는데 @fontsource npm 패키지로 웹폰트를 직접 호스팅하면, 웹폰트 다운로드로 인한 지연을 최소화하여 LCP와 FCP 지표를 향상 시킬 수 있습니다.

$ yarn add @fontsource/public-sans

모든 컴포넌트에서 다운 받은 웹 폰트를 이용할 수 있도록 import 문을 최상위 컴포넌트에서 위치시켜줍니다.
프로젝트에서 사용하는 글꼴 굵기와 스타일만 명시하여 불러와 최적화를 진행할 수 있습니다.

// src/App.tsx

import '@fontsource/public-sans/400.css';
import '@fontsource/public-sans/500.css';
import '@fontsource/public-sans/600.css';
import '@fontsource/public-sans/700.css';

4. 이미지 webp로 최적화


로고 이미지를 2x 크기로 최적화하고, png 파일을 구글에서 권장하는 확장자인 webp으로 변환하여 LCP 50 밀리초를 개선했습니다.

5. dead code 삭제하기


프로젝트 내의 미사용 코드를 찾기 위해 ts-prune을 설치해줍니다.

// 설치
$ yarn add -D ts-prune

// used in module인 부분과 default export로 사용된 부분을 제외하고 출력 
$ npx ts-prune | grep -E -v '(used in module)|default'

ESM(ES Module)내에서 사용하지 않는 변수, 함수들을 확인할 수 있으며 데드 코드를 삭제하는 과정을 거쳤습니다.

데드코드 정리하기 참고 글

최적화 결과


해당 다섯가지 최적화를 진행하고 성능 지표는 61점 => 75점, LCP는 3.4초 => 2.4초, FCP는 3.4초 => 2.1초, Speed Index도 3.4초 => 2.1초로 개선된 것을 확인할 수 있었습니다.

LCP가 2.5초 아래로 줄어든 것은 유의미한 변화라고 생각하며 아직 성능 지표가 75점으로 아쉬운 수준이라, 추가적으로 최적화할 수 있는 방법을 찾아보려고 합니다.

profile
Code On Paper 📝

0개의 댓글