React/이론

바벨

잉여개발자 2024. 12. 8. 18:47
반응형

Babel이란? 

Babel은 자바스크립트 트랜스파일러로, ECMAScript 2015+ 코드를 구형 및 최신 브라우저 환경에서도 호환도록 변환하는 도구 체인이다. 

 

주요 기능

  1. 문법 변환
    • 최신 ECMAScript 문법을 구형 브라우저에서도 동작할 수 있도록 변환한다. 
    • 예) const나 arrow function 같은 문법을 구형 문법으로 변환
  2. polyfill 적용
    • 브라우저에서 지원하지 않는 새로운 JavaScript 기능을 사용할 수 있도록 추가 기능을 삽입한다. 
    • 예) Promise, Array.prototype.includes 등.
  3. 코드 전환
    • React(JSX), TypeScript와 같은 다양한 JavaScript 확장 언어를 표준 JavaScript로 변환한다. 
    • 예) JSX 코드를 React.createElement 호출로 변환. 

 

왜 Babel을 사용해야 할까? 

바벨은 최신 JavaScript 문법과 기능을 활용하면서도, 다양한 브라우저 환경에서의 호환성을 유지할 수 있도록 도와주는 강력한 도구이다. 특히, React와 함께 사용할 때 JSX 변환이나 최신 문법 적용을 위해 필수적으로 사용된다. 

 

이제 이러한 Babel을 좀 더 자세하게 알아보자. 

Polyfill

Polyfill은 기본적으로 지원하지 않는 구형 브라우저에서 최신 JavaScript 기능을 사용할 수 있도록 제공하는 코드이다. 

예를 들어, Promise나 async/await 같은 최신 기능은 구형 브라우저에서 지원되지 않으므로 Polyfill을 통해 호환성을 확보해야 한다. 

 

Babel vs Polyfill

설명만 들으면 비슷해보이는 Babel과 Polyfill은 역할과 동작 방식에서 명확한 차이가 있다. 

항목 Babel Polyfill
역할 최신 JavaScript 문법을 구형 브라우저에서도 실행 가능하게 변환 브라우저에서 지원하지 않는 기능을 사용할 수 있도록 제공
변환 대상 ES6+ 문법 (예. const, arrow function) 새로운 API(예. Promise, fetch, Array.prototype.includes)
동작 방식 코드를 변환하여 지원 가능한 문법으로 대체 브라우저 환경에 필요한 추가 코드를 삽입
const => var, JSX => React.createElement Promise가 없는 브라우저에 Promise 구현 추가

Babel은 문법 변환을 수행하지만, 새로운 JavaScript 기능(API)를 제공하지는 않습니다. 

  • Promise는 Babel만으로는 사용할 수 없으므로 Polyfill이 필요하다. 

결국 Polyfill은 Babel과 함께 사용되어 최신 문법과 새로운 기능 모두를 지원할 수 있게 한다. 

 

사용해보기 

1. 라이브러리 설치

yarn add -D @babel/core @babel/cli @babel/preset-env
  • @babel/core
    Babel의 핵심 라이브러리로, 실제 트랜스파일링 작업을 처리한다. 
    • 코드 변환, 플러그인 및 프리셋 관리 등 Babel의 주요 기능을 제공한다. 
  • @babel/cli
    Babel을 커맨드라인에서 사용할 수 있도록 지원한다. 
    • 직접 명령어를 입력해 트랜스파일링 작업을 수행할 수 있다. 
    • 예: babel src --out-dir dist 
  • @babel/preset-env
    Babel의 기본 프리셋으로, 최신 JavaScript 문법을 브라우저에서 지원하는 ES5 문법으로 변환한다. 
    • 브라우저 환경에 따라 필요한 polyfill을 자동으로 결정한다. 
    • 최신 브라우저에서는 불필요한 변환을 건너뛰고, 구형 브라우저에서는 필요한 변환만 수행한다. 

2. babel 설정 파일 작성

Babel의 동작 방식을 정의하기 위해 설정 파일을 작성한다. 

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

이 설정은 Babel에게 최신 JavaScript 문법을 ES5로 변환하도록 지시하였다. @babel/preset-env는 브라우저 환경에 맞게 필요한 변환을 자동으로 선택하여 처리한다. 

 

이때, 사용할 수 있는 속성이 몇개 있는데 다음과 같다. 

  • presets
    • 여러 개의 plugin을 하나로 묶은 규칙이다. 
    • 예) @babel/preset-env는 최신 ECMAScript 문법 변환에 필요한 플러그인 모음을 포함한다. 
  • plugins
    • 특정 JavaScript 문법을 변환하는 데 사용된다.
    • 예) @babel/plugin-proposal-class-properties는 브라우저가 지원하지 않는 class 속성을 변환한다. 

3. Babel 변환하기 

// index.js
const sayHello = (name) => {
  return `Hello, ${name}!`;
};

class User {
  constructor(name) {
    this.name = name;
  }

  say() {
    console.log(sayHello(this.name));
  }
}

const user = new User("John");
user.say();

 

다음 명령어를 사용해 Babel을 통해 index.js 파일을 변환하려고 한다. 

npx babel index.js -o dist.js
  • index.js: 변환할 소스 파일
  • -o dist.js : 변환된 결과를 dist.js라는 파일로 출력
"use strict";

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var sayHello = function sayHello(name) {
  return "Hello, ".concat(name, "!");
};
var User = /*#__PURE__*/function () {
  function User(name) {
    _classCallCheck(this, User);
    this.name = name;
  }
  return _createClass(User, [{
    key: "say",
    value: function say() {
      console.log(sayHello(this.name));
    }
  }]);
}();
var user = new User("John");
user.say();
  • const => var : const 키워드가 구형 브라우저에서는 지원하지 않으므로 var로 변환되었다. 
  • class => function 및 헬퍼 함수 : 클래스가 함수로 변환되고, 클래스 관련 로직을 구현하기 위해 헬퍼 함수가 추가되었다.
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise resolved");
  }, 1000);
});

Promise 문법을 Babel을 통해서 변환하면 다음과 같이 변환된다. 

var myPromise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve("Promise resolved");
  }, 1000);
});

문제점이 보이시나요??

  • Babel은 const는 변환하고 있지만, Promise 자체는 변환하지 않고 있다. 
  • Promise는 최신 브라우저에서 지원되지만, 구형 브라우저에서는 지원하지 않을 수 있다. 

Polyfill 사용하기 

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

구형 브라우저에서 Promise를 지원하게 하려면 Polyfill이 필요하다. 

위와  같이 preset-env 외에 polyfill 설정을 추가해주면 정상적으로 Promise 객체도 변환해주는 것을 확인할 수 있다. 

반응형