Vite가 뭘까?

6/22/2023FE

오늘은 최근에 공부한 Vite에 대해 정리해보려고 합니다. Vite를 어떻게 커스텀할지를 다루기 보다는 Vite가 왜 나오게 되었고 Webpack 같은 번들러와 비교하여 무엇이 좋은지 등을 간단하게 풀어놓고자 합니다.

Vite 탄생 일화

Vite는 프랑스어로 "빠르다(Quick)"를 의미합니다. 그 이름답게 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드 도구입니다.

그럼 Vite는 어떻게 그렇게 빠른 걸까요?

  1. 우선 Vite는 Dependencies(패키지)와 Source Code(소스 코드)를 나누어 번들링 합니다. 실제 개발을 하면서 소스 코드는 자주 바뀌는 반면 패키지는 바뀌지 않기 때문에 분리하여 패키지를 사전 번들링 합니다. 그리고 그 사전 번들링에 Esbuild를 사용합니다. Go로 작성된 Esbuild는 Webpack, Parcel과 같은 기존의 번들러 대비 10~100배까지의 빠른 속도를 제공합니다. 또한 한 번 빌드한 결과는 캐싱을 해두기 때문에 다음 빌드에서는 더욱 빠른 속도를 자랑합니다.
  2. 또한 Vite는 Native ESM을 이용해 소스 코드를 제공합니다. 이는 브라우저가 번들러의 작업의 일부를 차지할 수 있도록 하므로, Vite는 브라우저가 요청하는 대로 소스 코드를 변환하고 제공하기만 하면 됩니다. 조건부 동적 import 이후의 코드는 현재 화면에서 실제로 사용되는 경우에만 처리됩니다. 즉, 자동으로 routes마다 code splitting이 일어나 Dynamic import가 됩니다.
  3. 그리고 Vite는 HMR을 번들러가 아닌 ESM을 사용하여 지원합니다. 어떤 모듈이 수정되면 Vite는 그저 수정된 모듈과 관련된 부분만 교체하고, 브라우저에서 해당 모듈을 요청하면 교체된 모듈을 전달합니다. 전 과정에서 완벽하게 ESM을 이용하기에, 앱 사이즈가 커져도 HMR을 포함한 갱신 시간에는 영향을 끼치지 않습니다.
  4. 마지막으로 Vite는 HTTP 헤더를 활용하여 전체 페이지의 로드 속도를 높입니다. 필요에 따라 소스 코드는 304 Not Modified로, 디펜던시는 Cache-Control: max-age=31536000,immutable을 이용해 캐시됩니다. 이렇게 함으로써 요청 횟수를 최소화하여 페이지 로딩을 빠르게 만들어 줍니다.

다만 Vite 문서에도 나와있다시피 Vite는 현재 프로덕션 번들링 과정에서는 Esbuild를 사용하지 않고 Rollup을 사용합니다. 물론 속도로는 esbuild가 더 빠르지만, 현재로서는 Rollup이 성능 대 유연성 트레이드오프에서 더 나은 선택이라고 여겼기에 그렇다고 합니다. 그러나 esbuild는 지난 몇 년 동안 많은 진전을 이루었고, 향후 프로덕션 빌드에서 esbuild를 사용할 가능성도 존재한다고 하니, 완전히 esbuild로 넘어갈 날이 올지 조금 기대가 되네요.


Vite는 두 가지 컨셉을 중심으로 하고 있습니다.

  • 개발 시 다양한 기능을 제공합니다.
  • 번들링 시 Rollup 기반의 다양한 빌드 커맨드를 사용할 수 있습니다. 이는 높은 수준으로 최적화된 정적(Static) 리소스들을 배포할 수 있게끔 하며, 미리 정의된 설정(Pre-configured)을 제공합니다.

Vite는 이와 같이 최적화된 설정을 제공하지만, Plugin API 또는 JavaScript API를 이용할 수 있습니다.

Vite 프로젝트 생성

그럼 이제 Vite가 빠른 것도 알았고, 간단하게 어떻게 돌아가는 시스템인지를 파악하면 좋을 것 같습니다.

먼저 Vite로 프로젝트를 생성해봅시다. 각각 사용하는 패키지 매니저에 맞게 생성하면 됩니다. 저는 react + typescript를 주로 사용하니 react-ts 템플릿을 사용하여 만들어보겠습니다.

# npm 6.x
npm create vite@latest app --template react-ts

# npm 7+
npm create vite@latest app -- --template react-ts

# yarn
yarn create vite app --template react-ts

# pnpm
pnpm create vite app --template react-ts

Vite가 지원하는 템플릿은 vanilla, vanilla-ts, vue, vue-ts, react, react-ts, react-swc, react-swc-ts, preact, preact-ts, lit, lit-ts, svelte, svelte-ts가 있으니 상황에 맞게 템플릿만 바꿔 프로젝트를 생성할 수 있습니다.


