Webpack 3의 Scope Hoisting으로 번들 사이즈 줄이기

문제 상황

운영 중인 서비스의 번들 사이즈가 계속 증가하면서 초기 로딩 속도가 느려지고 있었다. Webpack 2를 사용 중이었는데, 최근 Webpack 3가 릴리즈되면서 Scope Hoisting 기능이 추가되었다는 소식을 접했다.

Scope Hoisting이란

Webpack은 기본적으로 각 모듈을 개별 함수로 감싸서 번들링한다. 이 과정에서 불필요한 함수 래퍼와 클로저가 많이 생성된다. Scope Hoisting은 가능한 경우 모듈들을 하나의 스코프로 합쳐서 이런 오버헤드를 줄여준다.

적용 방법

Webpack 3로 업그레이드 후 production 설정에 플러그인을 추가했다.

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.optimize.ModuleConcatenationPlugin()
  ]
};

ES6 모듈을 사용하고 있어야 제대로 동작한다. Babel 설정에서 modules: false로 설정해 ES6 import/export를 유지했다.

{
  "presets": [
    ["env", {
      "modules": false
    }]
  ]
}

결과

  • 번들 사이즈: 482KB → 410KB (약 15% 감소)
  • 초기 로딩 시간: 2.3초 → 2.0초
  • Gzip 압축 후에도 체감할 수 있는 차이가 있었다

빌드 시간은 큰 변화가 없었다. Webpack 3 업그레이드 자체는 큰 breaking change 없이 순조로웠다.

주의사항

CommonJS 모듈이 섞여 있으면 해당 모듈은 concatenation 대상에서 제외된다. webpack --display-optimization-bailout 옵션으로 어떤 모듈이 제외되었는지 확인할 수 있다.

당장 큰 리팩토링 없이 적용 가능한 최적화 방법이라 추천한다.