들어가며
자바스크립트에서 var
키워드와 let
, const
키워드는 서로 다른 지역 스코프 갖습니다. var
키워드로 선언한 변수는 함수 레벨 스코프를 갖고, let
, const
키워드로 선언한 변수는 블록 레벨 스코프를 갖습니다.
그리고 우리는 ES6 문법을 활용하여 코드를 작성하고 이를 babel을 통해 ES5 문법으로 변환하여 하위 브라우저에서도 동작하는 코드로 컴파일하여 사용합니다. 작업을 할 때면 언제나 babel을 설정하여 사용하지만, 실제로 변환된 코드는 본 적이 거의 없습니다. 실제 배포되는 소스가 ES5 문법인 것과 달리, 제가 작업하는 파일은 언제나 ES6 문법으로 작업 된 파일이기 때문이죠.
그러다 문득 궁금해졌습니다. babel은 어떻게 서로 다른 스코프를 갖는 var
키워드와 let
, const
키워드를 변환할까? 어떻게 var
키워드로 let
, const
처럼 동작하게 할까?
이러한 궁금증을 해결하기 위하여 본 포스팅에서는 간단한 예시를 통해 babel이 어떻게 코드를 컴파일주는지 함께 보고자합니다.
babel은 왜 쓸까요?
babel은 ES6 이상의 최신 문법으로 작성된 자바스크립트를 ES5 문법으로 변환해주는 컴파일러(과거에는 트렌스파일러라고 불리기도 했으나, babel 공식 홈페이지에서 babel을 컴파일러라고 표현하므로, 본 글에서는 컴파일러라고 표현하도록 하겠습니다)입니다. 왜 굳이 문법을 변환시켜주는 것일까요? 그 이유는 다음과 같습니다.
자바스크립트는 ES6를 기준으로 아주 큰 변화를 맞이했습니다. 그중 가장 대표적인 것이 let
, const
키워드를 사용하여 변수를 선언할 수 있게 된 것입니다. 이를 통해 함수 레벨 스코프에서 블록 레벨 스코프를 가질 수 있게 되었습니다. 또한, class, 화살표 함수, 탬플릿 리터럴 등 현재 유의미하게 사용되는 문법이 많이 나왔습니다.
이러한 ES6 문법(혹은 더 최신의 문법)을 사용하면 개발이 쉬워지고 ES5에서 작업할 때 생겼던 문제들을 쉽게 해결할 수 있습니다. 문제는, ES6 문법은 말 그대로 최신 문법이기 때문에 구형 브라우저에서는 동작하지 않는다는 것에 있습니다.
이와 같은 이유로 우리는 ES5 문법으로 개발을 하거나 ES6 문법으로 개발 한 후 ES5 문법으로 변환해주어야 하는데, babel은 ES6 이상의 최신 문법으로 작성한 자바스크립트를 ES5 문법으로 자동으로 변환해주는 도구입니다.
babel로 변환하면 어떻게 될까요?
왜 babel을 사용하여 컴파일하는지 알아봤으니, 실제로 어떻게 컴파일되는지 확인해보도록 하죠!
블록문 컴파일
블록문(if, for)문을 활용하여 let, const를 사용하여 지역변수를 만들어봤습니다.
// ES6 문법
let startCount = 1;
if (startCount === 1) {
let startCount = 2;
const resetCount = 0;
for (let startCount = 0; i < 3; i++) {
console.log(startCount);
}
}
첫 번째 줄의 startCount
는 전역변수이며, if문 안에 있는 startCount
는 if문 안에서만 유효한 지역변수입니다. 또한 for문에 사용된 startCount
는 for문 안에서만 유효한 지역변수입니다. 변수명은 모두 같지만, let
과 const
키워드가 블록레벨 스코프를 갖기 때문에 세 개의 변수는 서로 충돌되거나, 하위에 선언된 값으로 재할당되지 않습니다.
이렇게 ES6 문법으로 작성된 자바스크립트를 babel로 컴파일하면 어떻게 될까요?
// babel이 변환한 ES5 문법
var startCount = 1;
if (startCount === 1) {
var _startCount = 2;
var resetCount = 3;
for (var _startCount2 = 0; i < 3; i++) {
console.log(_startCount2);
}
}
일단 ES5에서 변수 선언은 var
키워드로밖에 안되기 때문에, 모든 변수 선언문의 키워드가 var
로 변환된 것을 확인할 수 있습니다.
또한, var
키워드는 함수 레벨 스코프를 갖기 때문에, if문과 for문에 선언된 변수들은 더는 지역변수가 아닌 전역변수가 됩니다. 이 경우, 변수명을 그대로 두면 값이 계속 재할당 되어 문제가 생기게 되므로 babel은 같은 변수명이 있다면 뒤에 선언된 변수에 _
를 붙여 구분하고, 같은 변수명이 3개 이상일 경우 숫자를 붙여서 잘못된 재할당이 일어나지 않도록 하고 있습니다.
함수 컴파일
그렇다면, 함수의 지역변수는 어떻게 처리될까요? let
, const
를 사용하여 함수 내 지역변수를 만들고 컴파일 해보았습니다.
// ES6 문법
let startCount = 1;
const endCount = 1;
function foo() {
let startCount = 1;
const endCount = 1;
}
// babel이 변환한 ES5 문법
var startCount = 1;
var endCount = 1;
function foo() {
var startCount = 1;
var endCount = 1;
}
앞서 살펴본 예제와 같이 let
, const
키워드를 모두 var
키워드로 변환했지만, ES5에서도 함수는 지역스코프를 가지기 때문에 변수명을 변경하지는 않은 것을 확인할 수 있습니다. 해당 코드는 ES5에서도 ES6에서도 문제가 없는 코드라는 뜻이죠. 이를 통해 babel이 변환이 필요한 부분만 선택적으로 변환해준다는 것을 알 수 있습니다.
마치며
babel은 브라우저에 구애받지 않고 자바스크립트 최신 문법으로 개발할 수 있게 해주는 아주 고마운 도구입니다.
그러나 우리가 언제나 babel이 자동으로 컴파일해주는 환경에서만 작업할 수 있을까요? 우리는 다양한 환경에서 작업하게 될 것이고, 아주 오래된 코드를 수정해야 하는 경우를 만날 수도 있습니다. 이런 다양한 상황에서 적절한 대응을 하기 위해서는 ES5 문법과 최신 문법의 차이를 명확하게 알고 있어야 합니다.
그렇기때문에 ES6 이상의 최신 문법을 꾸준히 공부하고 활용하여 개발하는 것도 중요하지만, ES5 문법에 대한 공부와 이해 또한 놓치지 말아야 할 포인트라고 생각합니다.
그리고, 이번 포스팅에서는 서로 다른 스코프를 갖는 몇개의 키워드를 중심으로 풀어보았는데요! Babel 공식 홈페이지에서 온라인 컴파일이 가능하므로, 다른 최신문법들 또한 어떻게 컴파일되는지 직접 해보시면 더욱 좋은 공부가 될 것 같습니다.