vite로 프로젝트를 구성하기

BangDori·2024년 4월 4일
2

해당 게시물에서는 Vite가 무엇인지부터, Vite를 이용한 프로젝트 구성부터 React, Typescript, 환경 변수, 경로 설정 등에 대한 방법을 다루어 보겠습니다.

📌 Vite

Vite에 대한 정보는 공식 문서에서 자세하게 설명되어 있다. Vite(프랑스어로 "빠르다(Quick)"를 의미하며, 발음은 "veet")는 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드 도구이며, 두 가지 컨셉을 중심으로 하고 있다.

  • 개발 시 네이티브 ES Module을 넘어 Hot Module Replacement와 같이 더욱 다양한 기능을 제공합니다.
  • 번들링 시, Rollup 기반의 다양한 빌드 커맨드를 사용할 수 있습니다.

Vite를 사용해야 하는 이유

기존에는 번들링 도구로 Webpack, Rollup 그리고 Parcel과 같은 도구를 이용하여 번들링을 진행하였습니다.

번들링

bundling image

웹 개발 및 프론트엔드 개발에서 주로 사용되는 용어로, 일반적으로 여러 파일을 하나로 결합 하는 작업을 나타낸다. 이렇게 하나의 파일로 결합하는 것을 "번들링" 이라고도 하는데 번들링은 주로 JavaScript 및 CSS 파일을 하나의 파일로 결합하는 것을 의미
참고: https://webpack.kr/

이러한 번들링 도구는 수 많은 자바스크립트 파일을 하나의 파일로 결합함으로써 프론트 엔드 개발자의 생산성을 크게 향상시켰습니다.

하지만 애플리케이션이 점점 더 발전함에 따라 처리해야 하는 JavaScript 모듈의 개수도 극적으로 증가하고 있습니다. 심지어 수천 개의 모듈이 존재하는 것도 대규모 프로젝트에서는 그리 드문 일이 아닙니다. 이러한 상황에서 JavaScript 기반의 도구는 성능 병목 현상이 발생되었고, 종종 개발 서버를 가동하는 데 너무 오랜 시간을 기다려야 한다거나 HMR을 사용하더라도 변경된 파일이 적용될 때까지 수 초 이상 소요되곤 했습니다. 이와 같은 느린 피드백 루프는 개발자의 생산성에 영향을 주었습니다.

Vite는 이러한 것에 초점을 맞춰, 브라우저에서 지원하는 ES Modules(ESM) 및 네이티브 언어로 작성된 JavaScript 도구 등을 활용해 문제를 해결하고자 합니다.

서버 구동 방식의 차이

콜드 스타트 방식으로 개발 서버를 구동할 때, 번들러 기반의 도구의 경우 애플리케이션 내 모든 소스 코드에 대해 크롤링 및 빌드 작업을 마쳐야지만 실제 페이지를 제공할 수 있습니다.

콜드 스타트 방식

Cold Start란 추천 시스템에서 언급되는 용어로, 새롭게 들어온 유저(고객)이나 특정 컨셉(매니악한)을 가진 유저(고객)에 대한 정보가 충분하지 않아 적절한 상품을 추천해주지 못하는 문제를 의미하는데, 번들링에서는 최초로 실행되어 이전에 캐싱한 데이터가 없는 경우를 의미합니다.

vite는 애플리케이션의 모듈을 dependenciessource code 두 가지 카테고리로 나누어 개발 서버의 시작 시간을 개선합니다.

  • Dependencies: 개발 시 그 내용이 바뀌지 않을 일반적인(Plain) JavaScript 소스 코드입니다. 기존 번들러로는 컴포넌트 라이브러리와 같이 몇 백 개의 JavaScript 모듈을 갖고 있는 매우 큰 디펜던시에 대한 번들링 과정이 매우 비효율적이었고 많은 시간을 필요로 했습니다.

Vite의 사전 번들링 기능은 Esbuild를 사용하고 있습니다. Go로 작성된 Esbuild는 Webpack, Parcel과 같은 기존의 번들러 대비 10-100배 빠른 속도를 제공합니다.

실제로 번들러들의 Build Times를 확인해보면 esbuild가 다른 번들러 대비해 굉장히 빠른 빌드 속도를 가지고 있는 것을 확인할 수 있습니다.

  • Source code: JSX, CSS 또는 Vue/Svelte 컴포넌트와 같이 컴파일링이 필요하고, 수정 또한 매우 잦은 Non-plain JavaScript 소스 코드는 어떻게 할까요? (물론 이들 역시 특정 시점에서 모두 불러올 필요는 없습니다.)

vite는 Native ESM을 이용해 소스 코드를 제공합니다. 이것은 본질적으로 브라우저가 번들러의 작업의 일부를 차지할 수 있도록 합니다. vite는 브라우저가 요청한 대로 소스 코드를 변환하고 제공하기만 하면 됩니다. 조건부 동작 import 이후의 코드는 현재 화면에서 실제로 사용되는 경우에만 처리됩니다.

bundle based dev server
Native ESM based dev server

