Babel은 주로 ECMAScript 2015+ (ES6+) 코드를 이전 버전의 브라우저나 환경에서 호환되는 JavaScript 버전으로 변환하는데 사용하는 도구이다. 개발자는 Babel를 사용해 소스코드를 웹 브라우저가 처리할 수 있는 JavaScript 버전으로 변환하여 JavaScript 언어의 최신 기능을 활용할 수 있게 된다. TypeScript를 JavaScript로 컴파일하는데에도 사용할 수 있다.
JavaScript는 지속적으로 새로운 기능이 추가된다. 최신 기능은 개발자의 생산성을 늪이고 코드를 더 효율적으로 작성하는데 도움을 준다.
문제는 모든 브라우저가 최신 JavaScript 문법을 지원하지 않는다는 점이다. Babel을 사용하면 다양한 브라우저와 환경에서 코드를 일관되게 실행할 수 있다. 다양한 브라우저를 지원해야 하는 웹 사이트에서 특히 중요할 수밖에 없다.
Babel을 사용한다고 해서 최신 함수를 사용할 수 있는 것은 아니다. 브라우저 엔진이 구현하지 않은 새로운 함수를 사용하기 위해서, polyfill
을 사용한다. polyfill은 스크립트에 사용자가 원하는 최신 함수를 추가한다. 자바스크립트는 동적인 언어로 어떤 함수라도 스크립트에 추가할 수 있기 때문에, polyfill이 이를 대신한다. Babel은 컴파일시에, polyfill은 런타임에 실행된다는 차이점이 있다.
아래는 Babel의 변환 예시이다. 이외에도 다양한 변환이 있다.
화살표 함수는 ES6에서 도입된 기능으로, 함수 표현식을 간결하게 작성할 수 있게 해준다. Babel은 화살표 함수를 일반 함수 선언으로 변환한다.
// 입력 코드
const add = (a, b) => a + b;
// 변환된 코드
var add = function(a, b) {
return a + b;
};
ES6에서 도입된 클래스 문법을 변환할 수 있다.
// 입력 코드
class Person {
constructor(name) {
this.name = name;
}
greet() {
return `Hello, my name is ${this.name}`;
}
}
// 변환된 코드
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return 'Hello, my name is ' + this.name;
};
ES8에서 도입된 비동기 함수를 변환할 수 있다.
// 입력 코드
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
// 변환된 코드
function fetchData() {
return regeneratorRuntime.async(function fetchData$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return regeneratorRuntime.awrap(fetch('https://api.example.com/data'));
case 2:
response = _context.sent;
_context.next = 5;
return regeneratorRuntime.awrap(response.json());
case 5:
data = _context.sent;
return _context.abrupt("return", data);
case 7:
case "end":
return _context.stop();
}
}
});
}
ES6에서 도입된 디스트럭처링 할당 문법을 변환할 수 있다.
// 입력 코드
const [a, b] = [1, 2];
const { name, age } = { name: 'Alice', age: 25 };
// 변환된 코드
var _ref = [1, 2],
a = _ref[0],
b = _ref[1];
var _ref2 = { name: 'Alice', age: 25 },
name = _ref2.name,
age = _ref2.age;
ES6에서 도입된 템플릿 리터럴을 변환할 수 있다.
// 입력 코드
const greeting = `Hello, ${name}!`;
// 변환된 코드
var greeting = 'Hello, ' + name + '!';
JSX는 React에서 사용되는 문법으로, HTML과 유사한 구조를 JavaScript 코드에서 사용할 수 있게 한다. Babel은 JSX 코드를 일반 JavaScript로 변환한다.
// 입력 코드
const element = <h1>Hello, world!</h1>;
// 변환된 코드
const element = React.createElement('h1', null, 'Hello, world!');
TypeScript는 정적 타입을 명시할 수 있는 JavaScript의 상위집합이다. Babel은 TypeScript 코드를 일반 JavaScript로 변환한다.
// 입력 코드
const greeting: string = "Hello, world!";
// 변환된 코드
const greeting = "Hello, world!";
JavaScript 코드를 분석해 추상 구문 트리(Abstract Syntax Tree, AST)로 변환한다. 이 과정에서 코드를 구조화된 데이터로 표현하게 된다.
생성한 AST를 변환한다. 각종 플러그인과 프리셋을 사용해 브라우저가 지원하는 문법의 AST로 수정한다.
변환된 AST를 다시 JavaScript 코드로 변환한다.
Webpack은 JavaScript 정적 모듈 번들러(module bundler)이다. 모듈 번들러란 웹 애플리케이션을 구성하는 HTML, CSS, JS, 이미지 등의 리소스를 모두 각각의 모듈로 보고 이를 조합해서 하나의 결과물을 만드는 도구를 의미한다. 웹 개발의 복잡성이 증가하며 여러개의 파일과 모듈을 효율적으로 관리하고 번들링하는 도구의 필요성이 생겼다. Webpack은 이러한 필요성을 위해 다양한 파일 형식을 하나의 번들로 결합하고 최적화한다.
Webpack이 해결해주는 문제는 다음과 같다.
아래 코드처럼 스크립트를 추가하는 경우, 복잡한 애플리케이션을 개발할 때 변수의 이름이 중복될 문제가 있다. 반대로 하나의 거대한 JavaScript 파일을 만들어서 사용한다면 유효범위와 크기, 가독성, 유지보수의 문제가 생긴다. 따라서 파일 단위로 변수를 관리해야만 했다.
<body>
<script>
var num = 10;
function getNum() => {console.log(num);};
</script>
var num = 20;
function getNum() => {console.log(num);};
<script>
</script>
<script>
getNum(); // 20
</script>
</body>
TCP에 따라 브라우저에서 한번에 서버로 보낼 수 있는 HTTP 요청 숫자는 제한되어 있다. 스크립트가 많을수록 웹페이지를 로드하는 시간이 늘어나기 때문에 HTTP 요청 숫자를 줄이는 것이 웹 애플리케이션의 성능을 높이는 방법이다.
사용하지 않는 라이브러리나 코드가 생기거나, 라이브러리를 사용하더라도 일부 기능만 사용하는 경우가 있다. 모든 코드를 번들 파일에 포함시킨다면 불필요한 용량이 크게 증가할 것이다.
사용자는 웹페이지의 일부만 본다. 성능을 향상하기 위해선 모든 코드를 로드하는 것이 아닌, 필요한 모듈만 동적으로 로딩해야 한다.
Webpack의 가장 기본적인 기능은 여러 개의 JavaScript 파일을 하나의 번들 파일로 합치는 것이다. 이 과정에서 Webpack은 모듈 간의 종속성을 분석하고, 최적의 방식으로 결합한다.
모듈 번들러는 두 가지 단계를 거쳐 작동하게 된다.
의존성 그래프를 매핑하는 단계이다. 모든 파일 간 의존성을 파악하여 관계 맵을 생성한다. 브라우저가 함수를 요청할 때, 함수를 검색하기 위해 의존성 순서가 필수적이다.
여러 개의 코드 파일과 의존성을 브라우저가 처리할 수 있는 단일 파일로 제공한다. 의존성 그래프를 기반으로 코드 파일을 하나로 통합하고, 각 모듈이 독립적으로 작동하고 다른 모듈에서 사용할 수 있도록 하고, 모든 코드 파일과 의존성을 하나의 파일로 만들어낸다.
코드 분할은 애플리케이션에서 필요한 부분만 로드하도록 해 초기 로드 시간을 줄이는 방법이다. Webpack은 코드 분할을 통해 대규모 애플리케이션의 성능을 최적화할 수 있다.
로더는 Webpack이 JavaScript 외에 다른 파일(CSS, Image, Font 등)을 처리할 수 있게 해준다.
Babel
은 자바스크립트 코드를 변환하는데 사용하는 도구이다. 최신 JavaScript 문법을 구형 브라우저에서도 호환될 수 있도록 변환하는 역할을 한다.
Webpack
은 여러 개의 파일과 리소스를 하나의 번들로 묶어주는 모듈 번들러(module bundler)이다. JavaScript, CSS, 이미지 등 다양한 리소스를 효율적으로 관리하고 빌드할 수 있도록 도와준다.
Babel
과 Webpack
은 현대 웹 개발에서 필수적으로 사용된다. 서로 보완적인 역할을 하며, Babel로 최신 문법을 변환한 뒤 Webpack으로 번들링하여 배포하는 방식이 일반적이다.