
빌드하는 중에 이런 경고 메시지가 떴다.
이 경고는 빌드 프로세스 중에 몇몇 청크(코드 묶음)가 최소화된 후에도 여전히 500kB를 초과한다는 것을 알리는 메시지라고 한다.
큰 프로젝트도 아닌데 빌드 시간이 11.66s ... ... .

어떤 것이 문제인지 확인하기 위해 rollup-plugin-visualizer로 번들의 크기를 시각적으로 확인해 보았다.
아까 문제가 되었던 index.js에서는 firebase가 많은 부분을 차지하고 있고, EventDetail.js에서는 refractor가 많은 부분을 차지하고 있는 것을 알 수 있다.
firebase 라이브러리가 상당히 큰 공간을 차지하고 있는 것을 알 수 있다.
그래서 검색해 봤는데 firebase 공식 문서에서 제안한 방법들은 나는 vite를 사용하고 있기 때문에 이미 적용이 되고 있었다…….
// before
import { doc, getDoc, setDoc, updateDoc } from 'firebase/firestore';
// after
import { doc, getDoc, setDoc, updateDoc } from 'firebase/firestore/lite';
일단 실시간 업데이트가 필요하지 않은 서비스는 firestore/lite를 사용하면 번들 사이즈를 좀 줄일 수 있다고 하여 해당 코드를 수정하였다.
dist/assets/index-D1u2acml.js 746.35 kB │ gzip: 205.89 kB
dist/assets/EventDetail-BHVjT0o1.js 1,050.32 kB │ gzip: 362.96 kB
✓ built in 7.04s
index.js가 처음 빌드 시에
935.29 kB였던 것이746.35 kB가 되었다.
built 시간이11.66s에서7.04s가 되었다.어느 정도 성공!
동적 import를 이용한 코드 스플리팅
터미널 메시지에서 제안해 준 방법대로 Using dynamic import() to code-split the application를 적용해 보았다.
동적 import로 수정한 컴포넌트의 기준은 사용자가 특정 동작을 수행할 때만 필요할 수 있는 컴포넌트이다.
예를 들어 Main.tsx에서는 사용자가 필터 버튼을 눌렀을 때만 보여지는 컴포넌트인 ModalCategory와 ModalPrice, 그리고 에러가 났을 때만 보여지는 컴포넌트인 ErrorBox를 동적 import로 수정했다.
const ErrorBox = lazy(() => import('@shared/ErrorBox'));
const ModalCategory = lazy(() => import('@components/main/ModalCategory'));
const ModalPrice = lazy(() => import('@components/main/ModalPrice'));
dist/assets/index-AaaZZaCI.js 739.39 kB │ gzip: 203.56 kB
dist/assets/EventDetail-jb-Hc4l9.js 1,050.70 kB │ gzip: 363.12 kB
✓ built in 7.27s
index.js가
746.35 kB였던 것이739.39 kB가 되었다.
built 시간이7.04s에서7.27s가 되었다......................... 약간 실패.
Rollup의 manualChunks 옵션을 사용하여 청크를 수동으로 분할하는 방법을 적용
빌드 오류에서 제안해 준 방법대로 Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks를 적용해 보았다.
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom', 'react-router-dom'],
firebase: [
'firebase/app',
'firebase/auth',
'firebase/firestore',
'firebase/storage',
'firebase/analytics',
],
ui: [
'@radix-ui/react-alert-dialog',
'@radix-ui/react-avatar',
'@radix-ui/react-checkbox',
'@radix-ui/react-dropdown-menu',
'@radix-ui/react-label',
'@radix-ui/react-popover',
'@radix-ui/react-radio-group',
'@radix-ui/react-select',
'@radix-ui/react-slot',
'@radix-ui/react-tooltip',
],
syntaxHighlight: ['refractor'],
},
},
},
},
// ... 생략
});
dist/assets/index-C8WAEFox.js 280.67 kB │ gzip: 78.15 kB
dist/assets/EventDetail-B6b9m9S7.js 937.60 kB │ gzip: 323.21 kB
✓ built in 7.62s
index.js가
739.39 kB였던 것이280.67 kB가 되었다.
EventDetail.js도1,050.70 kB였던 것이937.60 kB가 되었다.
built 시간이7.27s에서7.62s가 되었다.성공.

하지만 아직도 EventDetail은 개선이 필요하다. 별도의 청크로 분리를 시도하였으나 의도와는 다르게 refractor가 여전히 초기 로딩 시 로드되고 있는 중이다.
라이브러리 교체를 통한 번들 최적화
ChatGPT에 물어보니 다른 라이브러리(@uiw/react-md-editor)에서 내부적으로 refractor를 사용하고 있기 때문에 여전히 번들 크기에 영향을 미치고 있다는 것 같았다.
그래서 나는 refractor를 사용하지 않고 훨씬 더 가벼운 react-markdown로 라이브러리를 대체하였다.
dist/assets/index-Cb2yEKZa.js 280.60 kB │ gzip: 78.10 kB
dist/assets/EventDetail-BT16ARb2.js 122.06 kB │ gzip: 38.05 kB
✓ built in 6.15s
index.js가
280.67 kB였던 것이280.60 kB가 되었다.
EventDetail.js도937.60 kB였던 것이122.06 kB가 되었다.
built 시간이7.62s에서6.15s가 되었다.성공.
최종적으로는 웹 애플리케이션의 빌드 시간을 기존 11.66초에서 6.15초로 단축, 47% 개선을 달성하였다!
사용자 경험 향상과 서버 리소스 효율성 증가에 기여하게 된 것이다.