해당 포스트는
babel
에 대해 정리한 포스트입니다.
주관적으로 해석한 내용이 들어가 있어서 잘못된 내용이 포함될 수 있습니다.
사용 경험이 거의 없어서 가벼운 내용만 담고 있습니다.
🪄 babel
공식 문서에서는 Babel is a JavaScript compiler.
라고 합니다.
컴파일러보다는 트랜스파일러가 조금 더 적확한 표현인 것 같습니다. ( 물론 개인적인 의견입니다… 🥲 )
그러면 컴파일러와 트랜스파일러가 무엇일까요? 그 부분은 컴파일러/인터프리터/트랜스파일러를 참고해주세요!
그러면 트랜스파일러가 어떤 언어를 다른 언어로 바꿔주는 것이라고 이해했는데 이걸 왜 쓰는걸까요?
🐔🍗 babel을 사용하는 이유
우리가 JavaScript
를 사용할 때는 일반적으로 최신 문법을 사용하는 것을 선호합니다.
1
const sum = (...args) => args.reduce((acc, curr) => acc + curr);
위처럼 대부분은 function
으로 함수 표현식을 작성하는 것보단 화살표 함수로 함수 표현식을 작성하는 것을 더 선호할 것입니다.
( TMI
:: 저는 화살표 함수를 굉장히 좋아합니다. )
아무튼 그래서 위처럼 코드를 구성했는데 어떤 브라우저에서는 화살표 함수를 지원하지 않을 수 있습니다.
그런 경우는 어떻게 해야할까요? 특정 브라우저를 위해서 작성했던 모든 화살표 함수를 function
으로 바꿔야할까요?
뭐 그렇게 해결할 수 있겠지만 그러면 너무 힘들고 비효율적이죠.
근데 거기에다가 async/await
, class
같은 문법도 지원하지 않는다면 모두 바꿔주는 것은 엄청난 노가다가 될 것입니다.
이럴 때 사용하는 방법이 babel
을 이용한 트랜스파일링입니다.
🕹️ babel을 사용하는 방법
사실 글은 적고 있지만 실제로 사용해 본 적은 거의 없습니다.
최근에는 create-react-app
/ create-next-app
으로만 세팅을 해서 내부적으로 webpack
으로 babel
이 세팅되어 있어서 제가 건드릴 부분이 없었습니다.
( 사실 webpack
에 대한 두려움이 있어서 건드릴 생각을 안합니다…🥲 )
그래도 간단하게 어떤 느낌인지 예시를 들어보겠습니다.
0️⃣ 설치
일단 먼저 npm
으로 babel
과 원하는 plugin
을 설치해야합니다.
1
2
3
4
5
6
7
8
# "babel"을 "cli"로 실행시키기 위해 설치
npm i -D @babel/cli
# "arrow function"을 일반 "function"으로 트랜스파일링할 때 사용하는 플러그인
npm i -D @babel/plugin-transform-arrow-functions
# "JSX"를 "React" 문법으로 바꿔주는 플러그인 ( "React.createElement()"로 바꿔줌 )
npm i -D @babel/plugin-transform-react-jsx
1️⃣ 명령어
기본적으로 cli
를 통해서 babel
을 적용할 수 있습니다.
--plugins=<플러그인1[,플러그인2[,...]]>
: 플러그인 적용--out-file <경로>
: 트랜스파일링의 결과물 위치 지정
1
2
3
4
5
# (1) "cli"에서만 결과가 출력됩니다. ( "ES6/index.js"는 트랜스파일링할 파일 )
npx babel --plugins @babel/plugin-transform-arrow-functions ES6/index.js
# (2) "ES6/index.js" 파일에 두 가지의 프러그인을 적용해서 "ES5/index.js"에 생성해줘 라는 의미를 갖는 명령어입니다.
npx babel --plugins=@babel/plugin-transform-arrow-functions,@babel/plugin-transform-react-jsx ES6/index.js --out-file ES5/index.js
(1)
과 (2)
를 보면서 느껴지는 게 코드가 너무 길고 외우기 힘듭니다.
package.json
의 scripts
에 작성한다고 쳐도 너무 길고 수정사항을 쉽게 반영하기가 힘든 문제가 있습니다.
이런 불편함을 해결하기 위해서는 babel.config.js
를 이용하면 됩니다.
경로가 맞다고 치고 (2)
을 실행한다면 아래와 같이 변환됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// ES6/index.js
const Commnet = () => <span>message</span>;
const Page = ({ children, isLoggedIn }) => {
if (!isLoggedIn) return <span>You need to LogIn</span>;
return (
<>
<span>Hello, Babel</span>
{children}
</>
);
};
const App = () => {
const obj = { x: 1, y: 2, z: 3 };
return (
<>
{/* (3) */}
<section>
<Page isLoggedIn>
<Commnet />
</Page>
</section>
{/* (4) */}
<section>
<Page>{Commnet()}</Page>
</section>
{/* (5) */}
<section>
<Page {...obj} />
</section>
{/* (6) */}
<section>
<Page x={obj.x} y={obj.y} z={obj.z} />
</section>
</>
);
};
// ES5/index.js
const Commnet = function () {
return /*#__PURE__*/ React.createElement("span", null, "message");
};
const Page = function ({ children, isLoggedIn }) {
if (!isLoggedIn)
return /*#__PURE__*/ React.createElement("span", null, "You need to LogIn");
return /*#__PURE__*/ React.createElement(
React.Fragment,
null,
/*#__PURE__*/ React.createElement("span", null, "Hello, Babel"),
children
);
};
const App = function () {
const obj = {
x: 1,
y: 2,
z: 3,
};
return /*#__PURE__*/ React.createElement(
React.Fragment,
null,
/* (3) */
/*#__PURE__*/ React.createElement(
"section",
null,
/*#__PURE__*/ React.createElement(
Page,
{
isLoggedIn: true,
},
/*#__PURE__*/ React.createElement(Commnet, null)
)
),
/* (4) */
/*#__PURE__*/ React.createElement(
"section",
null,
/*#__PURE__*/ React.createElement(Page, null, Commnet())
),
/* (5) */
/*#__PURE__*/ React.createElement(
"section",
null,
/*#__PURE__*/ React.createElement(Page, obj)
),
/* (6) */
/*#__PURE__*/ React.createElement(
"section",
null,
/*#__PURE__*/ React.createElement(Page, {
x: obj.x,
y: obj.y,
z: obj.z,
})
)
);
};
(3)
,(4)
에 대한 차이가 궁금하다면 지연평가를 읽어보시는 것을 추천드립니다./*#__PURE__*/
는 그냥 주석이 아닌 Tree-Shaking이랑 연관있는 어노테이션입니다.
( 해당 함수가 사이드이펙트가 없는 순수 함수라는 것을 증명하는 어노테이션입니다. )
2️⃣ babel.config.js
babel
에 대한 기본 세팅을 작성하는 파일입니다.
최상위에 babel.config.js
라는 파일만 작성해두면 babel
을 실행할 때 자동으로 파일을 읽어서 옵션들을 적용해줍니다.
1
2
3
4
5
6
7
8
// 아래처럼 사용하면 "(2)"에서 적용한 플러그인을 똑같이 적용할 수 있습니다.
const presets = [];
const plugins = [
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-react-jsx",
];
module.exports = { presets, plugins };
이제는 아래와 같은 명령어를 수행하면 플러그인들이 자동으로 적용됩니다.
1
npx babel ES6/index.jsx --out-file ES5/index.jsx
presets
: 자주 쓰는 유용한 플러그인들을 포함하고 있는 플러그인 ( 스타트팩같은 느낌이죠 )
( babel-preset-react을 확인해보시면 어떤 플러그인들이 있고 어떻게 적용하는지 알려줍니다. )
📇 polyfill
구형 브라우저에서 지원하지 않는 기능을 지원해주기 위해서 자겨오는 코드 뭉치입니다.
예를 들면 Promise
같은 경우 babel
의 트랜스파일링으로 변화시켜줄 수 없습니다.
따라서 Promise
의 코드 뭉치를 런타임에 추가시켜줌으로써 문제 없이 동작할 수 있도록 도와주는 것을 의미합니다.