왜 다들 CRA 대신 Vite를 쓸까?


React를 처음 배울 때 우리는 보통 npx create-react-app my-app 한 줄로 프로젝트를 시작합니다. 그런데 요즘 React 생태계의 분위기는 확실히 달라졌습니다. 다들 “이제 CRA 말고 Vite 쓰세요”라고 말하죠.

그러다 보면 자연스럽게 이런 질문이 떠오릅니다.

왜 요즘은 CRA가 아니라 Vite일까? 그리고 CRA, Vite, Webpack, Babel은 각각 무슨 역할을 할까?

사실 이 두 질문은 연결되어 있습니다. 왜 Vite로 넘어가는지를 제대로 이해하려면, 그 안에서 일하는 Webpack과 Babel부터 알아야 하기 때문입니다. 결론부터 말하면 이 넷은 같은 종류의 도구가 아니라, 서로 다른 층(layer)에서 일하는 도구들이에요.

그래서 이 글에서는 Webpack과 Babel이 어떤 일을 하는지 먼저 짚고, 그 위에서 CRA와 Vite가 어떻게 다른지 — 그리고 왜 CRA는 뒤로 밀려나게 되었는지를 정리해 보겠습니다.


1. 먼저, 이 도구들은 레벨이 다릅니다

Babel, Webpack, CRA, Vite — 비슷해 보이지만 사실 하는 일이 전혀 다릅니다. 이 넷은 각자 다른 레벨에서 일하는 도구들이에요.

도구한 줄 정의역할의 층위
Babel최신 JS/JSX를 구형 브라우저용 코드로 변환부품 (변환기)
Webpack흩어진 파일들을 하나로 묶음부품 (번들러)
CRAWebpack + Babel을 미리 세팅해 둔 시작 키트완성품 (도구 모음)
Vite번들링 방식을 새로 설계한 빌드 도구완성품 (도구 모음)

Babel과 Webpack은 엔진·부품이고, CRA와 Vite는 그 부품을 조립해 만든 완성된 자동차입니다. CRA와 Vite를 비교하려면, 그 안에 들어 있는 Babel과 Webpack부터 이해해야 하는 이유가 여기 있습니다.

핵심: Babel·Webpack은 부품, CRA·Vite는 그 부품으로 만든 완성품이다.


2. Babel — 최신 문법을 번역하는 번역기

우리가 React에서 매일 쓰는 이런 코드를 떠올려 봅시다.

const App = () => {
  return <h1>Hello!</h1>;
};

여기엔 두 가지 문제가 있습니다. 첫째, <h1> 같은 JSX 문법은 브라우저가 모릅니다. 둘째, 화살표 함수나 const 같은 최신 문법은 아주 오래된 브라우저에서 동작하지 않을 수 있습니다.

Babel은 이 코드를 브라우저가 알아들을 수 있는 평범한 JavaScript로 바꿔 줍니다.

// Babel이 변환한 결과 (실제 출력은 Babel 설정에 따라 조금씩 다릅니다)
var App = function App() {
  return React.createElement("h1", null, "Hello!");
};

React 개발자에게 Babel이 중요한 이유는 단순합니다. Babel이 없으면 JSX 자체가 동작하지 않기 때문입니다. 우리가 JSX를 자유롭게 쓸 수 있는 건 뒤에서 Babel이 조용히 번역해 주고 있기 때문이에요.

핵심: Babel은 브라우저가 모르는 문법을 아는 문법으로 번역해 주는 번역기다.


3. Webpack — 흩어진 파일을 하나로 묶는 번들러

React 프로젝트는 컴포넌트, CSS, 이미지 등 수십~수백 개의 파일로 쪼개져 있습니다. 그런데 브라우저가 이 파일을 하나하나 따로 요청하면 느리고 비효율적입니다.

Webpack은 import / export로 연결된 파일들을 따라가며 의존성 그래프를 만들고, 그것을 몇 개의 파일(번들)로 합쳐 줍니다.

App.jsx    ─┐
Button.jsx ─┼─>  [ Webpack ]  ─>  bundle.js  (하나로 합쳐진 결과)
style.css  ─┘

여기서 중요한 점은 Webpack과 Babel은 협업 관계라는 것입니다. Webpack이 파일을 묶다가 JSX 파일을 만나면, 그 파일의 번역은 Babel에게 넘깁니다. Webpack은 묶는 일을, Babel은 번역하는 일을 맡는 분업 구조입니다.

핵심: Webpack은 흩어진 파일을 번들로 묶고, 그 과정에서 Babel에게 번역을 맡긴다.


4. CRA — Webpack과 Babel을 미리 조립해 둔 시작 키트

여기까지 읽으면 이런 생각이 들 겁니다. 그럼 React 프로젝트를 시작할 때마다 Webpack과 Babel을 매번 직접 설정해야 할까요?

예전에는 그래야 했습니다. 그리고 그 설정은 React를 막 시작한 사람에게 꽤 높은 진입 장벽이었죠 ૮(•᷄‎ࡇ•᷅ )ა CRA(Create React App)는 바로 그 번거로움을 없애주려고 등장했습니다.

CRA는 Webpack, Babel, 개발 서버, 테스트 환경 같은 설정을 미리 다 조립해서 명령어 한 줄로 끝내 줍니다.

npx create-react-app my-app

장점은 명확합니다. 설정을 몰라도 바로 React 개발을 시작할 수 있죠. 대신 그 설정들이 react-scripts라는 패키지 안에 숨겨져 있어서, 세부 설정을 바꾸려면 까다롭다는 단점이 있습니다.

중요: CRA는 2025년 초 React 공식 팀에 의해 권장 중단되었습니다. 공식 문서도 이제 새 프로젝트에는 Vite나 프레임워크를 권하니, 지금 React를 시작한다면 CRA보다 Vite를 보게 될 가능성이 큽니다.