참고: https://ko.vitejs.dev/guide/why

(추가)

기존의 번들 시스템의 경우 프로젝트내 모든 모듈들을 번들링 한 후에 서버를 구동하였기 때문에, 프로젝트내 모듈의 수에 비례하여 빌드 타임이 걸리게 되었습니다. 하지만 Native ESM으로 기반의 번들링 도구인 vite는 우선 서버를 실행하고, 필요한 부분에 대해서만 번들링하기 때문에 굉장히 빠른 빌드 타임을 가지고 있습니다.

느렸던 소스 코드 갱신

기존의 번들러 기반으로 개발을 진행할 때, 소스 코드를 업데이트 하게 되면 번들링 과정을 다시 거쳐야 했었습니다. 따라서 서비스가 커질수록 소스 코드 갱신 시간 또한 선형적으로 증가하게 됩니다.

일부 번들러는 메모리에서 작업을 수행하여 실제로 갱신에 영향을 받는 파일들만을 새롭게 번들링하도록 했지만, 결국 처음에는 모든 파일에 대한 번들링을 수행해야 했습니다. "모든 파일"을 번들링 하고, 이를 다시 웹 페이지에서 불러오는 것이 얼마나 비효율적인 것인지 느껴지시나요? 이러한 이슈를 우회하고자 HMR(Hot Module Replacement) 이라는 대안이 나왔으나, 이 역시 명확한 해답은 아니였습니다.

물론, vite는 HMR을 지원합니다. 이는 번들러가 아닌 ESM을 이용하는 것입니다. 어떤 모듈이 수정되면 vite는 그저 수정된 모듈과 관련된 부분만을 교체할 뿐이고, 브라우저에서 해당 모듈을 요청하면 교체된 모듈을 전달할 뿐입니다. 전 과정에서 완벽하게 ESM을 이용하게, 앱 사이즈가 커져도 HMR을 포함한 갱신 시간에는 영향을 끼치지 않습니다.

또한 vite는 HTTP 헤더를 활용하여 전체 페이지의 로드 속도를 높입니다. 필요에 따라 소스 코드는 304 Not Modified로, 디펜던시는 Cache-Control: max-age=31536000,immutable을 이용해 캐시됩니다. 이렇게 함으로써 요청 횟수를 최소화하여 페이지 로딩을 빠르게 만들어 줍니다.

이렇게나 빠른 Vite를 사용하지 않을 이유가 있나요?

그럼 이제 Vite에 대해 알아보았으니, 어떻게 프로젝트를 구성하는지 알아보도록 하겠습니다!

📌 Vite + React + TypeScript

저는 React와 TypeScript를 주로 이용하기 때문에, React와 TypeScript를 기반으로 vite를 이용한 프로젝트를 생성해보겠습니다.

# npm 7+, '--'를 반드시 붙여주세요
npm create vite@latest [템플릿 명] --template react+ts

# yarn
yarn create vite [템플릿 명] --template react+ts
  1. vite로 프로젝트 구성을 위해 명령어를 입력합니다. (명령어를 입력하면 다음과 같이 콘솔에 표시되게 됩니다.)

  1. React를 선택해주고, 엔터를 클릭해줍니다.

  1. TypeScript를 선택합니다.

정상적으로 프로젝트 세팅이 완료된 것을 확인할 수 있습니다. 이후, 프로젝트 폴더로 이동하여 디펜던시들을 설치하고, 실행시키면 다음과 같은 화면이 표시되게 됩니다.

프로젝트 초기 세팅이 완료되었고, 이제 환경 변수와 경로 설정을 진행해보겠습니다.

📌 환경 변수 설정

CRA로 프로젝트를 진행할 때는 원래 다음과 같이 환경 변수를 설정했었습니다.

// .env - CRA

REACT_APP_SERVER_ENDPOINT=https://server.com

하지만 Vite에서는 REACT_APP 접두사가 아닌 VITE 접두사를 통해 환경 변수를 설정하고 사용할 수 있습니다.

// .env - VITE

VITE_SERVER_ENDPOINT=https://server.com

위와 같이 설정된 환경 변수는 다음과 같이 사용할 수 있습니다.

import.meta.env.환경변수
import.meta.env.VITE_SERVER_ENDPOINT

아주 잘 동작하는 것을 확인할 수 있습니다.

📌 Alias 경로 설정

우선 typescript를 이용하기 때문에, tsconfig에서 Alias 경로를 설정해주어야 합니다.

{
  "compilerOptions": {
    // ...

    // alias 설정
    "baseUrl": "src",
    "paths": {
      "@/*": ["*"]
    }
  },
  // ...
}

그리고 vite.config.ts에서도 동일하게 설정을 추가해주겠습니다.

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }],
  },
});

위와 같이 설정하면 정상적으로 alias 경로가 설정되게 됩니다.

import Component from "@/component/Component";

const App = () => {
  return <Component />;
};

export default App;

정상적으로 적용된 것을 확인할 수 있습니다.

참고 자료

profile
Happy Day 😊❣️ >> bangdori.kr

0개의 댓글