2025-09-23 20:43

  • 바벨(Babel)은 최신 버전의 자바스크립트 코드를 구형 브라우저에서도 동작하는 이전 버전 코드로 변환해주는 ‘트랜스파일러’이다.

  • 개발자는 브라우저 호환성 걱정 없이 화살표 함수, 클래스 같은 최신 문법을 자유롭게 사용할 수 있게 된다.

  • 바벨은 특정 문법 변환 규칙을 정의하는 ‘플러그인’과 이들의 묶음인 ‘프리셋’을 통해 동작하며, 필요한 기능만 선택적으로 적용할 수 있다.

자바스크립트 개발자 필수 교양 바벨 완벽 정복 핸드북

모던 웹 개발의 세계에 발을 들였다면 ‘바벨(Babel)‘이라는 이름을 한 번쯤은 들어봤을 것이다. 리액트(React)나 뷰(Vue) 같은 프레임워크 튜토리얼을 따라 하다 보면 어김없이 등장하고, 웹팩(Webpack) 설정 파일에서도 중요한 자리를 차지한다. 하지만 많은 개발자가 바벨을 ‘그냥 최신 자바스크립트를 쓰게 해주는 도구’ 정도로만 알고 넘어가는 경우가 많다.

바벨은 단순히 문법을 변환하는 도구를 넘어, 자바스크립트 생태계가 파편화되지 않고 끊임없이 발전할 수 있도록 지탱해주는 핵심적인 기술이다. 이 핸드북은 바벨이 왜 만들어졌는지, 어떤 원리로 동작하는지, 그리고 어떻게 효과적으로 사용할 수 있는지에 대한 모든 것을 담았다. 바벨에 대한 막연한 이해를 명확한 지식으로 바꾸고 싶다면, 이 글이 완벽한 안내서가 될 것이다.

1. 바벨의 탄생 배경 시간 여행이 필요했던 자바스크립트

바벨의 필요성을 이해하려면 먼저 자바스크립트라는 언어와 이를 실행하는 브라우저의 역사를 알아야 한다.

자바스크립트의 진화와 파편화 문제

자바스크립트의 공식 명칭은 ‘ECMAScript’다. TC39라는 기술 위원회는 매년 ECMAScript의 새로운 버전을 발표하며 언어의 기능을 발전시킨다. 2015년에 발표된 **ES2015(통칭 ES6)**는 자바스크립트 역사상 가장 큰 변화를 가져왔다. 화살표 함수(=>), 클래스(class), let/const, 템플릿 리터럴 등 개발 생산성을 획기적으로 높여주는 기능들이 대거 추가되었다.

개발자들은 이 새로운 기능들을 사용해 더 깔끔하고 효율적인 코드를 작성하고 싶어 했다. 하지만 여기에는 치명적인 문제가 있었다. 바로 **‘브라우저 호환성’**이다.

크롬, 파이어폭스, 사파리, 그리고 악명 높았던 인터넷 익스플로러(IE)까지, 세상에는 너무나도 다양한 브라우저가 존재한다. 각 브라우저는 저마다 다른 자바스크립트 엔진을 가지고 있어 새로운 언어 기능을 지원하는 속도와 범위가 제각각이었다. 내가 최신 문법인 화살표 함수를 사용해 코드를 작성해도, 구형 브라우저를 사용하는 사용자는 문법 오류(Syntax Error)를 마주하며 웹사이트가 아예 동작하지 않는 경험을 하게 되는 것이다.

이는 개발자에게 큰 딜레마를 안겨주었다.

  • 선택 1: 최신 기술을 포기한다. 모든 브라우저에서 확실히 동작하는 낡은 ES5 문법만으로 개발한다. (안전하지만, 생산성과 코드 품질이 저하된다.)

  • 선택 2: 사용자를 포기한다. 최신 문법을 마음껏 사용하고, 구형 브라우저 사용자는 지원하지 않는다. (혁신적이지만, 많은 잠재적 사용자를 잃는다.)

두 가지 선택 모두 만족스럽지 않았다. 이때, 이 딜레마를 해결하기 위해 혜성처럼 등장한 것이 바로 바벨이다.

바벨 시간을 거스르는 번역가

바벨은 이 문제에 대한 우아한 해결책을 제시했다.

“개발자님, 최신 문법으로 마음껏 코드를 작성하세요. 제가 그 코드를 모든 브라우저가 이해할 수 있는 낡은 코드로 ‘번역’해 드릴게요.”

