Vite에 대해서

2023. 4. 18. 14:10코딩

Vite

Vue를 만들었던 Evan You가 만든 새로운 프론트엔드 빌드 도구입니다.

기존 문제

ESM(ECMAScript Modules)이 등장하기 전에는 자바스크립트 언어에서의 모듈화 방식은 없었습니다. 그래서 모듈화를 하기 위해서는 Webpack 등의 도구를 활용하여 번들링 작업을 진행 했었습니다.

하지만 애플리케이션이 점점 발전함에 따라 처리해야되는 JS 모듈의 개수도 증가합니다. 이러한 상황에서 번들링 도구는 성능 병목 현상이 발생됐고, 서버 가동 시 처음부터 소스 크롤링 및 빌드 작업을 하기 때문에 오랜 시간을 기다려야 했습니다.

하지만 개발 서버 구동 시 번들러 기반 도구는 모든 소스 코드에 대해서 크롤링 및 빌드 작업을 마쳐야만 실제 페이지를 제공할 수 있었습니다.

이어서

Vite는 이 문제를 해결하기 위해서 dependencies & source code 두 가지로 나누어 개발 서버를 시작하게 하였습니다.

  • Dependencies : 개발 시 내용이 바뀌지 않을 Plain JS source code를 의미합니다.
  • Source Code : JSX, CSS or Vue/Svelte Component 같은 컴파일링이 필요하고, 수정이 잦을 Non-plain JS source code를 의미합니다.

Vite 는 사전 번들링 기능으로 Esbuild를 사용하고 있습니다. Esbuild는 Webpack, Parcel같은 기존 번들러 대비 10~100배 빠른 번들링 속도를 보여줍니다.

  • Esbuild 는 go로 작성된 번들러로, Typescript type checking 이나 Front 언어, HMR을 포함한 번들링 기능들은 일체 없음
  • 첫 실행 시, 사이트 불러오기 전에 프로젝트의 디펜던시를 사전 번들링 함
  • Three js 라이브러리 10번 번들링 속도

또 다른 문제와 Vite에서의 해결 방법

기존 번들링 방식으로 개발 진행 시, 소스 코드를 수정하거나 새 파일을 추가 하였을 때 번들링 과정을 다시 거쳐야 했었습니다. 따라서 어플리케이션이 커질수록 소스 코드 갱신 시간 또한 선형적으로 증가할 수 밖에 없었습니다.

일부 번들러는 바뀐 소스들에 대해서만 번들링하게 지원하긴 했으나, 어차피 처음 실행 시에는 모든 파일들에 대해 번들링을 하고, 다시 웹에서 불러오기 때문에 근본적인 문제는 해결되지 않았던 것 입니다.

이런 이슈를 우회하기 위해서 HMR 이라는 대안이 나왔는데, 이 방식 또한 어플리케이션이 커지면 갱신에 요구되는 시간이 증가 하였습니다.

  • HMR이란 Hot Module Replacement의 약자로 앱을 종료하지 않고 갱신된 파일만 교체하는 방식입니다.

이상하게도 시간이 증가하는 단점에도 Vite는 HMR을 지원하는데, 그 이유는 기존 번들러 방식이 아닌 ESM을 이용해서 지원합니다.

Vite는 Native ESM을 이용해 소스 코드를 제공합니다. 이 말은 즉 브라우저가 곧 번들러라는 이야기 입니다.

  • 기존 빌드 방식
  • Vite 빌드 방식

쉽게 설명 하면, Vite는 수정된 모듈과 관련된 부분만 교체하고, 브라우저에서 해당 모듈을 요청하면 교체된 모듈을 전달만 하는 것 입니다.

또 속도를 높이기 위해서 HTTP 헤더를 이용하였습니다.

  • 소스 코드 : 304 Not Modified
  • 디펜던시 : Cache-Control: max-age=31536000, immutable
    위 의 내용을 이용해서 캐쉬되도록 함으로써, 요청을 덜 하게 만드는 것 입니다.

여기서 ESM은 아래에서 설명 드리겠습니다.

ESM ( ECMAScript Modules )