생성하면 다음과 같은 구조의 프로젝트가 생성됩니다.

vite 템플릿

react의 CRA와 비교했을 때 한 가지 눈에 띄는 점이 보이지 않나요? index.html이 public 폴더가 아닌 루트 폴더에 있습니다. Vite는 이게 의도적인 위치 선정이라고 합니다.
이는 추가적인 번들링 과정 없이 index.html이 앱의 진입점이 되게끔 하기 위함입니다. 그래서인지 index.html 파일 안을 보면 가장 메인이 되는 tsx 파일이 <script> 태그로 삽입되어 있습니다. (<script type="module" src="/src/main.tsx"></script>)


자. index.html과 main.tsx가 어떻게 실행되는지를 알았겠다, 이제는 package.json을 뜯어볼 차례입니다.

가장 먼저 scripts 부분을 보면 다음과 같이 적혀있습니다.

"scripts": {
  "dev": "vite",
  "build": "tsc && vite build",
  "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
  "preview": "vite preview"
},

근데 빌드 시에 tsc를 사용하네요? 왠지 예전 제 글이 생각나네요 😎


이외에 커맨드 라인에서 옵션으로 붙일 수 있는 것들이 여럿 존재합니다. 이는 공식 문서 - CLI 부분에 잘 정리가 되어있으니, 이 부분을 참고하여 용도에 맞게 커스텀하여 사용할 수 있을 것 같습니다.

TypeScript 지원?

당연하게도 Vite는 타입스크립트를 지원합니다. 하지만 타입에 대한 검사는 IDE 자체에서 하는 것과 build 과정에서만 진행합니다.
(위의 scripts에서 build 시 tsc를 먼저 수행하는 데, 이 부분이 타입 검사에 해당합니다.)
일반적으로 개발 시에는 .ts 파일에 대해서 트랜스파일링만 수행합니다.


왜 이렇게 하는 걸까요? 이는 Vite의 장점인 "빠른 속도"와 관련이 있습니다.
만약 개발 시에도 계속 타입 검사를 한다면 전체 모듈 그래프에 대한 탐색이 필요하므로 이 장점이 퇴색될 수 밖에 없겠죠.
때문에 Vite에서는 타입 검사는 빌드 시 수행하도록 분리했습니다. (당연히 이는 기본 설정이므로 타입 검사를 하도록 설정하는 방법도 있습니다.)


Vite에서는 타입스크립트 컴파일 시 esbuild를 이용합니다. 이로 인해 ts 코드를 js 코드로 변환이 tsc 대비 약 20~30배 정도 빠르게 이루어집니다.

그럼 Webpack과 Vite 중에서 뭘 선택할래?

저는 번들러를 선택하는 데 빌드 속도도 큰 비중을 차지하는 요소라고 생각합니다.


Webpack은 오래된 번들러로서 생태계가 크고 플러그인도 많아 확장하는 데 보다 유리하고, 트러블슈팅도 관련 예시가 많아 적당히 사용하기 좋았습니다.
다만 프로젝트가 커지면서 의존성이 늘어나고 플러그인도 하나둘 추가되면서 빌드 속도가 확연히 느려졌습니다. 이는 로컬에서 테스트할 때는 큰 불만을 못 느꼈지만, 실제로 aws나 vercel, netlify 같은 플랫폼을 사용해 배포를 하고 기다리는 시간과 그 시간에 비례하여 드는 비용에는 큰 불만을 느꼈습니다.


그래서 빠른 속도와 쉬운 설정이 자랑이라던 Vite에 관심이 생겼고, 먼저 조그만 토이 프로젝트에 Vite를 사용해보며 확실히 빌드 속도가 빠름을 많이 체감했습니다. (예전에 개발 모드에서 webpack을 사용할 때는 서버를 시작하고 적어도 2초 이상은 기다려야 화면이 떴는데, vite를 사용했더니 1초도 안돼서 화면이 뜨는 기현상을 볼 수 있었습니다. 정말 그때의 심경은...)


사실 Webpack vs Vite라는 비교 자체도 어떻게 보면 프로젝트의 주제나 목적에 따라 베스트는 다를 것이라고 생각합니다. 안정성과 확장성을 최우선으로 여긴다면 Webpack이 여전히 좋은 선택지일 것 같습니다. 그렇지만 Vite도 꾸준히 업데이트를 하며 많이 안정적으로 바뀌었고 지원하는 플러그인도 많이 늘어났으니, 만약 본인이 원하는 기능을 Vite에서 플러그인 등으로도 구현할 수 있도록 지원을 해주고 있다면 Vite가 아주 매력적인 선택지가 될 수 있겠죠.

Vite가 뭘까? : 🐢