본문으로 건너뛰기
Previous
Next
Vite 완벽 가이드: 차세대 프론트엔드 빌드 도구

Vite 완벽 가이드: 차세대 프론트엔드 빌드 도구

Vite 완벽 가이드: 차세대 프론트엔드 빌드 도구

이 글의 핵심

Vite는 ESBuild 기반의 초고속 개발 서버와 Rollup 기반의 최적화된 프로덕션 빌드를 제공하는 차세대 빌드 도구입니다. 네이티브 ESM을 활용하여 번들링 없이 즉시 서버를 시작하고, HMR로 빠른 피드백 루프를 제공합니다. Webpack 대비 10-100배 빠른 콜드 스타트와 거의 즉각적인 HMR 업데이트를 경험할 수 있습니다.

Webpack에서 Vite로 갈아탄 건, 솔직히 “설정 파일 줄 수”만 보려고 한 게 아니에요. 레거시 SPA에서 webpack-dev-server 켤 때마다 커피 한 잔 돌릴 수 있을 만큼 기다리던 콜드 스타트, 저장 한 번에 HMR이 몇 초씩 끌리던 그짓거리, 그냥 질려버린 거죠. Vite 쪽에선 개발일 때는 브라우저 네이티브 ESM에 맡기고, 요청이 들어온 모듈만 esbuild로 손봐서 보내요. 빌드 속도가 다릅니다 — 이건 마케팅 문구가 아니라, 체감이 주식 차트 갈라지는 수준이에요. 프로덕션은 Rollup이 번들을 짜고, Tree-shaking·코드 스플릿이 거기서 나옵니다. Vue·Svelte·Nuxt·SvelteKit 쪽이 Vite를 기본으로 쓰는 이유를 “철학”으로만 읽지 말고, 팀이 매일 npm run dev를 몇 번 치는지로 환산해 보면 답이 나옵니다.

Vite(프랑스어로 ‘빠른’) 자체는 Evan You가 밀고 나온 프로젝트고, “개발 = 번들 없이/거의 없이, 빌드 = Rollup”이라는 쪽지 하나로 머릿속이 정리돼요. Webpack 쪽 콜드 스타트는 프로젝트가 커질수록 3060초대로 가는 경우도 흔하고, HMR도 파일 많아지면 310초 훅 가는 느낌 나죠. Vite는 개발 서버 뜨는 데 12초 잡는 편이 일반적이고, HMR은 보통 50200ms 구간에 들어가요. 숫자만 나열하면 ‘과장’ 같지만, 같은 레포에서 바꿔 켜 보면 “아, 이게 달랐구나”가 바로 감이 와요. Webpack이 나쁜 도구냐? 아니에요. 다만 “개발 모드에 전부 번들부터 돌리는” 모델이랑, “그걸 쪼개서 아껴 쓰는” 모델이 하루 8시간 쌓이면 누적이 장난이 아닙니다.

새로 시작할 땐 CLI가 제일 덜 피곤해요. 대화형으로 박고 싶으면 npm create vite@latest 한 번, CI나 스크립트엔 템플릿을 박아 넣고요. React·Vue·Svelte·Solid·Preact 등 골라 쓰면 됩니다.

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

프로젝트 만들고 npm installnpm run dev — 여기서 이미 “아까 그 기다림”이 사라지는 케이스가 많아요. 수동으로 붙이고 싶으면 npm install -D vite 하고, React면 @vitejs/plugin-react를 같이 설치하는 식입니다. 구조는 Webpack이랑 느낌이 달라요. index.html이 루트에 있고(그냥 public 안에 박는 게 아님), 엔트리는 그 HTML이 잡는다 — 이 점은 마이그레이션할 때 익숙해져야 합니다. 대충 my-vite-app/index.html + src/main.* + vite.config.js + public/에 정적 자산, 빌드 결과는 dist/.

