Vite는 어떻게 빌드되는가?

sham·2025년 1월 5일

개요

처음 개발을 시작할 때, 개발 강의를 찾아보면 거의 대부분 CRA를 사용해서 프로젝트 환경을 세팅하는 것이 대부분이었다. 그러나 오늘날에는 CRA 대신 Vite를 사용하는 것을 어렵지 않게 찾아볼 수 있다. Vite는 대체 무엇일까?

Vite 공식 문서 왈

공식 문서에서는 이렇게 이야기하는데, 좀 더 자세히 알아보도록 하자.

Vite를 사용해야 하는 이유

탄생 배경

  • 기존에는 브라우저가 ES Modules(ESM)을 지원하기 전에는 모든 파일을 번들링해야 했음.
  • 번들링 도구(Webpack, Rollup, Parcel 등)는 파일 크롤링과 처리에 시간이 많이 소요됨.
  • 대규모 프로젝트에서는 파일 갱신과 HMR(Hot Module Replacement)이 느려져 개발 속도가 저하됨.

Vite 작동 방식

  • 소스 코드를 두 가지 카테고리로 구분
    • Dependencies: 변하지 않는 일반 JavaScript 모듈은 Esbuild로 사전 번들링. (기존 도구보다 10~100배 빠름)
    • Source Code: Native ESM를 이용해 브라우저가 요청하는 모듈만 변환 및 제공.
  • HTTP 요청 기반으로 필요한 모듈만 로드.
  • HMR(Hot Module Replacement)
    • 수정된 모듈만 교체하여 빠르게 반영.
    • 브라우저와 네이티브 ESM을 통해 빠른 갱신 속도 제공.
  • 캐싱 활용
    • 디펜던시는 장기 캐싱(immutable) 설정.
    • 변경되지 않은 소스는 304 Not Modified로 요청 최소화.

프로덕션 빌드

  • 번들링 필요성
    • ESM을 직접 사용하는 것은 네트워크 요청 증가로 인해 비효율적.
    • 프로덕션에서는 Rollup을 통해 Tree Shaking, 코드 스플리팅 등으로 최적화된 번들 생성.
  • Rollup 채택
    • 플러그인 생태계와 유연성 때문에 Rollup을 사용.
    • 미래에는 Rust 기반 Rolldown으로 성능을 더 개선할 계획.

용어 정리

ESM (ES Modules)

  • JavaScript의 공식적인 모듈 시스템.
  • exportimport 키워드를 사용해 모듈 형태로 파일 간의 코드를 사용할 수 있게 한다.
  • ES6(ECMAScript 2015)에서 도입되어 JavaScript 표준으로 인정.

Native ESM

  • 브라우저나 Node.js가 ESM을 네이티브(기본적으로) 지원하는 환경을 의미한다.
    • 별도의 번들링 도구 없이 ESM을 직접 실행할 수 있다는 뜻.
  • 브라우저의 경우 <script type="module"> 태그를 통해 ESM을 사용할 수 있다.
<script type="module">
  import { add } from './math.js';
  console.log(add(1, 2));
</script>
  • Node.js의 경우 .mjs 확장자를 사용하거나 package.json"type": "module”을 설정하는 것으로 사용할 수 있다.
  • 단, 배포(production) 환경에서는 여전히 번들링(파일 통합)이 필요하다.

Bundling (번들링)

  • 웹사이트에서 JS 파일을 요청한다고 생각해보자. 여러 개의 파일을 하나하나 요청하는 것보다 하나의 파일만을 요청하는 것이 훨씬 비용적으로 유리할 것이다.
  • 번들링은 여러 개의 JavaScript 파일(모듈)을 하나의 파일로 병합하는 과정으로, 브라우저가 JS 파일을 효율적으로 로드할 수 있도록 최적화된다.
  • 몇몇 번들러의 경우 트랜스파일러 역할도 수행한다. Vite가 대표적인 예
  • Webpack, Rollup, Parcel, Vite 등이 존재한다.

번들링 과정을 이해해보자

Transpile (트랜스파일)

  • 코드의 언어 또는 문법을 다른 형태로 변환하는 과정.
  • 모던 웹 어플리케이션은 HTML, CSS, JavaScript만을 사용해서 개발하기엔 너무나 복잡해져 버렸기에, 이를 보완하고자 다양한 슈퍼셋(Superset, 기존 집합을 포함하는 더 큰 집합)이 등장함.
    • 이들을 기존 생태계에서 사용하기 위해 트랜스파일이 등장.
    • 대표적인 트랜스파일 예시
      • TypeScript → JavaScript
      • SASS → CSS
      • ES2021 JavaScript → ES2014 JavaScript
      • JSX → JavaScript
  • 코드의 문법 수준을 변환하여 브라우저 호환성을 높이거나 최신 기능을 사용할 수 있게 함이 목적.
  • Babel, TypeScript Compiler(TSC), SWC 등이 대표적인 트랜스파일러.
  • 언어 및 문법 변환에 초점을 맞추며, 번들링과 달리 파일 병합이나 최적화 작업은 하지 않음.
  • Polyfill과는 런타임 이전에 변환 작업을 수행