바벨은 일종의 ‘시간 여행 기계’ 혹은 ‘번역가’와 같다. 개발자가 ES6+의 최신 문법으로 작성한 코드를 입력받아, IE를 포함한 거의 모든 브라우저에서 문제없이 실행되는 ES5 버전의 코드로 변환(Transpile)해준다.

JavaScript

// 개발자가 작성한 최신 코드 (ES6)
const greet = (name) => `Hello, ${name}!`;

// 바벨이 변환한 결과물 (ES5)
"use strict";

var greet = function greet(name) {
  return "Hello, " + name + "!";
};

이 덕분에 개발자들은 더 이상 브라우저 호환성 문제에 얽매이지 않고, 언어의 최신 기능을 적극적으로 활용하며 개발 생산성과 코드 품질을 높이는 데만 집중할 수 있게 되었다. 이것이 바로 바벨이 모던 웹 개발의 필수 도구로 자리 잡게 된 이유다.

2. 바벨의 작동 원리 코드 변환의 세 단계

바벨은 어떻게 마법처럼 코드를 변환하는 것일까? 내부적으로 바벨은 세 가지 주요 단계를 거쳐 동작한다.

  1. 파싱 (Parsing)

  2. 변환 (Transforming)

  3. 생성 (Generating)

이를 문장을 번역하는 과정에 비유해 보자. “I love you”라는 영어 문장을 한국어로 번역하려면, 먼저 문장의 구조(주어: I, 동사: love, 목적어: you)를 분석해야 한다. 그 다음, 분석된 구조를 한국어 어순과 문법에 맞게 ‘나는 너를 사랑해’라는 구조로 바꾼다. 마지막으로 이 구조를 다시 완전한 문장으로 합치면 번역이 완성된다. 바벨도 이와 매우 유사한 과정을 거친다.

1단계: 파싱 (Parsing)

이 단계에서 바벨은 입력받은 자바스크립트 코드를 분석하여 추상 구문 트리(Abstract Syntax Tree, AST) 라는 자료구조로 변환한다. AST는 코드의 구조를 나무 형태로 표현한 것으로, 각 노드는 코드의 특정 부분(변수 선언, 함수 호출 등)을 나타낸다.

예를 들어 const n = 1; 이라는 코드는 다음과 같은 AST로 파싱될 수 있다.

JSON

{
  "type": "VariableDeclaration",
  "kind": "const",
  "declarations": [
    {
      "type": "VariableDeclarator",
      "id": {
        "type": "Identifier",
        "name": "n"
      },
      "init": {
        "type": "NumericLiteral",
        "value": 1
      }
    }
  ]
}

이 과정은 마치 영어 문장의 문법 구조를 파악하는 것과 같다. 바벨은 이 AST를 통해 코드의 의미와 구조를 정확하게 이해하게 된다. (@babel/parser가 이 역할을 담당한다.)

2단계: 변환 (Transforming)

파싱을 통해 생성된 AST를 가지고 실제 코드 변환 작업을 수행하는 단계다. 바벨은 AST를 처음부터 끝까지 순회하면서, 우리가 설정한 규칙(플러그인)에 따라 노드를 변경하거나 추가, 삭제한다.

예를 들어, constvar로 바꾸는 플러그인이 적용되었다면, 바벨은 AST를 순회하다가 VariableDeclaration 노드를 만나면 kind 속성을 'const'에서 'var'로 바꾼다. 화살표 함수를 일반 함수로 바꾸는 플러그인은 ArrowFunctionExpression 노드를 FunctionExpression 노드로 통째로 교체한다.

이것이 바벨의 핵심이며, 어떤 플러그인을 사용하느냐에 따라 변환 결과가 완전히 달라진다. (@babel/traverse가 이 역할을 담당한다.)

3단계: 생성 (Generating)

변환 단계에서 수정된 AST를 다시 실제 자바스크립트 코드(문자열)로 변환하는 마지막 단계다. 이 과정에서 소스맵(Source Map)을 함께 생성하여, 변환된 코드가 원래 소스 코드의 어느 부분에 해당하는지 추적할 수 있게 해준다. (@babel/generator가 이 역할을 담당한다.)

이 세 단계를 거쳐 개발자가 작성한 최신 코드는 구형 브라우저에서도 안전하게 동작하는 코드로 재탄생하게 된다.

3. 바벨 실전 사용법 설정과 실행

이제 바벨을 실제 프로젝트에 어떻게 적용하는지 알아보자.

기본 패키지 설치

