프로젝트를 실제로 배포할 때는, 우리는 작성한 코드를 빌드한 후에 웹서버를 통해서 배포를 하게 된다.
리액트는 기본적으로 SPA 방식이기 때문에, MPA와 달리 하나의 index.html파일을 사용합니다. 또한 이때 JS파일을 모두 로딩합니다. 그렇기 때문에 페이지가 많아 질수록, 프로젝트 규모가 커질수록 해당 파일의 크기가 커지고 초기 로딩속도가 느려지게 됩니다.
이때 초기 로딩 속도를 늘리기 위한 방법 중 하나로 Tree Shaking이라는 방법이 있습니다.
Tree Shaking이란 불필요한 코드를 제거하는 방법을 의미합니다.
https://github.com/rollup/rollup?tab=readme-ov-file#tree-shaking
1. 번들사이즈 분석하기
Tree Shaking이 효과적으로 적용되었는지 확인하기 위해서, https://www.npmjs.com/package/webpack-bundle-analyzer
webpack-bundle-analyzer
Webpack plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. Latest version: 4.10.1, last published: a month ago. Start using webpack-bundle-analyzer in your project by running `npm i webpack-bundle-analyzer`. T
www.npmjs.com
위 라이브러리를 통해서 각각의 JS파일이 얼만큼의 용량을 먹고 있고, Tree Shaking 이후 얼만큼 감소하는 지를 확인할 것 입니다.
해당 라이브러리를 개발자 의존성에 추가한 이후, config 파일에 아래 코드를 추가해 줍니다.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
저는 webpack 대신에 craco를 사용하여서 craco.config.js에 아래와 같이 코드를 추가했습니다.
const CracoAlias = require('craco-alias')
// webpack-bundle-analyzer를 추가하고, 개발환경에서만 실행하도록 함
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
source: 'tsconfig',
tsConfigPath: 'tsconfig.paths.json',
},
},
],
babel: {
presets: [['@babel/preset-react', { runtime: 'automatic', importSource: '@emotion/react' }]],
plugins: ['@emotion/babel-plugin'],
},
// 아래 부분
webpack: {
plugins: isProduction ? [] : [new BundleAnalyzerPlugin()],
},
}
이후 프로젝트를 시작하면, 아래와 같은 창이 생깁니다.

각각의 javascript 파일의 크기를 확인할 수 있으며, 저는 lodash 파일을 트리쉐이킹해서 크기를 줄일 것 입니다.
우선 빌드된 파일의 크기를 확인해보면 아래와 같습니다.

이후 Tree Shaking을 통해서 감소시키면 됩니다.

2. 트리쉐이킹 원리

위의 표를 통해서 간단하게 CJS 와 ESM의 차이를 알 수 있는데, 이때 주목해야할 점은 로딩방식의 차이점입니다.
CJS에서는 로딩이 동적이고 분석시점이 런타임이기에 빌드시에 필요성에 대한 유무를 명확히 알기 힘들지만, ESM은 정적입니다. 따라서 저희는 ESM 방식을 통하여서 필요한 코드들만 import 하여 사용할 수 있습니다.
저는 프로젝트에서 flatten 이외의 lodash의 기능을 사용하지 않았습니다. 따라서 lodash를 전체를 import 하는 것은 불필요한 코드를 많이 사용하게 됩니다.
https://www.npmjs.com/package/lodash
lodash
Lodash modular utilities.. Latest version: 4.17.21, last published: 3 years ago. Start using lodash in your project by running `npm i lodash`. There are 179589 other projects in the npm registry using lodash.
www.npmjs.com
따라서 기존 CJS의 lodash (위의 라이브러리) 대신에 lodash-es라는 라이브러리를 사용하는 것이 좋고, 더 나아가 flatten이라는 함수만 제공하는 lodash.flatten 라이브러리를 사용하여 트리쉐이킹을 진행할 것 입니다.
(lodash의 많은 유틸리티 함수를 사용한다면, lodash-es를 사용하고 , 저는 lodash flatten을 설치하였습니다.
https://www.npmjs.com/package/lodash.flatten
lodash.flatten
The lodash method `_.flatten` exported as a module.. Latest version: 4.4.0, last published: 7 years ago. Start using lodash.flatten in your project by running `npm i lodash.flatten`. There are 871 other projects in the npm registry using lodash.flatten.
www.npmjs.com
https://www.npmjs.com/package/lodash-es
lodash-es
Lodash exported as ES modules.. Latest version: 4.17.21, last published: 3 years ago. Start using lodash-es in your project by running `npm i lodash-es`. There are 9670 other projects in the npm registry using lodash-es.
www.npmjs.com
해당 라이브러리를 설치한 이후 기존의 import 문을 변경해주면 됩니다.
// import { flatten } from 'lodash'
import flatten from 'lodash.flatten'
자세한 CJS와 ESM의 차이를 알고 싶다면 카카오 기술블로그에서 내용을 읽어 보시는 것도 좋을 것 같아요.
https://tech.kakao.com/2023/10/19/commonjs-esm-migration/
CommonJS에서 ESM으로 전환하기
안녕하세요, FE플랫폼팀에서 FE 개발자를 위한 개발을 담당하는 Ethan입니다. 이 글에서는 운영 중인 서비스에서 사용하는 라이브러리의 버전을 업그레이드하는 과정에서, 기존에 사용하던 모듈
tech.kakao.com
'프론트엔드 > 최적화' 카테고리의 다른 글
react-helmet-async 활용하여 동적으로 메타데이터 처리하기( SEO최적화) (1) | 2024.01.13 |
---|---|
React lazy,와 Suspense를 활용하여 Code Splitting 하기 (0) | 2024.01.12 |
Skeleton UI 로 Layout Shift 관리하기 (0) | 2023.12.25 |
React useState 초기값 함수로 할당시 최적화 (1) | 2023.12.22 |
react input에 랜더링 제어를 위한 디바운스 커스텀훅 만들기 (0) | 2023.08.31 |