Babel (바벨)

4221 단어 babelbabel

많은 개발자들이 개발의 편의성과 생산성 향상을 위해 최신 JS 문법인 ES6, ES7를 사용한다. 그러나 브라우저의 종류, 버전에 따라 해당 문법을 이해하지 못할 수 있다.

Babel은 상위 문법을 ES5와 같은 범용적인 하위버전의 JS 문법으로 변환한다.
설정에 따라 어느 수준까지 변환할지 정할 수 있다.

바벨의 진행 단계/동작

바벨은 세 단계로 빌드를 진행한다.

  1. 파싱(Parsing)
  2. 변환(Transforming)
  3. 출력 (Printing)

코드를 읽고 추상 구문 트리(AST)로 변환하는 단계가 "파싱" 인데 이는 빌드 작업을 처리하기에 적합한 자료구조로 변환하는 단계이다.
추상 구문 트리를 변경하는 것이 "변환" 단계이다. 실제로 코드를 변경하는 작업을 한다.
변경된 결과물을 "출력"하는 것을 마지막으로 바벨은 작업을 완료한다.

바벨은 파싱과 출력만 담당하고 변환 작업은 다른 녀석이 처리하데 이것을 "플러그인" 이라고 부른다. 따라서 플러그인을 따로 추가하지 않으면 input과 output이 동일하기 때문에 JS파일이 실질적으로 변환되지 않는다.

플러그인 사용하기

바벨에는 수 많은 플러그인이 존재한다.

    "@babel/plugin-transform-block-scoping",
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-strict-mode",
      ...

각 플러그인은 하나의 기능씩을 담당하는데 개발자가 사용할 플러그인을 일일히 추가하는 것은 비효율적이기 때문에 다수의 플러그인을 하나로 묶은 '프리셋'을 사용한다.
PS. 아직 정식 버전에는 포함되어 있지 않은 새로운 스펙들은 plugins 배열로 추가하면 된다.
아직 정식 버전에 포함되지 않은 개발 중인 스펙은 플로그인 형태로 개별 추가해 해당 기능을 사용할 수 있지만 Stage-3 이상의 스펙들만 사용하는 것을 추천한다.

사용할 수 있는 플러그인 목록들은 여기에서 확인할 수 있다. 이미 정식 버전에 포함된 스펙들은 프리셋으로 모아서 적용 가능하기 때문에 따로 따로 플러그인으로 사용할 일은 없다. 아직 정식 버전에 포함되지 않은 스펙의 플러그인들은 Experimental 파트에 정리되어 있다.

다음은 바벨의 공식 프리셋이다.

  "@babel/preset-env"
  "@babel/preset-flow"
  "@babel/preset-react"
  "@babel/preset-typescript"

@babel/preset-env 프리셋 이용하기

npm install -D @babel/preset-env
// babel.config.js:
module.exports = {
  presets: ["@babel/preset-env"],
}

지원할 브라우저 정보와 일부옵션을 지정하면 자동으로 필요한 기능들을 주입해줍니다.
자동 주입되는 필요한 기능들은 컴파일에 필요한 바벨변환 플러그인들과 core-js 폴리필들입니다.

설정하고자 하는 브라우저 선택

기본적으로 babel-preset-env는 단순히 모든 es6 plugin을 설치한다. 하지만 이것은 컴파일된 자바스크립트의 양이 많아져 번들의 코드를 길어지게 만든다.

왼쪽은 es6 코드이고 중간의 코드는 오래된 브라우저에 제공하기 위해 컴파일된 파일이다. 제일 오른쪽의 나름 최신의 브라우저에 제공되는 코드에 비해서도 매우 길다.

그래서 babel-preset-env만을 쓴다면 오래된 브라우저에 제공하는 코드의 길이는 엄청나게 많아져 번들 파일을 터뜨려 버릴 것이다. (그만큼 코드 길이가 늘어난다는 뜻)

최근의 브라우저는 대부분 es6를 지원한다. google analystics만 보더라도 99%는 최신의 브라우저이다. 그래서 모든 옛날 브라우저를 지원할 필요는 없다고 생각할 수도 있다.

그래서 babel-preset-env에게 원하는 브라우저만 지원가능하도록 plugin을 선택할 수 있다.

바벨은 만병통치약인가?

babel은 기본적으로 es6(ecma2015) 문법으로 작성한 코드를 es5 환경에서 동작할 수 있도록 문법적인 변환을 해주지만 es5에 존재하지 않는 es6의 메서드나 생성자들까지 지원해주지는 않는다.

그래서 es5로 동작하는 하위 브라우저를 지원하는 서비스를 개발할 때에는 폴리필을 추가하여 개발 편의성을 향상시킬 수 있다
babel을 사용한다고 자바스크립트 최신 함수를 사용할 수 있는 건 아니다. 초기에 babel만 믿고 최신 함수를 사용했다가 브라우저에서 동작하지 않는 것을 보고 당황했었다. babel은 문법을 변환해주는 역할만 할 뿐이다. polyfill은 프로그램이 처음에 시작될 때 현재 브라우저에서 지원하지 않는 함수를 검사해서 각 object의 prototype에 붙여주는 역할을 한다. 즉, babel은 컴파일-타임에 실행되고 babel-polyfill은 런-타임에 실행된다.
babel-polyfill을 사용하고 싶다면 별도로 설정해줘야 한다.
Babel은 컴파일-타임에 코드를 구 브라우저에서 사용가능하게 변환하지만, ES6이상에서 새롭게 추가된 Promise, Map, Set 같은 전역객체들이나 String.padStart등 전역 객체에 추가된 메서드등 컴파일-타임의 코드변환으로는 해결하기 어렵기 때문에 폴리필(polyfill) 이 필요한 것입이다.

babel 7.4.0 이후부터 @babel/polyfill이 deprecated 되었다.

@babel/plugin-transform-runtime을 사용하면 실제로 코드에서 사용한 폴리필 메서드만 번들에 포함된다.
현재 시점에서 전역을 오염시키지 않는 가장 바람직한 방법이라고 생각된다.

좋은 웹페이지 즐겨찾기