Babel 이란?

TheJang·2021년 2월 17일
0
post-thumbnail

이 포스팅은 지속적으로 상기 시키기 위해 다른 블로그의 글에서 가져와 약간만 수정한 포스팅입니다.

크로스 브라우징& 바벨

크로스 브라우징이란 ? 브라우저나 플랫폼마다 보여지는 모습이 다른 경우가 많습니다. 바벨은 이러한 차이를 최소하 하여 브라우저, 환경에 영향을 최소한으로 받고 해당 웹 서비스를 사용할 수 있게 최적화를 하는 작업을 말합니다. 일부 최신 브라우저에서만 동작하는 기능을 그렇지 않은 브라우저에서 구현해야 할 경우 , 기능을 단순화 하거나 생략해야 하는 경우가 발생하기도 합니다.

이러한 크로스 브라우징 이슈를 해결하기 위해 생겨난 툴이 바벨 이라 할 수 있습니다. ES6+ 버전의 자바스크립트나 타입스크립트 ,JSX등 다른 언어로 분류되는 언어들에 대해서도 모든 브라우저에서 동작할 수 있도록 호환성을 지켜줍니다.

바벨은 이렇게 추상화 수준을 유지한 채로 코드를 변화시키는 트랜스파일러의 역할을 합니다.

바벨 공식 문서

바벨은 주로 ECMAScript 2015+ 코드를 현재 및 과거의 브라우저와 같은 환경에서 호환되는 버전으로 변환하는데 주로 사용되는 도구입니다.

바벨을 세 단계 빌드를 진행합니다.

  1. 파싱(Parsing): 코드를 읽고 추상 구문 트리(AST)로 변환하는 단계
  2. 변환(Transforming): 추상 구문 트리를 변경
  3. 출력(Printing): 변경된 결과물을 출력

여기서 바벨을 파싱출력 담당하고 변환(Transforming)은 다른 녀석이 진행합니다. 바로 그 녀석이 플러그인입니다. 바벨 플러그인은 바벨이 어떤 코드를 어떻게 변환할 지에 대한 규칙을 나타냅니다. 플러그인은 직접 만들어서 커스텀 플러그인을 사용해도 되고, 이미 잘 만들어진 플러그인을 가져다가 써도 됩니다.

  • 바벨 플러그인(Babel-plugin)

NPM 패키지로 제공하는 플러그인을 설치하여 ES6의 const,let을 var로 바꾸고, 화살표 함수를 일반 함수로 바꾸고 엄격 모드를 적용하여 ES6+를 ES5로 변환하는 바벨 설정 파일은 다음과 같습니다.

// babel.config.js

module.exports = {
  plugins: [
    "@babel/plugin-transform-block-scoping",
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-strict-mode", 
  ]
}

위와 같이 설정값을 세팅하고 다시 빌드를 하면 아래와 같이 코드가 변합니다.

// terminal에서 babel로 app.js 빌드

// (before) app.js
const alert = msg => window.alert(msg);

// (after) app.js
"use strict";

var alert = function (msg) {
  return window.alert(msg);
};

여러가지 바벨 플러그인들은 바벨 공식문서에서 더 찾아 볼 수 있습니다.

https://babeljs.io/docs/en/plugins

프리셋

플러그인을 매번 일일이 설정하는 것은 정말 번거롭습니다. 그래서 이렇게 필요한 플러그인들을 목적에 따라 세트로 묶어 놓은 경우가 많습니다. 이러한 세트를 프리셋(preset) 이라고 합니다. 프리셋도 마찬가지로 직접 모듈을 만들어서 설정할 수도 있고,바벨에서 제공하는 프리셋을 가져와서 사용할 수도 있습니다. 바벨 7 이전에는 연도별 프리셋을 제공했지만 이후 버전에서는 env 하나로 합쳐져서 무척 편리하게 사용할 수 있게 되었습니다.

프리셋(Preset): 플러그인을 목적에 따라 세트로 묶어놓은 경우

대표적인 프리셋으로 ES6+를 변환하는 프리셋인 preset-env를 살펴 봅시다. 프리셋 패키지를 설치하고 아래와 같이 바벨 설정 파일을 바꿔줍니다.

  • preset-env(NPM 패키지)

    module.exports = {
      presets: [
        '@babel/preset-env'
      ]
    }

그러면 위에서 npx babel app.js를 했던 결과와 같은 결과가 나오게 됩니다.