import, export를 별도의 도구 없이 브라우저에서 바로 사용 가능한 모듈 방식을 의미합니다. 아래 같은 코드를 번들러 없이 실행하면 에러가 발생합니다.

// company.js
import { JeonJai } from "openobject.js";
console.log(JeonJai("hi, jai"));
<script src="company.js"></script>

하지만 시대가 바뀜으로 다음과 같은 속성을 추가하면 import 와 export를 에러 없이 적용이 가능합니다.

<script type="module" src="company.js"></script>

Vite가 지원하는 기능

  • HMR 지원 : 페이지 리로드 or 상태 초기화 안하고 업데이트

  • TypeScript 지원 : Esbuild로 트랜스파일만 수행함으로 속도 더 빠름

    • 그럼 타입 체킹은 어떻게 하나 ? : IDE랑 빌드 프로세스에서 수행된다고 가정함
    • 왜 타입 체킹을 안 함? : 트랜스파일링은 파일 단위이지만, 타입 체킹은 전체 모듈에 대해서 탐색을 해야 돼서, 타입 체킹을 하게 되면 속도 이점이 사라짐
  • SSR 지원 : 서버 사이드 렌더링 지원

    • import.meta.env.SSR 같은 옵션을 사용해서 ssr에서만 작동하는 코드 등을 분기처리 작성 가능합니다.
  • Vue 지원

  • JSX 지원

  • CSS 지원

    • .module.css로 끝나는 파일들은 일반적인 JS 모듈처럼 사용 가능

      import styles from "example.module.css";
      document.getElementById("name-card").className = styles.card;
  • 정적 에셋

    • URL 쿼리를 이용해 어떻게 가져올 것인지 명시 가능 (이 부분 신기, 한번도 안 써봄)

      // Base64 포맷으로 웹 워커 가져오기
      import InlineWorker from "/worker.js?worker&inline";
  • JSON 지원

    • JSON 파일 바로 Import 가능, 필드 지정 가능

      // 객체로 가져오기
      import json from "example.json";
      // 필드 지정 가져오기 (트리 쉐이킹)
      import { field } from "example.json";
    • 트리쉐이킹 : 사용하지 않는 코드 제거

  • Glob Import : Vite 는 import.meta.glob으로 여러 모듈을 한 번에 가져옵니다.

    • Glob 패턴을 활용함

      // 이렇게 사용함
      const modules = import.meta.glob("/dir/*.js");
      // Vite로 변환하면
      const modules = {
      "/dir/hi.js": () => import("/dir/hi.js"),
      "/dir/bye.js": () => import("/dir/bye.js"),
      };
  • 백엔드 프레임워크랑 함께 사용

    • Vite config 파일에서 작업 후에 백엔드와 연결 가능 (Laravel 같은거)

관심있게 살펴본 지원 기능은 위와 같으며 자세한 내용은 공식 문서를 통해 확인해주시면 감사하겠습니다.

특이점

index.html 위치

Vite로 만든 프로젝트를 보면 index.html이 public 디렉터리에 있는게 아닌 프로젝트 루트에 있는데, 이유는 추가적인 번들링 과정이 없이 앱의 진입점이 되게끔 하기 위해서 입니다.

단점

  • env 사용 시 기존에 웹팩을 사용하던 프로젝트에서 마이그레이션 진행할 때 불편함
  • 초기 serve 시 디펜던시 캐시화에 시간이 쪼끔 걸림, 물론 웹팩보다 빠름

마치며

Vite는 번들링 방식에 대해서 여러가지 다른 방법을 썼음에도 결국 배포를 위해서는 기존 번들 과정이 필요합니다. 따라서 비효율적인 부분들 때문에 기존 번들링 기법을 최대한 활용하기 위해서 Vite에서 빌드 명령어들을 제공합니다. 빌드 프로세스는 내부적으로 Rollup을 사용하고 있어서 원하는 경우 Rollup plugin을 설정해줄 수 있습니다.

  • 또 ESM을 사용하고 있어서 기존 CommonJS 방식 파일을 사용하고 싶다면 끝에 cjs라고 명시해줘야 합니다

참고자료