핵심: CRA는 Webpack·Babel 설정을 대신 해 주는 시작 키트지만, 지금은 더 이상 권장되지 않는다.


5. Vite — 번들링 방식 자체를 다시 생각한 빌드 도구

CRA가 느리다는 불만은 오래전부터 있었습니다. 프로젝트가 커질수록 개발 서버를 켜는 데 한참 걸리고, 코드를 한 줄 고쳐도 화면 반영이 느려졌죠.

이유는 Webpack의 동작 방식에 있습니다. Webpack은 개발 서버를 켤 때 모든 파일을 미리 번들로 묶습니다. 파일이 많을수록 이 작업이 오래 걸립니다.

Vite는 발상을 뒤집었습니다. 요즘 브라우저는 import 문법(ES Modules)을 직접 이해할 수 있다는 점을 활용해, 개발 중에는 프로젝트 코드를 미리 묶지 않고 브라우저가 요청하는 파일만 그때그때 변환해서 보내 줍니다.

npm create vite@latest my-app -- --template react

그래서 프로젝트가 아무리 커도 개발 서버가 거의 즉시 켜집니다. (배포용 빌드에서는 Vite도 Rollup으로 묶지만, 개발 중에는 묶지 않는다는 점이 핵심입니다.)

참고: Rollup은 Webpack과 같은 번들러(파일을 묶는 도구)입니다. 결과물이 깔끔해 라이브러리 제작에 강점이 있고, Vite는 배포용 빌드에 이 Rollup을 사용합니다.

속도 차이는 처음 켤 때만의 이야기가 아닙니다. 개발 중 코드를 한 줄 고쳤을 때 그 변경을 화면에 반영하는 기능을 HMR(Hot Module Replacement) 이라고 하는데, 페이지 전체를 새로고침하지 않고 바뀐 부분만 즉시 갈아끼웁니다. Vite는 개발 서버가 파일 하나만 다시 변환하면 되기 때문에 이 HMR도 CRA보다 훨씬 빠릅니다. 우리가 “Vite는 빠르다”고 느끼는 건 결국 개발 서버 시작 속도 + HMR 반영 속도, 이 둘의 체감 차이인 셈입니다.

개발 서버와 HMR이 내부에서 정확히 어떻게 동작하는지는 이야기가 꽤 길어서, 추후에 Vite를 더 깊이 다루는 글에서 따로 정리해 보겠습니다.

핵심: Vite는 자주 바뀌는 프로젝트 코드는 미리 묶지 않고, 잘 바뀌지 않는 의존성만 한 번 묶어두는 방식으로 속도 문제를 해결했다.

참고: 의존성이란 react, lodash처럼 내가 직접 만들지 않고 외부에서 설치해 가져다 쓰는 라이브러리를 말합니다. package.json에 적히고 node_modules에 설치됩니다.


6. CRA vs Vite — 한눈에 비교

이제 진짜 비교 대상인 CRA와 Vite를 정리해 봅시다.

항목CRAVite
내부 번들러Webpack개발: 브라우저 ESM / 배포: Rollup
변환 도구Babelesbuild (Go 기반, 매우 빠름)
개발 서버 시작 속도프로젝트가 크면 느림거의 즉시
코드 수정 반영(HMR)상대적으로 느림빠름
설정 변경어려움 (eject 필요)vite.config.js로 간단
현재 상태공식 권장 중단사실상 표준으로 자리잡음

표에서 보듯 CRA와 Vite의 차이는 결국 내부에서 어떤 부품을 어떤 방식으로 쓰느냐의 차이입니다. CRA는 Webpack+Babel을 전통적인 방식으로, Vite는 esbuild와 브라우저 ESM을 활용한 새로운 방식으로 조립했을 뿐이에요.

핵심: CRA와 Vite의 차이는 안에 든 부품과 조립 방식의 차이다.

참고: esbuild는 Go로 만든 아주 빠른 변환·번들링 도구로, Babel·Webpack이 하던 일을 훨씬 빠르게 처리합니다. 브라우저 ESM은 브라우저가 import·export 문법을 직접 이해하는 기능으로, 덕분에 Vite는 개발 중 파일을 미리 다 묶지 않아도 됩니다.


7. 그래서 React 개발자가 알아야 할 것

여기까지의 내용을 다음 네 가지 질문으로 정리했습니다.

내가 쓴 JSX는 왜 그냥 동작할까? → Babel(또는 esbuild)이 번역해 줬으니까.

컴포넌트를 이렇게 많이 나눴는데 브라우저는 어떻게 한 번에 읽을까? → Webpack(또는 Rollup) 같은 번들러가 묶어 줬으니까.

그럼 이걸 매번 직접 설정해야 할까? → 아니다. CRA와 Vite가 대신 해 준다.

새 프로젝트는 뭘로 시작할까? → 이제는 CRA가 아니라 Vite.

이 흐름을 알아두면 에러 메시지에 babel·webpack·vite 같은 단어가 떠도 당황하지 않습니다. 번역 단계의 문제인지 묶는 단계의 문제인지, 어디부터 봐야 할지 방향이 잡히기 때문입니다.

핵심: 도구의 역할을 구분할 줄 알면, 에러가 나도 어디를 봐야 할지 알 수 있다.


한 줄 요약

Babel은 번역기, Webpack은 묶는 도구(번들러)이고, CRA와 Vite는 이 둘을 대신 세팅해 주는 시작 키트다. CRA는 Webpack을 전통 방식으로, Vite는 더 빠른 방식으로 조립했다. 그리고 앞으로 새 프로젝트의 답은 사실상 Vite 하나다.

hskang 아바타