Babel 8 Beta — CJS를 버리고 ESM 전용으로 간다
2년간의 알파를 거쳐 베타에 진입한 Babel 8의 핵심 변경사항과 마이그레이션 전략을 정리한다.
Babel은 JavaScript 생태계에서 가장 오래 살아남은 도구 중 하나다. 2014년 첫 릴리스 이후 ES6→ES5 트랜스파일링의 대명사였고, JSX, TypeScript, 데코레이터 등 브라우저가 지원하기 전의 문법을 먼저 써볼 수 있게 해준 "시간 여행 머신" 같은 존재다. 그 Babel이 8.0 베타에 진입했다. 핵심 변화는 ESM(ES Modules) 전용 배포다. CommonJS는 더 이상 제공하지 않는다.
Babel 7에서 무엇이 달라지나
| 항목 | Babel 7 | Babel 8 |
|---|---|---|
| 모듈 시스템 | CJS + ESM 이중 배포 | ESM 전용 |
| Node.js 최소 버전 | 12+ | 20+ |
| 설정 파일 | .babelrc, babel.config.js 등 | babel.config.mjs 권장 |
| 기술 부채 | 10년치 누적 | 대량 정리 |
| 단계 | 마지막 버전 7.29.0 배포 완료 | 베타 (안정화 중) |
가장 눈에 띄는 변화는 역시 CJS 드롭이다. 비유하면 양손잡이 투수가 "이제 왼손으로만 던지겠다"고 선언한 것과 같다. 한쪽을 포기하는 대신, 남은 쪽에 집중해서 더 빠르고 가벼운 패키지를 만들겠다는 판단이다.
[💡 잠깐! 이 용어는?]
ESM(ES Modules): import/export 구문을 사용하는 JavaScript 표준 모듈 시스템. Node.js 12부터 실험적으로, 20부터는 require(esm)까지 지원하며 사실상 표준이 됐다.
ESM 전용이 가능해진 배경
Babel 8이 CJS를 버릴 수 있게 된 결정적 이유는 Node.js 20의 require(esm) 지원이다. 이전에는 ESM 전용 패키지를 require()로 불러올 수 없어서, CJS 사용자를 위해 이중 배포가 필수였다. Node.js 20이 이 제약을 제거하면서 ESM 전용 배포의 현실적 장벽이 사라졌다.
// Node.js 20+에서는 CJS에서 ESM을 require() 가능
// 이전에는 이 코드가 에러를 던졌다
const babel = require('@babel/core')
// babel.config.mjs (ESM 설정 파일)
export default {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript'
]
}Babel 팀은 블로그에서 "계획했던 모든 브레이킹 체인지를 완료했고, 대량의 기술 부채를 제거했다"고 밝혔다. 2년 넘게 알파를 유지한 이유가 여기에 있다. 내부 코드를 대대적으로 정리하면서 동시에 Babel 7과 8을 컴파일 타임 피처 플래그로 하나의 코드베이스에서 관리해왔다.
마이그레이션 전략
Babel 팀은 대부분의 브레이킹 체인지를 Babel 7에서 옵션으로 미리 제공해왔다. 덕분에 Babel 7 최신 버전에서 옵션을 하나씩 켜면서 점진적으로 전환할 수 있다.
1단계: Babel 7을 최신 버전(7.29.0)으로 업데이트
npm install @babel/core@7 @babel/preset-env@7 @babel/preset-typescript@72단계: Babel 8 호환 옵션 활성화
module.exports = {
presets: [
['@babel/preset-env', {
targets: { node: '20' },
// Babel 8에서 기본값이 되는 옵션들을 미리 활성화
bugfixes: true
}],
['@babel/preset-typescript', {
// Babel 8에서 기본값이 되는 옵션
allowDeclareFields: true
}]
]
}3단계: 설정 파일을 ESM으로 전환
export default {
presets: [
['@babel/preset-env', {
targets: { node: '20' },
bugfixes: true
}],
'@babel/preset-typescript'
]
}.babelrc나 babel.config.js(CJS) 대신 babel.config.mjs(ESM)로 전환하면 Babel 8에서도 그대로 사용할 수 있다.
[💡 잠깐! 이 용어는?] 피처 플래그(Feature Flag): 코드에 새 기능을 넣어두되, 런타임이나 빌드 타임에 켜고 끌 수 있게 하는 기법. Babel은 7과 8 코드를 하나의 리포지토리에서 관리하면서 피처 플래그로 분기했다.
Babel이 아직도 필요한가?
TypeScript가 자체 트랜스파일링을 하고, tsc --noEmit으로 타입 체크만 쓰는 프로젝트도 많다. Vite는 esbuild를, Next.js는 SWC를 기본 트랜스파일러로 쓴다. 그렇다면 Babel의 자리는 어디인가?
| 시나리오 | Babel 필요 여부 |
|---|---|
| Next.js/Vite 기본 설정 | 불필요 (SWC/esbuild가 대체) |
| 커스텀 Babel 플러그인 사용 | 필요 |
| TC39 Stage 2~3 제안 사용 | 필요 (데코레이터, using 등) |
| 레거시 프로젝트 유지보수 | 필요 |
| Relay, Styled Components 등 Babel 의존 도구 | 필요 |
Babel의 핵심 가치는 플러그인 생태계다. 코드 변환의 "스위스 아미 나이프"로서, SWC나 esbuild가 커버하지 못하는 커스텀 트랜스폼이 필요한 프로젝트에서는 여전히 대체재가 없다.
Babel 7.29.0 — 마지막 메이저 릴리스
Babel 7의 마지막 릴리스인 7.29.0도 함께 배포됐다. 이 버전은 사실상 "Babel 7의 유종의 미"다. 이후 Babel 7에는 보안 패치만 제공될 예정이며, 모든 개발 역량은 Babel 8에 집중된다.
비유하면 건물의 한 층에서 다음 층으로 이사하면서, 이전 층의 조명과 수도는 유지하되 새 가구는 더 이상 들이지 않겠다는 것이다.
정리
- Babel 8 Beta가 2년간의 알파를 거쳐 드디어 출시됐다
- ESM 전용 배포가 가장 큰 변화다. CommonJS 번들은 더 이상 제공하지 않는다
- Node.js 20의
require(esm)지원이 이 전환을 가능하게 했다 - 마이그레이션은 Babel 7에서 호환 옵션을 미리 켜는 점진적 전략이 권장된다
- Babel 7.29.0이 7.x의 마지막 릴리스이며, 이후는 보안 패치만 제공된다
- SWC/esbuild 시대에도 커스텀 플러그인이 필요한 프로젝트에서 Babel은 여전히 유효하다
Babel 8을 당장 도입할 필요는 없다. 하지만 Babel 7을 사용 중이라면 7.29.0으로 업데이트하고, 호환 옵션을 켜두는 것부터 시작하는 게 좋다. 이 작업만 해두면 Babel 8 Stable이 나왔을 때 전환 비용이 크게 줄어든다.
참고:
- Babel 8 Beta Blog Post: https://babeljs.io/blog/2025/05/30/babel-8-beta
- Babel 7.29.0 Release: https://babeljs.io/blog/2026/01/31/7.29.0
- Babel Migration Guide: https://next.babeljs.io/docs/v8-migration
같은 카테고리 · Tooling
비슷한 주제의 최신 글
태그가 겹치는 글
공통 태그가 많을수록 위에 보인다