Polyfill (폴리필)

  • 특정 기능이 지원되지 않는 환경(주로 구형 브라우저)에서 해당 기능을 대체 구현하거나 에뮬레이션하는 코드.
  • Promisefetch API와 같이 최신 JavaScript 기능을 지원하지 않는 브라우저에서 이 기능들을 사용할 수 있게 해준다.
    • 브라우저가 새로운 기능을 호출할 때 폴리필이 동작하여 대체 기능을 제공
    • 코드 변경 없이 구형 환경에서도 최신 기능을 사용할 수 있도록 보완하며 브라우저 호환성 보장
  • 트랜스파일링과 달리, 폴리필은 런타임에 동작
  • 번들링과는 관련이 없으며, 주로 브라우저의 API나 메서드 부족을 보완하는 역할

번들링, 트랜스파일, 폴리필

키워드목적수행 시점주요 역할대표 도구
Bundling여러 파일 병합 및 최적화빌드(개발/배포 전)파일 병합, 트리 셰이킹, 압축Webpack, Vite, Parcel
Transpile언어 또는 문법 변환빌드(개발/배포 전)코드 변환 (ES6→ES5 등)Babel, TSC, SWC
Polyfill브라우저에서 새로운 기능 대체 구현런타임(실행 중)환경이 지원하지 않는 기능 보완core-js, polyfill.io

Esbuild

  • JavaScript와 TypeScript 코드를 초고속으로 번들링하고 트랜스파일러하는 도구.
  • Go 언어로 작성되어 기존 번들러 대비 10~100배 빠른 성능을 제공.
  • CPU 멀티코어와 효율적인 메모리 사용으로 매우 빠르게 작동하며, ESM을 지원하다.
  • 별도의 플러그인 없이도 TypeScript와 React JSX를 처리할 수 있다.

Rollup

  • JavaScript 번들링 도구로, 주로 라이브러리와 같은 재사용 가능한 코드를 번들링하는 데 최적화.
  • ES Modules(ESM)을 중심으로 설계되었으며, 트리 셰이킹(Tree Shaking)을 통해 사용되지 않는 코드를 제거.

본문

vite 빌드 과정

Vite는 개발 서버프로덕션 빌드에서 서로 다른 전략을 사용한다.

  • 개발 서버
    • 번들링 없이 Native ESM을 사용해 브라우저 요청에 따라 파일을 실시간으로 변환하고 제공한다.
    • 의존성 파일은 Esbuild로 사전 번들링하여 캐싱된 상태로 제공한다.
    • 파일 변경 시 HMR을 통해 필요한 파일만 다시 로드한다.
  • 배포 서버
    • Vite는 Rollup을 사용하여 최적화된 번들링을 수행한다.
      • 트리 셰이킹(Tree Shaking): 사용되지 않는 코드를 제거.
      • 코드 스플리팅(Code Splitting): 큰 파일을 작은 청크로 나누어 로드 성능 최적화.
      • CSS 및 이미지 최적화: CSS를 하나로 합치고, 이미지 파일을 압축.
    • 번들된 결과물을 최적화하여 dist 디렉토리에 생성한다.

run dev - vite

1. Vite 설정 파일 로드

  • Vite는 프로젝트 루트에 있는 vite.config.js 또는 vite.config.ts 파일을 읽는다.
    • 이 파일에는 개발 서버 설정, 플러그인, 빌드 옵션 등이 정의되어 있다.
    • 설정 파일이 없으면 기본값으로 동작한다.

2. 의존성 분석 및 사전 번들링

  • Vite는 프로젝트의 node_modules에서 외부 의존성을 분석한다.
    • 예: React, Vue, Lodash 등.
  • 의존성 파일은 대부분 변화가 없기 때문에 Esbuild를 사용해 사전 번들링을 수행.
    • Esbuild는 매우 빠르게 번들링을 처리하고, 결과를 캐싱해 개발 서버를 시작할 때 재사용.

