해당 글은
lazy
와code-splitting
,Suspense
을 통한 리액트 성능 최적화에 대한 내용과 실제 프로젝트에 적용해 본 글에 대한 내용입니다.
SPA(Single Page Appliction)의 특성상 맨처음 페이지에 진입하게 되면 웹팩에서 압축한 번들 파일을 다운받게 된다. 즉, 전체 리소스를 한번에 다운받게 된다는 뜻이다.
...
여기서 사용자(클라이언트)는 전체 번들 파일을 다운받기 전 화면을 볼 수 없어 React로 개발된 홈페이지에선 주로 초반에 빈 화면을 보게 될 가능성도 있다. 인터넷 속도가 빠른 한국에서는 큰 문제점을 느끼지 않을 수 있으나 환경이 느린 경우에는 사용자 경험을 저하시키는 요인이 될 수 있다.
...
또한 React 애플리케이션의 규모가 커질수록 메서드, 라이브러리, 유틸리티 크기가 커지게 되고 이는 번들이 커지게 되며 웹 페이지에 방문했을 때 로드해야할 파일의 크기가 커진다는 뜻이고 페이지 성능에 영향을 끼칠 수 있다.
React.lazy
는 컴포넌트의 코드가 처음 렌더링될 때까지 로딩을 연기하게 해주는 기능을 한다. 즉, 필요한 시점에 맞추어 컴포넌트를 로딩하므로 애플리케이션의 성능 향상에 기여할 수 있다.
_
React.lazy
메서드는 번들을 여러chunk
로 나눌 수 있게 해주어 사용자에게 보여주기 위한chunk
만 로딩하고 필요에 따라 청크들을 불러오는 것이다. 이는 초기 번들 크기를 줄여준다. 또한 필요한 데이터만 로드하게 되므로 데이터 사용량을 줄이고 또한 사용자에게 빠른 로딩과 더 빠른 상호작용으로 더 나은 사용자 경험을 제공한다.
사용자(클라이언트)에게 현재 불필요한 코드, 중복되는 코드 없이 적절한 사이즈의 코드가 적절한 타이밍에
동적으로
되도록 하는 것이다.
_
코드를 분할하는 것은 덩치가 큰 번들 파일을 작은 사이즈의 파일로 분할하는 것을 말한다.코드 분할은 코드를 필요에 따라 또는 병렬로 로드할 수 있는 여러 패키지 또는 컴포넌트로 분리하는 것으로 구성된다. 이것은 코드가 필요할 때까지 로드되지 않는다는 것을 의미한다.
컴포넌트가 동적으로 로드되면 어느 순간 아무것도 로드되지 않는 순간이 생기게 된다. 이때 에러를 도출하지 않고 Suspense에 들어오는 컴포넌트를 렌더링 하는 방식이다.
...
Suspense 컴포넌트는fallback
props를 통해 로딩 중일 때의 표시할 JSX를 정의한다.
React.lazy()
를 통해 컴포넌트를 코드 분할할 수 있어 필요한 시점에 컴포넌트를 로드할 수 있고,Suspense
는 로딩 중인 컴포넌트를 처리하기 위해 사용한다.
즉, React.lazy()
와 Suspense
를 같이 사용하면 초기 번들 크기를 줄이고 애플리케이션 로딩 속도를 개선하며, 로딩 중인 상태를 사용자에게 알려주어 사용자 경험 또한 개선할 수 있다.
import { createBrowserRouter } from "react-router-dom";
import Main from "pages/main";
import MakeScrollToTop from "components/MakeScrollToTop";
// import 생략...
const router = createBrowserRouter([
{
element: (
<>
<PrivateRouter>
<MakeScrollToTop />
</PrivateRouter>
</>
),
children: [
{
path: "/",
element: <Main />,
},
// 생략
React.lazy()
와 Suspense
적용import { createBrowserRouter } from "react-router-dom";
import React, { lazy, Suspense } from "react";
const Main = lazy(() => import("pages/main"));
const MakeScrollToTop = lazy(() => import("components/MakeScrollToTop"));
// import 생략...(모든 컴포넌트 lazy() 적용)
const router = createBrowserRouter([
{
element: (
<Suspense fallback={<div>Loading...</div>}>
<>
<PrivateRouter>
<MakeScrollToTop />
</PrivateRouter>
</>
</Suspense>
),
children: [
{
path: "/",
element: <Main />,
},
// 생략
Reduce unused JavaScript
즉, 사용하지 않는 javscript 문구가 뜬다.사용하지 않는 javascript를 로드하면 대역폭이 불필요하게 증가하고 페이지의 첫 번째 페인트(FCP)가 지연되어 전체 페이지 성능이 느려진다.
Reduce unused JavaScript
문구가 사라진 것을 볼 수 있다.코드 분할을 통해 번들된 자바스크립트를 중요한/중요하지 않은 자바스크립트로 나누어 중요한 자바스크립트 먼저 로드 되도록하여 성능을 최적화할 수 있다.
+) 추가로 performance 점수가 약 4점 가량 올랐다..