
사실 원래는 구조 분해 할당에 대한 글을 작성하려 했는데 ..!!
배열 구조 분해 할당 코드가 바벨에서 어떻게 트랜스파일 되는지에 대한 설명을 작성하다가 문득 '바벨이 정확히 뭐지?' 라는 궁금증이 생겨서 이거부터 정리하고 가려고 글의 주제를 바꿨다 😅
프론트엔드 개발을 한다면 바벨이라는 단어는 무조건 한 번쯤은 들어봤을 것이다.
심지어 설정도 해봤을 텐데, 막상 바벨이 뭔지 설명해보라 하면 입이 잘 움직이지 않는다 .. (┬┬﹏┬┬)
따라서 이번 글에서는 바벨이 뭔지 물어봤을 때 간략하게나마 답할 수 있게 !! 설정을 할 때 뭔지는 알고 설정할 수 있게 !! 바벨에 대해 정리를 해보고자 한다.
1. 바벨
웹 개발을 처음 시작하며 기술 블로그들을 봤을 때, "이건 바벨로 트랜스파일돼서 그래요 ㅎㅎ", "바벨이 알아서 바꿔줘요" 같은 설명을 많이 봤었다.
그런데 난 이제 막 처음 시작해서 아무것도 모르는데 !! 저렇게만 말하고 넘어가니까 솔직히 뭔소리지 싶었다.
이후에 그냥 개발을 하다 보니 "아 바벨은 최신 JS를 구형 브라우저에서도 돌아가게 해주는 거구나" 하고 느낌은 잡았지만 ,, 아래에서 한 단계씩 자세히 살펴보자.
1.1. 바벨을 이해하기 전에 짚고 가야 할 전제
가장 중요한 전제는 "자바스크립트는 하나의 언어가 아니다" 라는 점이다.
실제로 우리가 쓰는 자바스크립트는 계속 확장되는 사양들의 집합이다.
예를 들면 ES5, ES2015(= ES6), ES2016, ES2017, ..., ESNext 이렇게 매년 새로운 문법과 기능이 추가되고 있다.
그리고, 문제는 바로 여기서 시작된다.
새로운 문법이 추가되는 속도와 모든 실행 환경이 그 문법을 지원하게 되는 속도가 너무나도 차이가 나기 때문이다.
매년 확장되는 문법들을 바로바로 지원하는 게 현실적으로 말이 될 리가 없으니 말이다 ..o((⊙﹏⊙))o.
Q. 그럼 뭐 실행 환경이 얼마나 제각각이길래 그럴까 ?
당장 생각나는 것들만 적어 보더라도, 아래와 같은 것들이 있다.
- 웹 브라우저
Chrome, Safari, Firefox, Edge 등 - 모바일 웹뷰
안드로이드, iOS 앱 내부 브라우저 - Node.js
- Electron, React Native, IoT 디바이스 등
이러한 환경들은 각자 다른 속도로 JS 문법을 지원하게 된다.
예를 들자면 아래와 같은 간단한 코드를 봐보자.
const userName = user?.profile?.name ?? "익명";
우리는 user의 profile의 name이 있다면 그 값을 userName에 할당하고, 값이 없다면 "익명"이라는 값을 할당하는 코드임을 바로 파악 가능할 것이다.
최신 브라우저 또한 우리와 마찬가지로 위의 코드를 문제 없이 잘 실행한다.
그러나 구형 브라우저라면 위 코드를 아예 실행하기도 전에 SyntaxError(문법 에러)를 띄워 버린다.
이 점에서 알 수 있는게 해당 문법을 모르는 환경은 부분적으로라도 실행하지 않는다는 점이다.
그냥 파싱 단계에서 아예 실패해버리기 때문에 로딩 자체가 실패하게 된다.
이러한 문제점에서 등장한 게 바로 "변환해서 실행하자 !" 라는 아이디어이다.
즉, 개발자는 최신 문법으로 작성하고, 실제 실행은 오래된 환경이 이해할 수 있는 문법으로 바꿔서 하자는 생각이다.
그리고, 이 역할을 담당하는 도구가 바로 바벨이다 🤩
1.2. 바벨의 정의
그럼 이제 어쩌다 바벨이란 게 생겼는지는 알았으니까 조금 더 정확하게 정의를 다시 내려보자.
바벨이란, 최신 자바스크립트 문법과 확장 문법(JSX, TypeScript 등)을 더 넓은 실행 환경에서 이해할 수 있는 형태의 자바스크립트로 변환(= transpile, 트랜스파일) 해주는 도구이다.
cf) 바벨은 트랜스파일러이다.
이건 그냥 참고하라고 적은 건데, 바벨과 관련된 글들을 보면 가끔 바벨을 컴파일러에 빗대서 설명하는 걸 봤어서 슬쩍 추가해봤다 !
일단 결론부터 말하면 바벨은 컴파일러 보다는 트랜스파일러에 가깝다고 보는 게 맞는 것 같다.
컴파일의 대표적인 예시를 떠올려 보면 뭐가 떠오를까 ?
난 C언어로 작성된 코드를 기계어로 바꾸는 게 떠올랐었다.
그리고 이 예시를 보면 알 수 있듯이 컴파일이라는 건, 고수준 언어(C)를 저수준 언어(기계어)로 바꾸는 것을 의미한다.
반대로, 트랜스파일이라는 것은 같은 수준의 언어를 같은 수준의 언어로 바꾸는 것을 말한다.
최신 JS를 구형 JS로 바꾸는 바벨의 역할을 보면, JS를 다른 형태의 JS로 바꾸는 것이니까 트랜스파일에 해당됨을 알 수 있다.
cf) 바벨을 무조건 사용해야 할까?
문득 생각 해보면, 나도 React Native로 개발을 진행하던 프로젝트에서는 바벨을 설정해주었지만, 평소에 Vite로 웹 개발을 할 때에는 딱히 설정한 기억이 없다.
Q. 그럼 최근엔 바벨이 별로 필요 없어진 걸까?
이 질문에 답하려면, 먼저 "바벨의 존재 이유 자체는 지금도 변하지 않았다"는 점을 잘 기억해야 한다.
즉, 자바스크립트 코드에는 여전히 실행 환경이 이해하지 못할 수 있는 문법이 존재하고, 이를 해결하기 위해 코드 변환은 여전히 필요하다.
그리고, 바벨은 이 역할을 대표적으로 수행해 온 도구였다.
다만, 바벨은 어디까지나 하나의 도구였기 때문에 더 빠르고 효율적인 새로운 도구가 등장한다면 그 자리를 대체당하는 것은 자연스러운 흐름이다.
최근엔 대부분의 프로젝트가 최신 브라우저를 기본 타겟으로 하기도 하고, Node.js 역시 비교적 최신 버전을 사용한다.
여기에 더해 Vite나 Next.js 같은 현대적인 도구들은 내부적으로 esbuild나 SWC 같은 매우 빠른 컴파일러를 사용해서 기본적인 코드 변환을 자동으로 처리해준다.
이로 인해서 개발자가 바벨을 직접 설정하고 관리할 필요가 점점 줄어들게 된 것이다.
즉, 바벨이라는 도구 자체는 예전만큼 자주 등장하지 않게 되었지만, 바벨이 담당하던 역할을 esbuild나 SWC 등의 도구들이 이어 받아서 수행하고 있다고 기억하면 된다.
2. 바벨이 하는 일
앞서 바벨이 왜 등장했는지와 어떤 일을 하는지를 큰 틀에서 봤다면, 이제 구체적으로 바벨이 어떤 단계를 거쳐 코드를 변환하는 지에 대해 살펴보자.
일단 한 줄로 설명하면, 바벨은 코드를 읽어서 구조로 만들고, 그 구조를 바꾼 뒤, 다시 코드로 만들어내는 일을 한다.
이 과정을 더 구체적으로 나누면, 바벨의 작업은 크게 세 단계로 이루어진다.
- 파싱
자바스크립트 코드를 읽어서 내부적으로 이해할 수 있는 구조로 변환한다. - 변환
만들어진 구조(AST)를 기반으로, 특정 문법이나 패턴을 원하는 형태로 바꾼다. - 생성
변환이 끝난 구조를 다시 자바스크립트 코드 문자열로 만들어낸다.
2.1. AST
바벨의 동작을 이해하려면 반드시 AST(Abstract Syntax Tree)에 대해 짚고 넘어가야 한다.
AST란 코드의 문장 구조를 트리 형태로 표현한 것이다.
우리가 작성한 자바스크립트 코드는 겉보기에는 단순한 문자열이지만, 바벨은 이를 그대로 다루지 않고, 문법적으로 어떤 의미를 가지는지 분석하여 코드 전체를 구조화된 트리로 변환한다.
예를 들어 간단히 아래와 같은 코드가 있다고 해보자.
const x = 1 + 2;
이 코드를 바벨은 아래와 같은 구조로 인식하게 된다.
- Program
- VariableDeclaration (const)
- VariableDeclarator
- Identifier (x)
- BinaryExpression (+)
- NumericLiteral (1)
- NumericLiteral (2)
- VariableDeclarator
- VariableDeclaration (const)
즉, 바벨에게 이 코드는 변수 선언이고, 그 안에 식별자와 덧셈 연산이 있으며, 그 연산의 양쪽에 숫자 리터러이 존재하는 구조물인 것이다.
Q. 그럼 바벨은 왜 문자열이 아니라 AST를 다룰까?
만약 바벨이 문자열을 기반으로 해서 코드 변환을 수행한다면, 괄호 안의 + 연산만 바꾸거나, 특정 import 구문만 찾아서 변환하거나, JSX 문법만 함수 호출로 바꾸는 작업은 거의 불가능하다.
왜냐하면 ~기 때문이다.
그러나 AST를 사용하면 이야기가 완전 달라진다.
바벨은 '이 노드는 BinaryExpression 이구나 !', '이건 ImportDeclaration 이구나!' 하면서 코드의 의미를 정확히 알고 있기 때문에 특정 문법 요소만 안전하게 선택해서 변환할 수 있게 되기 때문이다.
이게 바로 우리가 JSX를 React.createElement 호출로 바꾸거나, 특정 문법을 구형 문법으로 바꾸면서도 코드의 의미를 유지할 수 있는 이유이다.
'👩🏻💻 Frontend > 📌 JavaScript' 카테고리의 다른 글
| [JavaScript] 웹에서 바로 코드 테스트 가능한 사이트 (0) | 2026.02.11 |
|---|---|
| [JavaScript] 구조 분해 할당 (1) | 2026.02.11 |
| [JavaScript] 태스크 큐와 마이크로 태스크 큐 (0) | 2026.02.10 |
| [JavaScript] 이벤트 루프 (Event Loop) (0) | 2026.02.10 |
| [JavaScript] 자바스크립트가 싱글 스레드인 이유 (0) | 2026.02.09 |