안녕하세요! 이번 시간에는 바벨(BabelJS)에 대해 알아보겠습니다! 바벨 자체는 ECMAScript가 아닙니다. 하지만 이 카테고리에 있는 이유는 바로 ES2015+ 문법을 실제로 사용할 수 있게 해주기 때문입니다.
ES2015+ 문법은 에버그린 브라우저만 지원하는 기능이기 때문에 구형 브라우저(IE라든가... IE라든가...)와는 호환이 안 된다는 단점이 있습니다. 아직도 윈도우7을 쓰는 컴퓨터가 많기 때문에 IE 점유율이 상당한데요. ES2015+ 문법을 구형 브라우저에서 사용하고 싶다면 어떻게 해야 할까요? 그냥 포기해야 하는 걸까요?
아닙니다. ES2015+ 문법을 사용한 코드를 예전 ES5 자바스크립트 코드로 바꿔주는 도구들이 있습니다. 그중에서 가장 유명한 도구가 바벨입니다. 바벨탑의 이름을 딴 것 같네요(왜 이름을 바벨로 지었는지 아시겠죠?). 바벨을 사용하려면 npm을 사용하여
npm install --save-dev @babel/cli @babel/core @babel/preset-env @babel/preset-stage-2
하여 설치해주어야 합니다. 바벨 7버전부터는 모든 바벨 패키지들이 @babel이라는 네임스페이스 안에 속하게 되었습니다. npm을 모른다면 이 강좌를 참조하세요.
6버전까지는 다음과 같이 했습니다. 이렇게 분산된 패키지들은 @babel이라는 네임스페이스로 모아준 것입니다.
npm install --save-dev babel-cli babel-core babel-preset-env babel-preset-stage-2
@babel/cli와 @babel/core @babel/preset-env, @babel/preset-stage-2 네 패키지를 설치하였습니다. 이제 명령 프롬프트에서 babel 명령어를 사용할 수 있습니다(@babel/cli의 역할). 하지만 직접 명령어를 치기보다는 npm과 package.json 파일을 사용하여 하는 게 더 간편합니다.
우선 .babelrc라는 파일을 만들어 설치한 preset을 연결해줍니다. .babelrc는 바벨에 대해 설정을 하는 파일입니다. 여기에 preset이나 plugin을 연결하면 됩니다. preset은 여러 플러그인의 모음집입니다.
유명한 preset으로는 react나 es2015, es2016, es2017, env, stage-0, stage-1, stage-2, stage-3 등이 있습니다. 7버전부터 stage-0, stage-1, stage-2, stage-3은 deprecated되었습니다. 앞으로는 새로운 스펙은 프리셋 대신 플러그인 형식으로 넣어야 합니다.
react 프리셋은 react 환경(jsx)을 위한 프리셋이고, es2015는 ES2015 문법을 사용할 수 있게 도와주는 플러그인들의 프리셋입니다.
env 프리셋은 한 술 더 떠서 특정한 문법 버전을 입력할 필요 없이, 타겟 브라우저를 입력하면 알아서 사용자가 환경에 맞춰 최신 EcmaScript를 사용할 수 있게 해줍니다. env를 정말 추천합니다. stage-0부터 3까지는 EcmaScript 스펙 중에서 비공식 실험적인 기술들을 사용할 수 있게 해주는 프리셋입니다. stage들은 deprecated되었습니다.
stage-2까지는 그나마 안정적이고, stage-0과 stage-1은 언제든지 바뀔 수 있는 기술들이라 사용 시 주의가 필요합니다. 저는 stage-2를 주로 사용합니다. stage-1이나 stage-0은 stage-2를 포함하고 있지만 자주 쓰이는 기능이 아니라 사용하지 않습니다. 플러그인과 preset에 대한 자세한 설명은 여기 있습니다.
.babelrc
{
"presets": [
["@babel/preset-env", { "targets": { "browsers": ["last 2 versions", ">= 5% in KR"] } }],
["@babel/preset-stage-2", { "decoratorsLegacy": true }]
]
}
env와 stage-2를 쓰도록 설정한 것인데요. 각각 배열 안에 배열로 묶여져 있습니다. 배열의 두 번째 요소가 env와 preset에 대한 설정입니다. targets 부분입니다.
targets 옵션을 살펴보면, 브라우저들에 대해서는 최신 두 버전(IE는 10과 11, 크롬과 파이어폭스, 사파리, 엣지는 최신 두 버전)과 한국에서 5% 이상 점유율을 차지하는 브라우저를 모두 지원하라고 설정해준 겁니다. 저렇게만 쓰면 babel이 알아서 최신 자바스크립트 코드를 지정한 targets에 맞게 호환되는 자바스크립트 코드로 바꿔줍니다. 정말 편하죠!
만약 브라우저 대신 노드 환경에서 바벨을 쓰고 싶다면(극히 드물지만, 리액트 서버사이드 렌더링을 하는 것과 같은 경우에 쓰기도 합니다) { targets: { node: 'current' } }
등을 지정하면 됩니다.
decoratorsLegacy는 stage-2의 decorators를 사용하기 위한 옵션입니다.
그리고 package.json에는 scripts 부분에 바벨로 컴파일하는 부분을 기재해줍니다.
package.json
{
"scripts": {
"build": "babel src -d lib"
}
}
npm run build 명령을 수행할 때 babel을 실행하고, src 폴더에 있는 최신 자바스크립트 코드를 컴파일하여 결과를 lib 폴더에 넣으라는 뜻(-d 옵션이 결과를 저장할 경로를 의미합니다.)입니다. 컴파일하는 과정에서 알아서 .babelrc 파일을 읽어 옵션을 적용합니다.
이제 구형 브라우저에서는 src 폴더 대신 lib 폴더에 있는 자바스크립트 파일을 사용하면 됩니다. 코딩은 src 폴더에서 ES2015 스타일로 하면 되고요. 당연한 소리이지만 폴더 이름은 src, lib으로 고정되어있는 것이 아니라 사용자 마음대로입니다. 추가적인 바벨 명령어에 대한 자세한 설명은 여기를 참조하세요.
babel-polyfill
바벨을 사용하면 새로운 문법을 구형 자바스크립트 문법으로만 바꿔줍니다. 문법만 바꿔주면 됐지 뭘 더 바라냐고요? 바벨 그 자체로는 ES2015의 새로운 객체(Promise, Map, Set 등등)과 메소드(Array.find
, Object.assign
등등)을 사용할 수 없습니다. 왜냐하면 ES2015에서 처음 생긴 거라 구형 자바스크립트에는 그에 상응하는 코드가 없거든요. 그래서 babel-polyfill을 설치해야 새로운 기능을 사용할 수 있습니다.
@babel/polyfill 패키지를 먼저 설치합니다. 6버전까지는 babel-polyfill이었습니다.
npm install @babel/polyfill
ES2015 문법을 사용하는 파일 가장 윗부분에 다음 줄을 추가합니다. 단, 폴리필은 하나의 프로젝트에 한 번만 사용해야 합니다. 그렇지 않으면 충돌이 발생합니다. 따라서 가장 먼저 로딩되는 스크립트 제일 위에 추가하도록 합시다.
import '@babel/polyfill';
구문을 넣으면 babel이 컴파일할 때 알아서 적용합니다. 다음은 예시입니다.
import '@babel/polyfill';
import ...
const val = Object.assign({ a: '1' }, { a: 'b' });
export default val;
웹팩을 사용한다면 파일에 import '@babel/polyfil';
하는 대신 웹팩 설정 파일 entry에 적어도 됩니다. 다음과 같이요.
webpack.config.js
{
entry: ['@babel/polyfill', './app.js'],
}
이렇게요. 웹팩이 알아서 app.js에 polyfill을 적용해줍니다.
간단하죠? @babel/preset-env와 @babel/polyfill 패키지만 있으면 ES2015+의 모든 기능을 사용할 수 있습니다. 다음 시간에는 새로 추가된 메소드들을 알아봅시다.