Babel이란?
Babel은 자바스크립트 트랜스파일러로, ECMAScript 2015+ 코드를 구형 및 최신 브라우저 환경에서도 호환도록 변환하는 도구 체인이다.
주요 기능
- 문법 변환
- 최신 ECMAScript 문법을 구형 브라우저에서도 동작할 수 있도록 변환한다.
- 예) const나 arrow function 같은 문법을 구형 문법으로 변환
- polyfill 적용
- 브라우저에서 지원하지 않는 새로운 JavaScript 기능을 사용할 수 있도록 추가 기능을 삽입한다.
- 예) Promise, Array.prototype.includes 등.
- 코드 전환
- 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 객체도 변환해주는 것을 확인할 수 있다.
'React > 이론' 카테고리의 다른 글
번들러 (1) | 2024.12.04 |
---|---|
[React] DOM vs Virtual DOM (0) | 2022.11.08 |
[React] 렌더링 (0) | 2022.11.07 |
[React] 브라우저의 렌더링 과정 (0) | 2022.11.06 |
[React] Custom Hook (1) | 2022.10.22 |