6.15 ECMAScript6 - Babel + Webpack

Babel 6와 Webpack 3를 이용한 ES6 환경 구축

babel-webpack

현재 브라우저는 ES6를 완전하게 지원하지 않는다.

es6-browser-support

ECMAScript 6 Browser Support

특히 모듈의 경우, 모듈 로더가 필요하다. 트랜스파일러(Transpiler) Babel과 모듈 번들러(Module bundler) Webpack을 이용하여 ES6로 작성된 코드를 IE를 포함한 모든 브라우저에서 문제없이 동작시키기 위한 환경을 구축하여 보자. 본 문서에서 사용한 Babel과 Webpack의 버전은 아래와 같다.

  • babel-cli : 6.26.0
    • babel-loader : 7.1.2
    • babel-preset-env : 1.6.0
  • webpack : 3.5.5
  • npm : 5.3.0

1. Babel CLI 설치

Babel은 트랜스파일러(Transpiler)로서 ES6를 ES5 이하의 버전으로 트랜스파일링한다.

npm을 사용하여 Babel CLI을 설치한다.

프로젝트별로 설정이 다를 수 있으므로 전역으로 설치하지 말고 로컬로 설치하도록 한다.

$ mkdir babel-project && cd babel-project
$ npm init -y
$ npm install babel-cli --save-dev

설치가 완료된 후 package.json은 아래와 같다. 불필요한 설정은 삭제하였다.

{
  "name": "babel-project",
  "version": "1.0.0",
  "devDependencies": {
    "babel-cli": "^6.26.0"
  }
}

2. .babelrc 설정 파일 작성

Babel의 사용을 위해서는 먼저 preset을 설치가 필요하다. env preset은 설정된 환경에 적합한 플러그인을 자동으로 설정해준다.

$ npm install babel-preset-env --save-dev

설치가 완료된 후 package.json은 아래와 같다.

{
  "name": "babel-project",
  "version": "1.0.0",
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.0"
  }
}

설치가 완료되었으면 .babelrc 파일을 아래와 같이 작성한다.

{
  "presets": ["env"]
}

3. 트랜스파일링

ES6를 트랜스파일링하기 위해 Babel CLI 명령어를 사용할 수도 있으나 npm scripts를 사용하여 트랜스파일링하는 방법에 대해 알아보도록 하자.

package.json 파일에 scripts를 추가한다. 완성된 package.json 파일은 아래와 같다.

{
  "name": "babel-project",
  "version": "1.0.0",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.0"
  }
}

위 npm scripts는 src/js 폴더의 ES6를 트랜스파일링한 후, dist/js 폴더에 저장한다.

-w
파일 변경을 감지하여 자동으로 트랜스파일한다. (--watch 옵션의 축약형)
-d
출력 파일이 저장될 폴더를 지정한다. (--out-dir 옵션의 축약형)

이제 트랜스파일링을 실행하기 위해 ES6 파일을 작성해 보자. 프로젝트 루트에 src 폴더를 생성한 후 main.js와 lib.js를 추가한다.

// src/js/main.js
import { pi, square, Person } from './lib';
console.log(pi);
console.log(square(10));
console.log(new Person('Lee'));
// src/js/lib.js
export const pi = Math.PI;

export function square(x) {
  return x * x;
}

export class Person {
  constructor(name) {
    this.name = name;
  }
}

트랜스파일링을 실행한다.

$ npm run build

프로젝트 루트에 dist/js 폴더가 생성되고 트랜스파일링된 main.js와 lib.js가 저장된다.

트랜스파일링된 main.js를 실행하여 보자. 결과는 아래와 같다.

$ node dist/js/main
3.141592653589793
100
Person { name: 'Lee' }

4. Webpack과 Babel을 이용한 ES6 환경 설치

앞에서 main.js와 lib.js 모듈을 트랜스파일한 후에 트랜스파일링된 main.js을 실행한 결과, 문제없이 실행되는 것을 확인하였다. 이것은 node.js 환경에서 실행한 것이다. node.js는 CommonJS 방식의 module loading system을 기본으로 지원한다.

현재 대부분의 브라우저는 ES6의 모듈을 지원하지 않고 있다. 따라서 ES6 모듈을 현재의 브라우저에서 사용하기 위해서는 RequireJS 또는 SystemJS와 같은 모듈 로더가 필요하다.

Webpack은 의존 관계에 있는 모듈들을 하나의 자바스크립트 파일로 번들링하는 모듈 번들러이다. Webpack을 사용하면 의존 모듈이 하나의 파일로 번들링되므로 별도의 모듈 로더가 필요없다.

Webpack

Webpack

Webpack과 Babel을 이용하여 ES6 환경을 설치하여 보자.

hello.js, world.js, entry.js 모듈을 작성한다. hello.js와 world.js는 entry.js에 의해 import되는 의존 모듈이다.

// src/js/hello.js
export default 'Hello';
// src/js/world.js
export default 'world';
// src/js/entry.js
import hello from './hello';
import world from './world';

document.getElementById('demo').innerHTML = `${hello}, ${world}!`;

Babel을 사용하여 트랜스파일링을 실행한다.

$ npm run build

이제 프로젝트 루트에 index.html을 생성하고 트랜스파일링된 자바스크립트 파일을 로드한다.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Babel Demo</title>
  <script src="./dist/js/hello.js" defer></script>
  <script src="./dist/js/world.js" defer></script>
  <script src="./dist/js/entry.js" defer></script>
</head>
<body>
  <h1>Babel Demo</h1>
  <div id="demo"></div>
</body>
</html>

index.html을 브라우저에서 불러오면 아래와 같이 에러가 발생한다.

module error

모듈 로딩 실패

이는 브라우저에서 CommonJS 모듈을 사용하려고 시도하였으나 실패한 것이다. 이제 Webpack을 사용하여 보자.

Webpack을 설치한다.

$ npm install webpack --save-dev

설치가 완료된 후 package.json은 아래와 같다.

{
  "name": "babel-project",
  "version": "1.0.0",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.0",
    "webpack": "^3.5.5"
  }
}

Webpack이 모듈을 번들링할 때 Babel을 사용하여 트랜스파일링을 실행하도록 babel-loader를 설치한다.

$ npm install babel-loader --save-dev

package.json 파일의 scripts를 변경한다. 완성된 package.json 파일은 아래와 같다.

{
  "name": "babel-project",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack -w"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "webpack": "^3.5.5"
  }
}

프로젝트 루트에 webpack.config.js을 생성하고 아래와 같이 수정한다.

var path = require('path');

module.exports = {
  entry: {
    entry: './src/js/entry.js'
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist/js')
  },
  module: {
    rules: [{
      test: /\.js$/,
      include: [
        path.resolve(__dirname, 'src/js')
      ],
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['env']
        }
      }
    }]
  },
  devtool: 'source-map'
};

이제 Webpack을 사용하여 번들링을 실행한다. 이때 Babel 또한 실행된다.

$ npm run build

실행 결과 dist/js 폴더에 bundle.js이 생성되었다. 이 파일은 hello.js, world.js, entry.js 모듈이 하나로 번들링된 결과물이다.

index.html을 아래와 같이 수정하고 브라우저에서 로드하여 보자.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Babel Demo</title>
  <script src="./dist/js/bundle.js" defer></script>
</head>
<body>
  <h1>Babel Demo</h1>
  <div id="demo"></div>
</body>
</html>

module success

모듈 로딩 성공!

hello.js, world.js, entry.js 모듈이 하나로 번들링된 bundle.js가 브라우저에서 문제없이 실행된 것을 확인할 수 있다.

Reference

Back to top
Close