[React]최적화 1편 - 코드 분할

Jinjer·2021년 12월 21일
0
post-thumbnail

1. 프롤로그

어떻게 하면 빠르게 되는건데?🤔

내가 만든 서비스의 성능을 개선해 보고 싶다면
성능을 끌어올릴 수 있는 것에는 어떠한 방법들이 있는지 알아야 한다

대표적인 성능 최적화 방법

  1. 코드 분할
  2. 코드 리팩토링
  3. 코드 압축&난독화
  4. 리소스 줄이기
  5. 리렌더링 방지
  6. 트리쉐이킹
  7. 레이아웃 스래싱 회피

너무도 많다!!
그러나 해야만 한다😭

오늘은 저 중에서 코드 분할만 다뤄보겠다

2. 코드 분할

코드 분할(Code-Splitting)이란 브라우저가 페이지를 렌더링하기 위해
리소스를 다운받아야 하나 한 번에 전부 받는 것이 아니라
화면 구성에 필요한 부분만 잘라내어 다운로드 하는 작업을 말한다

그렇다면
리액트에서는 어떤 방법으로 코드 분할을 할 수 있을까?🍕

2-1. React.lazy

React 자체에 내장되어 있는 React.lazy를 사용하자
React.lazy는 공식문서에 의하면 라우터에서 적용하는 것이 좋다고 한다

import React, { Suspense } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

const Home = React.lazy(() => import("./routes/Home"));
const About = React.lazy(() => import("./routes/About"));

const App = () => (
  <BrowserRouter>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route exact path="/" element={<Home />} />
        <Route path="/about" element={<About/>} />
      </Routes>
    </Suspense>
  </BrowserRouter>
);

확인을 위해 서버를 구동한 뒤 F12!!
path를 변경해보면 0.chunk.js와 1.chunk.js로 각각 코드가 분할되어
해당된 파일만 생성된 것을 확인할 수 있다

일반적인 import 구문을 사용하여 컴포넌트를 렌더링 하고 있다면
이제 React.lazy를 사용하여 동적 import 해보자

잠깐
React.lazy와 Suspense는 아직 서버 사이드 렌더링을 지원하지 않는다
서버에서 렌더링하는 Next.js와 같은 앱에서 코드분할을 하고 싶다면 Loadable Components를 사용하자

2-2. React dynamic import

동적 import를 고차컴포넌트(HOC)로 만들어 사용하고 싶다면
ReactDynamicImport를 써보는 것도 좋다

import ReactDynamicImport from "react-dynamic-import";

const Content = ({children, template}) => (
  const loader = () => import("./templates/" + template));
  const DynamicComponent = ReactDynamicImport({loader});
  
  return (
    <>
    	{template === undefined ? (children) : (
        <DynamicComponent />
        )}
    </>
  );
}

코드 분할은 이러한 방식으로 적용하면 된다. 끝~!
.
.
.

그러나 겉핡기만 하는 개발자가 안되려면 실제로 적용해보고
분석하고 개선해야만 성장할 수 있기에...

3. 실전 적용기

이번에 개발한 세금계산서 발행 서비스에도 코드 분할을 적용하였으나
메인페이지 렌더링에만 1190ms이 걸리는 수치수러움을 경험했다

Lighthouse 측정결과...
Perfomance 영역에서 51점이라는 충격적인 성적표를 받았다
물론 측정환경에 따라 결과가 다른점을 감안하더라도 좋지 못한 성적이다

3-1. 문제점

트리맵 분석 결과
전자서명과 출력을 위한 외부 모듈이 전체 스크립트의 52%를
차지하고 있어 그 외에 48%의 스크립트를 개선해 보고자 하였다

해결해야 할 과제
1. 코드 분할 더 효과적으로 개선하기
2. 렌더링에 방해되는 리소스 제거
3. 압축파일 용량 줄이기

3-2. 해결방안

React.lazy를 이용하여 페이지별로 청크 파일을 나눈다고 해도
해당 페이지에 접근 했을 때 숨겨진 컴포넌트까지 포함되기 때문에
보여지는 화면 렌더링에만 집중할 수 있도록 하고 싶었다🤔

좋은 방법이 없을까 하다가 나와 같은 고민을 한 누군가가
requestIdleCallBack을 사용하여 성능 개선한 사례가 있어 참고 하였다

requestIdleCallBack는 브라우저의 메인 스레드의 빈 공간(대기 기간)에 지정한 콜백 함수를 실행시킬 수 있는 함수로
Lazy Loading이 가능한 컴포넌트에 적용해야 올바른 결과를 얻을 수 있다

참고 원문: https://engineering.linecorp.com/ko/blog/line-securities-frontend-4/

4. 정리

✔ 렌더링이 이전보다 확실히 개선되었다
✔ 사용자경험을 유지하기 위해 라우터에 적용하는 것을 추천
✔ SSR 환경에서는 Loadable Components를 이용하자

profile
프론트엔드개발자

0개의 댓글