Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] Babel - Basics

Published
5 min readView as Markdown
[ 살펴보기 ] Babel - Basics
C

A developer living in Busan, Korea

Babel은 Modern ECMAScript syntax를 es5 syntax로 transpile하거나 target 환경에 따라 필요한 polyfill을 core-js와 같은 package를 통해 추가해주거나 JSX나 typescript를 일반 ECMAScript syntax로 변환해 주는 transpiler 역할을 한다.

우선 기본적인 사용법을 살펴보자. bable을 사용하기 위해 다음 package를 설치한다.

npm install -D @babel/core @babel/cli @babel/preset-env

그리고 package.json에 babel을 실행시키지 위한 script를 추가한다.

package.json

...
  "scripts": {
    "build": "babel ./src --out-dir dist"
  },
...

테스트를 진행하는 현재 project 구조는 다음과 같다.

...
package.json
src
    - index.js

src/index.js

const testFn = (param) => {
  return param;
};

위와 같은 상태에서 npm run build command를 실행하면 dist 폴더에 index.js file이 생성되는 것을 확인할 수 있다. 하지만 transpile에 대한 설정을 따로 지정하지 않았기 때문에 src/index.js file이 변하지 않고 그대로 dist 폴더에 생성된다. 이제 babel을 통해 transpile할 때 어떻게 transpile해야 하는지 설정하는 방법을 살펴보자.

Plugin & Preset

Babel을 통해 code를 특정한 형태로 transpile할 때는 plugin을 통해 transpile이 이루어진다. 예를 들어 babel을 통해 transpile할 때 ES6의 arrow function을 ES5 syntax로 변환하고 싶다고 가정해보자. 이를 적용하기 위해서 우선 plugin을 설치해야 한다.

npm install -D @babel/plugin-transform-arrow-functions

그리고 package.json의 script를 다음과 같이 변경해준다.

package.json

...
  "scripts": {
    "build": "babel ./src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions"
  },
...

이제 다시 npm run build command를 실행해보자. 이제 dist에 생성된 파일에 정의된 function이 arrow function이 아닌 es5 syntax function으로 변환되어 생성된 것을 확인할 수 있다.

하지만 실제로 code를 작성하고 babel을 통해 transpile을 할 때 transpile을 해야하는 ECMAScript syntax는 arrow function 뿐만이 아니다. 이럴 때는 transpile이 필요한 모든 syntax에 대한 plugin을 별도로 설치하여 적용하기 보다 필요한 plugin을 포함하고 있는 preset을 설치하여 적용할 수 있다.

Modern ECMAScript syntax를 transpile하기 위해 필요한 plugin을 포함하고 있는 preset인 @babel/preset-env package를 적용해보자.

npm install -D @babel/preset-env

그리고 plugin대신 preset을 적용하기 위해 pakcage.json script를 다음과 같이 수정한다.

package.json

...
  "scripts": {
    "build": "babel ./src --out-dir dist --presets=@babel/env"
  },
...

이제 다시 npm run build command를 실행하면 plugin을 적용한 것과 같은 결과가 dist 폴더에 생성된 것을 확인할 수 있다. preset에 별도로 configuration을 설정하지 않으면 모든 ECMAScript plugin이 적용된다. 원하는 동작을 설정하기 위해 configuration file을 생성하고 설정하는 방법을 살펴보자.

Preset Configuration

babel configuration을 위해 project root에 babel.config.json 파일을 생성한다. 우선 위에서 살펴본 preset을 설정하는 방법을 살펴보자.

babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "firefox": "70",
          "chrome": "70",
        }
      }
    ]
  ]
}

위의 코드에선 config 파일을 통해 preset 관련 설정을 추가해주고 있다. preset을 적용하여 compile하되 target하는 browser환경은 firefox 67, chrome 67 version이므로 compile할 때 해당 browser 환경에서 실행될 수 있는 code로 compile 되도록 설정 하고있다.

Babel은 transpile 작업을 수행할 때 특정 ECMScript version을 target해서 transpile하는 option은 제공하지 않으므로 위와 같이 target runtime을 설정해서 해당 runtime을 지원하는 code로 transpile하도록 설정해야 한다. 만약 targets을 명시적으로 설정하지 않으면 legacy browser 지원까지 target하여 transpile을 수행할 수 있으므로 targets option은 가급적 명시적으로 설정하여 output code size를 줄이는 편이 좋다.

target외에도 preset-env preset에 설정할 수 있는 option은 다양하며 모든 option list는 documentation을 통해 확인할 수 있다 ( Reference - @babel/preset-env )

Polyfill 적용하기

만약 babel을 통해 compile하는 target environment에서 modern ECMAScript에서 지원하는 syntax 자체가 존재하지 않으면 어떻게 될까? 예를 들어 Array.findLast나 Array.findLastIndex와 같은 feature는 ES2023에 추가된 feature다.