Webpack에서 Vite로 넘어올 때 제일 많이 터지는 건 환경 변수랑 index.html 위치예요. Webpack 쪽 process.env.REACT_APP_* 류는 Vite에선 import.meta.env.VITE_*로 갑니다. .env도 그에 맞춰 VITE_ 접두사 쓰는 게 기본이고, import.meta.env.DEV / PROD / MODE는 그냥 기본으로 써도 됩니다. process를 브라우저 코드에 기대는 패턴만 잘 뜯어내면 절반은 끝이에요. CJS require 섞인 코드도 import로 정리하거나, 꼭 CommonJS 끼인 패키지는 optimizeDeps에 끼워 넣는 쪽을 보면 됩니다. Webpack 쓰던 팀이 싫어하던 webpack.config.js 수백 줄 딜레마는, Vite 쪽 vite.config가 짧게 잡힌다는 말이 괜히 나온 게 아닙니다 — 물론 앱이 커지면 Rollup·SSR·별칭·프록시 때문에 길어지긴 합니다. “짧다”는 건 출발선이 덜 꼬인다는 뜻이에요.

기본 vite.config는 이런 뼈대에서 시작하면 됩니다. React 기준이에요. 포트·open·host, 빌드 쪽 outDir·소스맵, 벤더 청크 쪼개기, @ 별칭, VITE_ envPrefix까지 한 번에 박아 둔 예시입니다.

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: { port: 3000, open: true, host: true },
  build: {
    outDir: 'dist',
    sourcemap: true,
    minify: 'esbuild',
    rollupOptions: {
      output: {
        manualChunks: { vendor: ['react', 'react-dom'] },
      },
    },
  },
  resolve: {
    alias: { '@': '/src', '@components': '/src/components' },
  },
  envPrefix: 'VITE_',
});

TypeScript 쓰면 path__dirname 잡는 버전 흔하고, API 프록시는 server.proxy에 박습니다. '/api' → http://localhost:5000 같은 식—로컬에서 CORS 때려막기에 좋죠.

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: { alias: { '@': path.resolve(__dirname, './src') } },
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true,
        rewrite: (p) => p.replace(/^\/api/, ''),
      },
    },
  },
});

이미지·CSS는 익숙한 방식이에요. import logo from './logo.svg', public은 루트 경로로, ?url / ?raw / ?worker 쿼리는 그대로 쓰면 Vite가 알아서 묶어줍니다. React면 @vitejs/plugin-react에 Babel 꼴라 넣는 것도 있고, PWA 쓰려면 vite-plugin-pwa 흔해요. SVGR, visualizer, compression 같은 것도 “Webpack 때랑 비슷한 니즈”는 그대로 갑니다. 다만 “플러그인 이름만 바꾸면 된다” 수준은 아니고, Rollup·Vite 생태 기준으로 다시 읽는 시간은 필요해요.

프로덕션 최적화는 build.rollupOptions에서 manualChunks로 React·MUI·lodash 같은 덩어리 쪼개고, lazy+Suspense로 라우트 단위로 끊는 패턴 Webpack이랑 같습니다. 느리면 rollup-plugin-visualizer로 번들 뜯어 보는 게 먼저고, optimizeDeps.include / force: true로 사전 번들 캐시 꼬인 것도 훑어봅니다. 개발이 빠르다고 프로덕션도 자동으로 가벼운 건 아님—이건 Vite를 까는 말이 아니라, 프론트엔드 공통이에요. 다만 “개발에서 이미 느리면” 프로덕션 튜닝 전에 짜증이 먼저 쌓이니까, Vite 쪽이 정신 건강엔 이득인 경우가 많다 — 제 주관입니다.

Node 코어 fs 같은 걸 브라우저 번들에 끌고 오려다 깨지는 것, CJS-only 패키지, ssr 경계, 별칭·tsconfig 불일치로 Module not found — 트러블슈팅 토픽은 Webpack이랑 다르다기보다 “다른 툴로 옮겼다”는 착시에서 온 경우가 많아요. Vite 쓴다고 마법은 없고, 도구를 바꾸면 느리던 게 빨라질 뿐, 설계를 망쳐 둔 건 그대로인 건 잊지 말자는 쪽이 맞는 것 같아요.


정리하자면: Webpack에서 Vite로 이주하는 스토리는 “설정 몇 줄 줄었다”로 끝나는 경우가 별로 없고, index.html·환경 변수·import 모델 다시 익히는 댓가가 있어요. 그 댓가를 지불해도, 빌드(정확히는 개발 서버) 속도가 다릅니다—여기에 공감 못 하면 굳이 갈아탈 이유는 없고, 공감하면 돌이키기 어렵다. 프로덕션은 Rollup이 받치니 “개발만 번들”이라는 Vite 쪽의 방정식이, 생산 앱이랑도 잘 맞는 편이에요. 끝.