Webpack 3에서 Code Splitting 최적화한 경험

문제 상황

사내 어드민 페이지의 번들 사이즈가 2.3MB까지 커지면서 초기 로딩에 7~8초가 걸리는 상황이 발생했다. 특히 네트워크가 느린 환경에서는 사용이 거의 불가능한 수준이었다.

해결 과정

1. 번들 분석

webpack-bundle-analyzer를 설치해 번들 구성을 확인했다.

npm install --save-dev webpack-bundle-analyzer

moment.js의 locale 파일들과 lodash 전체가 포함되어 있었고, 차트 라이브러리도 모든 페이지에서 로드되고 있었다.

2. CommonsChunkPlugin 설정

module.exports = {
  entry: {
    app: './src/index.js',
    vendor: ['react', 'react-dom', 'redux', 'react-redux']
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: Infinity
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    })
  ]
};

3. Dynamic Import 적용

차트 페이지처럼 특정 라우트에서만 사용하는 무거운 라이브러리는 동적 임포트로 분리했다.

// Before
import ChartComponent from './components/Chart';

// After
const ChartComponent = () => import('./components/Chart');

4. Moment.js locale 제거

plugins: [
  new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]

결과

  • 초기 번들: 2.3MB → 680KB
  • 초기 로딩 시간: 7.8초 → 4.2초
  • vendor 번들 캐싱으로 재방문 시 로딩 시간 대폭 감소

배운 점

Webpack 3의 CommonsChunkPlugin은 설정이 직관적이지 않아 문서를 여러 번 읽어야 했다. 특히 manifest 청크를 별도로 분리하지 않으면 vendor 해시가 앱 코드 변경 시마다 바뀌어 캐싱 효과가 사라진다는 점을 뒤늦게 알았다. 다음에는 초기부터 번들 사이즈를 모니터링하는 게 중요하겠다.