하지만 bable을 통해 compile하는 target environment가 ES2023 이전 syntax를 사용한다면 문제가 발생할 수 있다. user가 ES2023에 추가된 features를 지원하지 않는 version의 browser를 사용하고 있으면 code 실행 시 오류가 발생하기 때문이다.

그렇기에 새로운 ECMAScript feature를 target environment에서도 사용할 수 있도록 각 feature마다 별도의 code를 추가해 feature의 동작을 구현하는데 이를 polyfill이라고 한다.

현재 포스트에서 진행하고 있는 환경에선 7.26.0version의 @babel/preset-env을 사용 중이며@babel/preset-env 7.4.0 version 이전까지는 @babel/polyfill package를 통해 polyfill을 추가했지만 7.4.0 이후부터는 @babel/polyfill deprecated 되었기 때문에 현재 version 기준으로 polyfill을 적용하는 방법을 살펴본다.

( Reference - Polyfill )

우선 polyfill을 제공하는 package를 설치한다. Babel은 core-js를 통해 polyfill을 제공한다.

npm install core-js@3

이제 babel이 transpile을 실행할 때 core-js를 통해 polyfill을 추가할 수 있도록 babel.config.json 파일을 업데이트 해준다. 포스트를 진행하며 설치한 core-js version은 3.39.0이다. 사용하는 core-js version에 따라 지원되는 polyfill에 차이가 있을 수 있으므로 주의하자.

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "targets": {
          "chrome": "70"
        },
        "corejs": "3.39.0",
        "useBuiltIns": "usage"
      }
    ]
  ]
}
  • useBuiltIns : babel이 compile을 진행할 때 어떤식으로 polyfill을 추가할건지 설정할 수 있다. usage로 설정하면 실제로 사용된 feature에 한해서 필요한 polyfill만 추가한다. default값은 false다.

  • corejs : project에서 사용하는 core-js version을 설정한다. useBuiltins option을 false아닌 값으로 설정했을 때 함께 설정해주어야 하며 project에 설치한 core-js version과 동일한 값을 설정해준다. default 값는 2.0이다.

  • modules : transpile되어 나오는 file에서 사용하는 module type을 설정한다. false로 지정하면 es module type이 사용된다. default 값은 auto다.

이제 다음 코드를 babel을 통해 transpile 해보자. 아래 예제에서 사용된 findLast는 ES2023에 추가된 feature이므로 위의 설정에서 target하는 chrome version 70에선 지원하지 않는 feature다.

src/index.js

const testFn = (param) => {
  return param;
};

const test1 = [27, 28, 30, 40, 42, 35, 30];
const test2 = test1.findLast((x) => x > 40);

dist/index.js

import "core-js/modules/es.array.find-last.js";
const testFn = param => {
  return param;
};
const test1 = [27, 28, 30, 40, 42, 35, 30];
const test2 = test1.findLast(x => x > 40);

위의 예제에서 볼 수 있듯이 findLast에 대한 polyfill이 compile된 코드가 추가된 것을 확인할 수 있다.

Configuration

위에서 살펴 보았듯이 babel은 babel.config.json 파일을 통해 babel 설정 값을 관리한다. extension은 json 뿐만 아니라 .js, .cjs, .mjs또한 사용할 수 있다.

babel.config.json에서 설정할 수 있는 모든 option list는 documentation에서 확인할 수 있으며 그 중 일부 option은 다음과 같다. ( Reference - Config Options )

  • ignore : babel을 통해 transpile을 실행할 때 특정 파일이나 폴더를 제외한다. 예를 들어 다음과 같이 설정하면 ./src/utils 폴더와 해당 폴더에 존재하는 file은 transpile 대상에서 제외된다.

      {
        "ignore": ["./src/utils"],
         ...
      }
    
  • only : babel을 통해 transpile을 수행할 때 특정 파일이나 폴더만 transpile 하고 싶다면 only option을 통해 특정 파일이나 폴더를 설정할 수 있다. 예를 들어 다음과 같이 설정하면 ./src/utils 폴더와 해당 폴더에 존재하는 file만 transpile의 대상이 된다.

      {
        "only": ["./src/utils"],
         ...
      }
    
  • sourceMap: transpile을 수행하면서 각 파일의 sourceMap도 함께 생성할 것인지 설정한다.

      {
        "sourceMap": false,
         ...
      }
    
  • compact : transpile을 수행할 때 traspile되어 나오는 output code를 whitespace와 newline을 제외한 compact mode로 생성할 것인지 여부를 설정한다.

      {
        "compact": false,
         ...
      }
    
  • plugins : transpile에 적용할 plugin을 설정한다. 아래 예제는 arrow function syntax transpile을 위한 plugin을 설정한다.

      {
        "plugins": [
          "@babel/plugin-transform-arrow-functions"
         ],
         ...
      }
    
  • presets : transpile에 적용할 preset을 설정한다. 아래 예제는 Modern ECMAScript syntax transpile을 위한 plugin을 모아둔 preset인 @babel/preset-env를 설정한다.

      {
        "presets": [
            "@babel/preset-env"
        ],
        ...
      }
    

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts