요즘 JavaScript 관련 프로젝트를 보면 ECMAScript 2015로 대부분 작성하는 것을 볼 수 있고 이 코드는 상당히 깔끔해 져서 얼핏 보면 JavaScript 코드인지 인식 못 할 정도이다. 현재 보통 사용하는 JavaScript는 ECMAScript에 기반을 두고 있는데 정확히는 ECMAScript-262 3번째 에디션을 쓰고 있다. 이런 과거에 대해서는 이전에 쓴 JavaScript.next에 대해서에 자세히 정리되어 있다.
이후 ECMAScript 5를 지나서 ECMAScript 6 에디션(ES6)로 접어들었고 이때부터는 버전 번호를 릴리즈 연도를 사용하기로 해서 ES2015라고 부르므로 ES6와 ES2015는 같다.(참고로 ES7은 ES2016이 될 것이다.) ES2015에서는 언어적으로 큰 변화가 이뤄졌으므로 많은 JavaScript가 ES2015기반으로 갈아타는 상황이다. ES2015에 대한 지원상태는 ES6 호환성 표에 잘 나와 있다.
웹 브라우저 같은 경우는 ES2015의 지원 여부 차이가 큰 편이고 Node.js는 어느 정도 지원하고 있지만 모두 지원하는 것은 아니므로 ES2015로 코드를 작성하면 코드를 트랜스파일 해서 ES5 코드로 바꾸어야 실제로 사용할 수 있다. JavaScript에서는 CoffeeScript처럼 비슷한 부류의 언어를 JavaScript로 바꾸는 것을 트랜스파일이라고 부르고 있고 ES2015의 트랜스파일러(transpiler)로는 구글이 만든 Traceur와 Babel이 있다.
Babel은 원래 6to5라는 이름으로 ES6를 ES5로 바꿔주는 도구로 시작했지만, 인기를 크게 얻고 ES7이나 다른 트랜스파일도 지원하는 포괄적인 도구가 되기 위해 Babel이라는 이름으로 바꾸었다. Traceur과 비교해 본 것은 아니지만 Babel이 인기가 좋기도 하고 ES2015의 지원상태가 아주 좋기 때문에 주로 Babel을 사용하고 있다. 앞에서 얘기한대로 아직 ES2015를 모두 사용할 수 있는 환경이 없으므로 문법을 공부하고 코드를 작성하려면 Babel 같은 도구가 필요한 상황이다.
10월 말에 Babel의 버전이 6.0.0으로 올라왔다. Babel이 6.0이 되면서 각 기능이 모듈화되어 예전에는 Babel을 설치했을 때 많은 기능이 포함되어 있었지만, 이제는 각자 따로 설치해야 한다. 아직 많은 프로젝트가 5.x에 머물러 있고 인터넷에서 문서를 찾아보아도 6.0 이전에 작성된 문서가 대부분이라서 문서대로 따라 해도 제대로 되지 않는 경우가 많고 공식 문서도 아직은 좀 부족한 편이다. 이 글에서는 Babel 6.x를 기준으로 사용한다.
$ npm install -g babel-cli
터미널에서 babel
을 사용하려면 babel-cli를 설치하면 된다. Node.js API를 코드에서 사용하려면 babel-core를 설치하면 된다. 이전에는 babel이라는 패키지를 설치하면 둘 다 가능했지만 6.0부터는 용도에 따라 설치하도록 바뀌었다.
$ babel-node
> var sum = (a, b) => a + b
undefined
> sum(3, 4)
7
babel-cli를 설치하면 babel-node
를 사용할 수 있다. babel-node
는 node
명령어랑 똑같이 생각하면 되는데 위처럼 REPL로 사용할 수도 있고 babel-node example.js
처럼 코드를 실행할 수도 있다. 다른 점이라면 Babel이 내장되어 있어서 코드를 바로 ES5로 트랜스파일 해준다. 그래서 ES2015 코드를 테스트해 보는 데 사용할 수 있다.
babel-node
를 쓰면 편리하기는 하지만 이를 Node.js 런타임 대신 사용하기에는 부담되므로 실제 사용할 때는 ES2015 코드를 ES5 코드로 변환(트랜스파일)한 뒤 이 변환된 코드를 실행해서 사용해야 한다. 이렇게 하면 Node.js가 지원하지 않는 ES2015 코드 뿐만 아니라 웹 브라우저에서도 사용할 수 있다. 이 변환과정을 위해서 앞에 설치한 babel-cli
에서 babel
명령어를 제공한다.
$ babel example.js
var sum = (a, b) => a + b;
console.log(sum(3, 4));
$ babel example.js -d out
example.js -> out/example.js
$ node out/example.js
7
babel 파일명
명령어를 실행하면 해당 JavaScript 코드를 트랜스파일 한다. 이때 -d
옵션을 주면 출력 디렉터리를 지정할 수 있어서 결과만 출력하는 대신 변환된 파일을 생성할 수 있다. 위에서는 Node.js를 이용해서 이 변환된 코드를 실행한 것이다. 하지만 위 코드를 자세히 보면 ES2015의 Arrow Function(function() {}
대신 () =>
문법으로 사용할 수 있는)이 변환되지 않고 그대로 출력된 것을 알 수 있다. Node.js 4.x가 Arrow Function을 지원하기 때문에 여기서는 실행이 제대로 되었지만 Node.js가 아닌 다른 환경이나 Node.js에서 아직 지원하지 않는 ES2015 기능을 사용한다면 제대로 실행되지 않고 오류가 발생할 것이다.
ES2015의 기능을 제대로 트랜스파일 하려면 Babel의 플러그인을 설정해야 한다. Babel 사이트에서 플러그인 목록을 볼 수 있는데 지원하는 기능별로 아주 다양한 플러그인이 존재한다. Babel을 오래 사용하진 않았지만, 아직 6.0의 문서가 많지 않은 관계로 경험상 어느 기능을 사용하기 위해서 어떤 플러그인 및 설정을 해야 하는지 찾는 게 처음에 가장 힘든 일이다. 여기서는 Arrow Function을 설정해 보자.
Babel의 Arrow Function 관련 플러그인의 이름은 transform-es2015-arrow-functions이다. 이를 npm을 이용해서 다음과 같이 설치해야 한다.
$ npm install babel-plugin-transform-es2015-arrow-functions
[email protected] node_modules/babel-plugin-transform-es2015-arrow-functions
└── [email protected] ([email protected])
설치가 완료되면 .babelrc
파일을 생성해서 플러그인 설정을 해야 한다.
{
"plugins": ["transform-es2015-arrow-functions"]
}
위 파일은 .babelrc
의 내용인데 .babelrc 는 Babel의 설정파일로 트랜스파일을 할 때 어떤 옵션을 사용하고 어떤 파일을 사용할지 등을 JSON 형식으로 지정하는 파일이다. 앞에서 설치한 transform-es2015-arrow-functions
를 사용하도록 plugins
에 설정했다.
$ babel example.js
var sum = function (a, b) {
return a + b;
};
console.log(sum(3, 4));
플러그인을 설정한 뒤에 다시 babel
을 실행하면 아까와는 달리 Arrow Function이 function() {}
형식으로 제대로 변환된 것을 볼 수 있다. 플러그인을 제대로 설치하지 않았다면 여기서 Unknown plugin "transform-es2015-arrow-functions"
같은 오류가 발생한다.
앞에서 필요한 플러그인이나 설정을 찾아서 적용하는 게 꽤 힘들다고 했는데 그래서 Babel에서는 필요한 여러 플러그인이나 설정을 미리 설정해 놓은 프리셋을 제공하고 있다. 현재 프리셋에는 es2015
, stage-0
, stage-1
, stage-2
, stage-3
, react
가 있다. es2015
는 ES2015를 ES5로 변환하는 데 필요한 설정이 포함되어 있고 stage-x
는 TC39에서 ECMAScript 표준을 여러 단계로 나누어 놓은 것이다. 이 단계는 Stage 0 - Strawman, Stage 1 - Proposal, Stage 2 - Draft, Stage 3 - Candidate, Stage 4 - Finished로 나누어 지고 숫자가 적은 단계가 상위 단계를 모두 포함하고 있다. Babel의 stage-x
프리셋은 이 각 단계의 기능을 지원하기 위한 설정이고 react
는 React 의 JSX를 변환하기 위한 설정이다.
여기서는 es2015를 사용해 보자. es2015 프리셋에는 다음 플러그인이 설정되어 있어서 앞에서 사용해 본 transform-es2015-arrow-functions
뿐만 아니라 ES2015 기능 대부분이 포함되어 있다.
- check-es2015-constants
- transform-es2015-arrow-functions
- transform-es2015-block-scoped-functions
- transform-es2015-block-scoping
- transform-es2015-classes
- transform-es2015-computed-properties
- transform-es2015-destructuring
- transform-es2015-for-of
- transform-es2015-function-name
- transform-es2015-literals
- transform-es2015-modules-commonjs
- transform-es2015-object-super
- transform-es2015-parameters
- transform-es2015-shorthand-properties
- transform-es2015-spread
- transform-es2015-sticky-regex
- transform-es2015-template-literals
- transform-es2015-typeof-symbol
- transform-es2015-unicode-regex
- transform-regenerator
프리셋을 사용하려면 npm install babel-preset-es2015
로 설치를 하면 된다. 플러그인은 프리셋에 포함되어 있으므로 자동으로 다 설치가 되고 .babelrc
에 플러그인 대신 프리셋을 지정해 주면 된다.
{
"presets": ["es2015"]
}