3. 개발 서버 실행

  • 개발 서버가 실행되고 브라우저가 연결할 수 있도록 로컬 서버가 열린다.
    • 기본적으로 http://localhost:5173에서 실행.
    • vite.config.js에서 server.port를 설정하면 포트를 변경할 수 있다.

4. Native ESM 방식으로 파일 제공

  • 브라우저가 요청을 보내면, Vite는 Native ESM 방식으로 동작.
    • 브라우저는 ESM을 기반으로 동적으로 필요한 모듈을 요청.
    • 예: import { useState } from 'react';와 같은 코드는 React 모듈을 브라우저가 직접 가져온다.
  • 브라우저 요청 처리 과정
    • 브라우저가 JavaScript 파일(예: main.tsx)을 요청.
    • Vite는 해당 파일을 읽고, 필요하다면 컴파일(JSX → JS, TS → JS 등)을 진행.
    • 결과를 브라우저에 반환.

5. HMR(Hot Module Replacement) 활성화

  • Vite는 HMR(Hot Module Replacement)을 통해 코드 변경 사항을 실시간으로 반영.
    • 소스 파일이 변경되면, 변경된 모듈만 브라우저에 다시 전송.
    • 전체 페이지를 새로고침하지 않고도 업데이트 내용을 즉시 확인 가능.
  • HMR 작동 방식
    • 코드가 수정되면 Vite는 해당 파일과 의존성을 감지.
    • 브라우저에 이 파일이 변경됨을 알리고 변경된 모듈만 갱신.
    • UI가 즉시 업데이트.

6. Static Assets 처리

  • CSS, 이미지, JSON 등 정적 파일 요청도 처리.
    • CSS는 <style> 태그로 주입하거나 브라우저에 직접 전달.
    • 이미지와 같은 파일은 브라우저에서 로드 가능하도록 URL로 변환하여 제공.

7. 브라우저 연결 및 초기 로드

  • 브라우저가 초기 페이지를 요청하면, Vite는 엔트리 파일(예: index.html)을 전달.
    • index.html 파일 내 스크립트 태그에서 type="module"을 통해 JavaScript 모듈을 로드.
    • 브라우저가 필요에 따라 모듈을 동적으로 요청.

8. 브라우저 캐싱 활용

  • Vite는 HTTP 캐싱을 활용해 자주 변경되지 않는 파일(의존성 파일 등)을 효율적으로 관리.
    • 예: Cache-Control: max-age=31536000, immutable 헤더를 설정해 브라우저가 의존성 파일을 캐싱.
    • 변경된 소스 코드만 새로 전송.

run build - tsc && vite build

tsc - typescript 컴파일러

  • TypeScript 파일을 JavaScript 파일로 변환하는 작업을 수행.
  • dist/ 폴더 안에 ts 파일이 js 파일로 변환.
    • tsconfig.jsonoutDir 설정에 따라 출력 경로 수정 가능
  • tsconfig.json에서 설정한 target 옵션에 따라 ES5, ES6 등 특정 JavaScript 버전으로 변환.

vite build - 배포용 정적 파일

  • Vite의 프로덕션 빌드를 실행하며, 최적화된 정적 파일을 생성

1. 번들링된 JavaScript 파일

  • 프로젝트의 여러 JavaScript 파일을 하나 또는 여러 개의 번들 파일로 결합.
    • 예: dist/assets/index-abc123.js.
  • 결과물은 최적화된 상태로, 사용되지 않는 코드(Dead Code)는 제거되고, 필요한 부분만 남는다. (트리 셰이킹)

2. CSS 파일 병합 및 최적화

  • 모든 CSS 파일이 하나로 병합되고, 중복된 스타일을 제거.
    • 예: dist/assets/style-xyz456.css.

3. 코드 압축

  • JavaScript와 CSS 코드가 축소(minified).
    • 공백, 주석, 불필요한 코드가 제거되어 파일 크기가 작아진다.
    • 결과 파일명: index-abc123.min.js.

4. 정적 파일 복사

  • public 폴더에 있는 정적 파일(이미지, 폰트, 아이콘 등)이 그대로 복사되어 빌드 디렉토리에 포함.
    • 예: public/logo.pngdist/logo.png.

5. HTML 파일 최적화

  • index.html 파일이 번들 파일을 참조하도록 수정되고, 최적화.
    • 예: <script type="module" src="/src/main.ts"><script src="/assets/index-abc123.js">.

6. 결과물 저장

  • 모든 빌드 결과물은 dist/ 폴더에 저장

레퍼런스

JavaScript 번들러의 이해 — (3) 번들러 개론

JavaScript 번들러의 이해 — (4) Webpack 및 다른 번들러들

profile
씨앗 개발자

0개의 댓글