만약에 특정 브라우저 버전 이상을 지원해야하는 경우 바벨 설정 파일에서 targets 속성 값으로 지정해 주면 됩니다. 예를 들어서 크롬 79이상, IE11이상을 지원해 주는 코드로 변환하고 싶다면 아래와 같이 바벨 설정 파일을 바꾸어 주면 됩니다.

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          chrome: '79', // 크롬 79까지 지원하는 코드를 만든다
          ie: '11' // ie 11까지 지원하는 코드를 만든다
        }
      }
    ]
  ]
}

폴리필(Polyfill)

이번에는 변환과는 조금 다른 폴리필에 대해서 알아보고자 합니다. 폴리필(polyfill)최신 ECMAScript 환경을 만들기 위해 코드가 실행 되는 환경에 존재하지 않는 빌트인, 메소드 등을 추가하는 역할을 합니다.

폴리필(Polyfill) : 최신 ES 환경을 만들기 위해 빌트인, 메소드등을 추가하는 역할

ES6에서 비동기 처리를 위해 등장한 Promise 객체는 env 프리셋을 가지고 변환을 하려고 해도 ie에서 인식하지 못합니다. 바벨의 경우는 ES6+를 ES5로 변환할 수 있는 것들만 변환을 하는데, Promise와 같이 ES5에서 변환할 수 있는 대상이 없는 경우는 에러를 발생합니다. 이러한 경우 우리는 폴리필을 통해서 이슈를 해결 할 수 있습니다. Promise를 ES5로 변환할 수 없지만 ES5 방식으로 구현하여 해결하는 것입니다.

아래와 같이 바벨 설정 파일에 폴리필을 추가합니다. useBuiltlns는 어떤 방식으로 폴리필을 사용할지 설정하는 옵션이고, **corejs** 도 기본값이 2이기 때문에 아래와 같이 명시했습니다.

/* bable.config.js */

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'usage', // 폴리필 사용 방식 지정
        corejs: { // 폴리필 버전 지정
          version: 2
        }
      },
    ],
  ],
};

그 후 빌드를 하면 아래와 같습니다.

/* app.js */

// 폴리필을 추가하여 빌드
npx babel app.js

// (before) app.js
new Promise();

// (after) app.js
"use strict";

require("core-js/modules/es6.promise");
require("core-js/modules/es6.object.to-string");

new Promise();

corejs 패키지로부터 프로미스 모듈을 가져오는 임포트 구문이 상단에 추가 되었습니다. 이 결과물은 이제 ie에서 정상적으로 돌아가게 됩니다.

실무에서는 바벨을 직접 사용하는 경우보다는 웹팩으로 통합해서 사용하는 경우가 더 많다고 합니다. 이 때 로더 형태로 제공되는 babel-loader 사용합니다.

babel-loader 를 설치하고 웹팩 설정 파일을 다음과 같이 작성합니다. 모든 js 파일을 바벨로 처리할 수 있게 했고, node_modules는 양이 많고 굳이 처리할 피료가 없기 때문에 제외해 주었습니다.

/* webpack.config.js  */

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader', // 바벨 로더를 추가한다 
      },
    ]
  },
}

폴리필을 사용하였다면 폴리필 또한 설치를 해 주어 햡니다. 그리고 webpack으로 번들링 된 결과물을 확인하면 코드가 정상적으로 변환이 되었음을 알 수있습니다.

정리

바벨을 일관적인 방식으로 코딩을 하면서, 다양한 브라우저에서 돌아가는 어플리케이션을 만들기 위한 도구입니다. 바벨의 코어는 파싱과 출력만 담당하고 변환 작업은 플러그인이 처리합니다. 여러 개의 플러그인들을 모아놓은 세트를 프리셋이라고 하는데 ES+환경은 env 프리셋을 사용합니다. 바벨이 변환하지 못하는 코드는 폴리필 이라 부르는 코드 조각을 가져와 결과물에 로딩해서 해결합니다. babel-loader로 웹팩과 함께 사용하면 훨씬 단순하고 자동화된 프론트엔드 개발 환경을 갖출 수 있습니다.

  • 바벨 : 다양한 브라우저에서 돌아가는 어플리케이션을 만들기 위한 도구 (chrome, IE, mozilla...)
    • 바벨은 파싱과 출력만 담당
  • 플러그인: 변환 작업 담당, 바벨이 어떤 코드를 어떻게 변환할 지에 대한 규칙을 나타냄.
  • 프리셋: 매번 플러그인을 수정하기 번거롭기 때문에 플러그인들을 모아놓은 세트
  • 폴리필: 바벨로 해결되지 않는 코드를 최신 ES 환경을 만들기 위해 빌트인, 메소드등을 추가하는 역할

Reference

profile
어제보다 오늘 더 노력하는 프론트엔드 개발자

0개의 댓글