바벨을 사용하기 위해서는 몇 가지 핵심 패키지를 설치해야 한다.

  • @babel/core: 바벨의 핵심 엔진. 파싱, 변환, 생성의 모든 과정을 관장한다.

  • @babel/cli: 터미널(Command Line)에서 바벨을 실행할 수 있게 해주는 도구.

  • @babel/preset-env: 가장 널리 사용되는 공식 프리셋.

Bash

npm install --save-dev @babel/core @babel/cli @babel/preset-env

핵심 구성 요소: 플러그인과 프리셋

바벨의 변환 작업은 플러그인(Plugin)프리셋(Preset) 에 의해 결정된다.

플러그인 (Plugins)

플러그인은 특정 문법 하나를 어떻게 변환할지에 대한 규칙을 담고 있는 작은 프로그램이다. 예를 들어, 화살표 함수만 변환하고 싶다면 @babel/plugin-transform-arrow-functions 플러그인을 설치하고 설정 파일에 추가하면 된다.

하지만 최신 자바스크립트 문법은 수십 가지가 넘는다. 이들을 하나하나 플러그인으로 추가하는 것은 매우 번거롭고 비효율적이다.

프리셋 (Presets)

프리셋은 이런 번거로움을 해결하기 위해 등장했다. 프리셋은 특정 목적을 위해 여러 플러그인들을 모아놓은 ‘플러그인 세트’다. 개발자는 프리셋 하나만 설정함으로써 관련된 수많은 플러그인을 한 번에 적용할 수 있다.

가장 대표적인 프리셋은 @babel/preset-env다. 이 프리셋의 가장 강력한 기능은 타겟 브라우저를 설정할 수 있다는 점이다. 예를 들어 “최신 2개 버전의 브라우저와 점유율 1% 이상의 브라우저만 지원하겠다”고 설정하면, 해당 브라우저들이 이미 지원하는 최신 문법은 굳이 변환하지 않고 그대로 둔다. 이는 불필요한 변환을 줄여 결과물의 용량을 최적화하는 데 큰 도움이 된다.

이 외에도 리액트의 JSX 문법을 변환해주는 @babel/preset-react, 타입스크립트를 자바스크립트로 변환하는 @babel/preset-typescript 등 다양한 공식 프리셋이 존재한다.

바벨 설정 파일 작성

프로젝트의 루트 디렉터리에 babel.config.json (또는 .js, .cjs) 파일을 생성하여 바벨의 동작을 설정한다.

JSON

// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 0.25%, not dead" // 전 세계 점유율 0.25% 이상, 공식 지원이 종료되지 않은 브라우저
      }
    ]
  ]
}

위 설정은 @babel/preset-env를 사용하며, 지원할 브라우저 범위를 명시하고 있다.

바벨 실행하기

설정이 완료되면 babel 명령어를 통해 코드를 변환할 수 있다. src 폴더에 있는 모든 자바스크립트 파일을 변환하여 dist 폴더에 저장하는 명령어는 다음과 같다.

Bash

npx babel src --out-dir dist

package.jsonscripts에 등록하여 간편하게 사용할 수도 있다.

JSON

// package.json
"scripts": {
  "build": "babel src --out-dir dist"
}

이제 npm run build 명령어를 실행하면 바벨 변환이 자동으로 수행된다. 실제 프로젝트에서는 웹팩의 babel-loader와 함께 사용하여 개발 서버 실행이나 빌드 과정에 통합하는 것이 일반적이다.

4. 심화 학습 폴리필과 런타임

바벨을 사용하다 보면 한 가지 의문이 생긴다. 바벨은 constvar로 바꾸는 등 ‘문법’을 변환하는 역할을 한다. 그렇다면 ES6에 새로 추가된 Promise, Map, Set 같은 ‘기능(객체나 메서드)‘은 어떻게 처리할까?

구형 브라우저(예: IE11)는 Promise라는 객체 자체를 알지 못한다. 이런 경우 문법 변환만으로는 코드가 동작하지 않는다. 이 문제를 해결하는 것이 바로 **폴리필(Polyfill)**이다.

폴리필 (Polyfill): 비어있는 기능을 채우다

폴리필은 특정 기능이 없는 환경에서 해당 기능을 구현해주는 코드 조각이다. 마치 벽의 구멍을 메꾸는 ‘폴리필라’ 퍼티처럼, 브라우저에 비어있는 기능을 채워주는 역할을 한다.

바벨은 core-js라는 라이브러리를 통해 폴리필을 자동으로 주입해줄 수 있다. @babel/preset-env 설정에 useBuiltIns 옵션을 추가하면 된다.

JSON

// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage", // 'usage': 코드에서 사용된 기능에 대한 폴리필만 포함
        "corejs": 3 // core-js 버전 명시
      }
    ]
  ]
}

useBuiltIns: 'usage' 옵션은 매우 스마트하게 동작한다. 바벨이 코드를 분석하여 PromiseArray.from 같은 기능이 사용된 것을 감지하면, 해당 기능에 필요한 폴리필만 결과물에 자동으로 포함시켜준다. 이로써 불필요한 코드가 포함되는 것을 막고 번들 크기를 최적화할 수 있다.

런타임 변환 (@babel/plugin-transform-runtime): 중복과 오염을 막는 기술

바벨은 클래스나 async/await 같은 복잡한 문법을 변환할 때, 종종 작은 헬퍼(helper) 함수들을 코드에 삽입한다. 예를 들어, class 문법을 변환하면 _classCallCheck 같은 헬퍼 함수가 파일 상단에 추가된다. 만약 여러 파일에서 class를 사용했다면, 이 헬퍼 함수가 모든 파일에 중복으로 포함되어 비효율을 유발한다.

또한, 폴리필은 Promise 같은 전역 객체를 직접 수정하거나(window.Promise = ...), Array.prototype에 새로운 메서드를 추가하는 방식으로 동작한다. 이는 애플리케이션 개발에서는 편리하지만, 다른 라이브러리와 충돌을 일으킬 수 있어 라이브러리 개발 시에는 위험할 수 있다.

@babel/plugin-transform-runtime은 이 두 가지 문제를 해결한다.

  1. 헬퍼 함수 중복 제거: 반복적으로 삽입되던 헬퍼 함수들을 @babel/runtime이라는 별도 패키지에서 가져오도록 코드를 수정한다. 이로써 모든 파일이 헬퍼 함수를 공유하게 되어 코드 중복이 사라진다.

  2. 전역 스코프 오염 방지: 폴리필이 전역 객체를 직접 건드리지 않도록 한다. Promise가 필요하면 전역 Promise를 만드는 대신, core-js에서 Promise 구현체를 가져와 지역적으로 사용하도록 코드를 변환한다.

구분@babel/preset-envuseBuiltIns@babel/plugin-transform-runtime
목적애플리케이션의 브라우저 호환성 확보라이브러리 개발 또는 헬퍼 중복 제거
작동 방식전역 스코프에 폴리필 주입 (e.g., Promise, Array.prototype.find)헬퍼/폴리필을 모듈에서 import하여 사용
전역 오염발생함 (의도된 동작)발생하지 않음
주요 사용처웹 애플리케이션재사용 가능한 라이브러리, 패키지

일반적으로 웹 애플리케이션을 개발할 때는 @babel/preset-env의 폴리필 기능을 사용하고, 다른 프로젝트에서 사용될 라이브러리를 개발할 때는 @babel/plugin-transform-runtime을 사용하는 것이 좋은 전략이다.

5. 결론 바벨, 자바스크립트 생태계의 든든한 다리

바벨은 단순히 낡은 브라우저를 위한 임시방편이 아니다. 바벨은 자바스크립트라는 언어가 과거의 유산에 발목 잡히지 않고 끊임없이 미래를 향해 나아갈 수 있도록 만들어준 핵심적인 인프라다. 개발자들은 바벨 덕분에 새로운 언어 명세가 발표되면 즉시 현업에 적용하며 더 나은 코드를 탐구할 수 있었고, 이는 곧 웹 생태계 전체의 발전으로 이어졌다.

최근에는 Rust 기반의 SWC나 Go 기반의 esbuild처럼 훨씬 빠른 속도를 자랑하는 트랜스파일러들이 등장하며 바벨의 입지를 위협하고 있다. 하지만 수년간 쌓아온 방대한 플러그인 생태계와 안정성, 그리고 세밀한 설정이 가능하다는 점에서 바벨은 여전히 많은 프로젝트에서 중요한 역할을 담당하고 있다.

이 핸드북을 통해 바벨이 어떤 고민 속에서 탄생했고, 어떤 원리로 동작하며, 어떻게 우리 코드의 호환성을 보장해주는지 깊이 있게 이해했기를 바란다. 이제 당신은 더 이상 babel.config.json 파일을 두려워하지 않고, 당신의 프로젝트에 가장 적합한 방식으로 바벨을 설정하고 활용할 수 있는 자신감을 얻었을 것이다. 바벨과 함께, 브라우저 호환성의 족쇄에서 벗어나 자유롭게 최신 자바스크립트의 세계를 탐험하길 바란다.