Bonjour, Vite! (Vite 실무 적용기)

Bonjour, Vite! (Vite 실무 적용기)

작성자 hectodata

1. Introduction

💡 번들러의 개념부터 알아볼까요?

💥 번들러가 없던 시절

초기 웹 생태계는 지금처럼 웹사이트의 규모가 크지 않았습니다. 따라서 웹을 구성하는 HTML이나 자바스크립트의 파일 크기가 작았고, 서비스의 유지보수도 그렇게 어렵지 않았습니다.

초창기 네이버의 웹페이지 화면 (지금의 네이버와 비교했을 때 꽤나 단순해 보이죠?)

그러나 점점 기술이 발전하면서 파일 하나당 코드의 양이 많아지고, 하나의 페이지를 구성하는 파일의 수도 커지게 되었으며, 복잡한 웹사이트의 경우 적게는 수백 개, 많게는 수천 개의 파일들을 다루게 되면서 크고 작은 문제들이 발생하게 되었습니다.

💡 대표적인 문제점은 충돌과 속도 이슈..!
  1. 중복된 이름으로 인한 충돌, 오류
  • 대규모 웹페이지의 경우, 엄청난 개수의 자바스크립트 파일로 구성되며, 여러 개발자가 하나의 서비스 개발에 참여하므로 서로 만든 함수 또는 변수명이 겹치는 일이 일어나는 경우가 허다합니다. 따라서 이런 경우 언제 어디서 충돌이 일어날지 모르는 위험이 존재합니다.

2.  파일 전송 속도 문제

  • 브라우저에서 각각의 페이지로 이동할 때, 서버는 해당 페이지를 구현하는 파일을 브라우저에 제공합니다. 웹 애플리케이션을 구성하는 파일의 양이 많아지면 많아질수록 파일을 제공하여 웹페이지를 그려내기까지 시간은 오래 걸릴 수밖에 없습니다.
  • 유지보수 측면에서는 각각의 기능별로 파일을 여러 개 쪼개서 개발하는 것이 유리한데, 파일이 많아지거나 파일 하나당 크기가 커질수록 속도 이슈에 대한 문제는 더욱 커지게 됩니다. 그렇지만 속도를 위해서 하나의 파일에 모든 코드를 개발하는 것 또한 현실적으로 불가능한 방법입니다.
  • 이처럼 가독성, 유지 보수를 위해 파일을 분리하면 네트워크 병목현상이 일어날 것이고, 응답 시간을 위해 파일 수를 줄이면 가독성, 유지 보수가 힘들어지는 딜레마에 빠지게 됩니다.
💡 이와같은 문제들로 인해 여러개의 파일을 하나의 파일로 묶어주는 번들러가 등장합니다. 🎊

✨ 번들러의 탄생

위와 같은 문제들을 해결하기 위해 번들러라는 것이 탄생하였습니다. 번들러란, 여러 개의 파일을 하나의 자바스크립트 파일로 묶어주는 역할을 하는데, 대표적으로 webpack , parcel, rollup 등이 존재합니다. 그리고 저희 헥토데이터의 기존 소스코드들은 그중 가장 범용적으로 사용되어 왔던 webpack을 사용하여 번들링을 하였습니다.

💡 Webpack이란?

오픈 소스 자바스크립트 모듈 번들러 로써 여러 개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축하고 최적화하는 라이브러리입니다.

💡 Webpack의 장점
  1. 여러 파일의 자바스크립트 코드를 압축하여 최적화할 수 있기 때문에 로딩에 대한 네트워크 비용을 줄일 수 있습니다.
  2. 모듈 단위로 개발이 가능하여, 가독성과 유지보수가 쉽습니다.
  3. 최신 자바스크립트 문법을 지원하지 않는 브라우저에서 사용할 수 있는 코드로 쉽게 변환시켜 줍니다.

🙈 Webpack..정말 좋은 거 맞아?

지금 헥토데이터의 프론트엔드 개발에서 주로 사용하는 Vue.js나 최근 프론트엔드 시장에서 가장 대중적으로 사용되고 있는 React, 그리고 Angular와 같은 프론트엔드 프레임워크/라이브러리가 처음 나왔던 초창기에는 webpack이 가장 널리 사용되었었고, webpack을 이용한 다른 플러그인들의 사용이 용이했기 때문에 webpack은 지금까지도 가장 많이 사용되는 번들러 중 하나입니다.

하지만 실무에서 개발할 때 webpack을 사용하면서 개발자로서 느낀 가장 큰 단점이 하나 있었는데 그건 바로..

프로젝트의 크기가 커지면 커질수록 빌드되는 속도가 느려도 너무 느려지는 것이었습니다. 🐌

Vue.js를 이용한 프론트엔드 개발은 Hot Reload를 통해 그때 그때 저장한 내용을 바로 화면으로 확인하며 개발하는 것이 장점인데, 프로젝트의 크기가 커지면서 번들링해야 하는 파일의 수가 많아지면 webpack은 점점 힘들어하는 것이 눈에 보일 정도로 느려집니다. 심지어 어떤 코드에서는 파일 저장 후 다시 번들링해서 화면으로 보이기까지 1분(…!!!)이 넘는 시간이 걸리기도 했습니다.

🤔 그래서 우리가 찾은 대안은?

매번 파일을 수정할 때마다 변경된 사항을 1분여의 시간을 기다려가며 확인한다는 것은 용납할 수 없는 일이었습니다. 속도가 생명인 프론트엔드 개발에서 저장 후 번들링을 하는 1분간의 시간이 쌓이고 쌓이다 보면 하루 업무 시간의 대부분은 번들링을 기다리는 시간으로 때워야 하는 거였기 때문에 업무 효율성도 매우 떨어지고 이대로는 안 되겠다고 판단을 하고 대안을 찾아보았습니다.

그리고 그 대안으로 찾은 것은 번들링 툴, Vite 였습니다!

2. Vite란?

💡 비트는 Vue.js의 창시자 Evan You가 만든 새로운 프론트엔드 도구로 프랑스어로 빠르다를 의미하며 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드도구입니다.

📓 자바스크립트의 모듈 시스템과 Vite

💡 자바스크립트의 모듈 시스템의 배경

자바스크립트는 웹페이지의 보조 기능 처리를 위한 간단한 목적으로 탄생했습니다. 그 때문에 큰 규모의 어플리케이션을 만들 목적이 아니었기에, 파일을 여러 개로 분리하여 개발하는 것이 불가능했습니다. 이는 자바스크립트가 원래 모듈 시스템을 지원하지 않았음을 의미합니다. 다시 말해, 파일 스코프, import, export 기능을 지원하지 않았습니다.

자바스크립트를 범용적으로 사용하기 위해, 모듈 시스템필수적이었습니다. 이를 위해 CommonJS와 AMD가 사용되었습니다. 마침내, ES6에서는 클라이언트 사이드 자바스크립트에서도 동작하는 모듈 기능을 추가했습니다. CommonJS와 AMD의 장점을 취합한 새로운 import, export 문법을 도입하였습니다. 이는 동기적, 비동기적 로딩을 모두 지원하면서 더욱 강력한 모듈 시스템을 제공하게 되었습니다.

브라우저에서 ESM(ES Modules)을 지원하기 전까지, JavaScript 모듈화를 네이티브 레벨에서 진행할 수 없었습니다. 그래서 소스 모듈을 브라우저에서 실행할 수 있는 파일로 크롤링, 처리 및 연결하는 "번들링(Bundling)"이라는 해결 방법을 사용해야 했습니다. 대표적으로 앞서 언급했던 Webpack, Rollup 그리고 **Parcel**과 같은 도구가 있습니다. 하지만 프로젝트의 규모가 커질수록  Javascript기반의 도구는 성능 병목 현상과 빌드 속도가 느리다는 문제가 있었습니다.

📒 esbuild의 등장

이에 대응하여 100배 빠른 빌드속도를 가진 esbuild가 등장합니다.  Go로 작성된 esbuildWebpack, Parcel과 같은 기존의 번들러 대비 10-100배 빠른 속도를 제공합니다. 하지만 기능적으로는 단순 빌드 도구에 불과하였습니다. 다른 번들러는 이미 그당시에 빌드 뿐만아니라 다양한 기능들을 제공하고 있었습니다. 그래서 esbuild의 빠른 속도를 이용하면서도 기존 번들러의 강점을 살린 도구가 필요했습니다.

이렇게 탄생하게 된게 Vite 입니다. Viteesbuild빠른 빌드 속도브라우저 모듈의 장점을 결합하여 복잡한 프론트엔드 개발 환경에서도 빠른 개발 속도안정성을 제공하게 되었습니다.

💫 vite가 빠를수 있었던 이유

Vite는 기존 자바 스크립트 코드에 대해서는 사전번들링 기능으로 esbuild를 사용하여 시간을 단축했습니다. 그리고 JSX,CSS 또는 Vue, Svelte 컴포넌트와 같이 컴파일링이 필요하고, 수정 또한 매우 잦은 Non-plain JavaScript 소스 코드에 대해서는 Native ESM을 이용해 소스코드를 제공합니다.  브라우저가 번들러의 작업의 일부를 차지할 수 있도록 하여 Vite는 브라우저가 요청하는 대로 소스 코드를 변환하고 제공하기만 하면 됩니다.

📝 Vite 의 특징

  • 빠른 개발: 비트는 로컬에서 개발할 때 번들링을 하지않고 ESM방식을 사용하여 서버 구동 속도가 매우 빠릅니다. 웹팩 데브 서버와 비교해봤을때 20~30배 이상 차이가 납니다.  또한, 내장된 서버는 Hot Module Replacement(HMR)를 지원합니다.
  • Rollup기반의 프로덕션 최적화: 프로덕션 빌드 시 Rollup을 사용하여 코드를 최적화합니다. Rollup은 코드를 효과적으로 트리쉐이킹 하여 불필요한 코드를 제거하고, 결과물의 파일 크기를 최소화 합니다.
  • 다양한 프레임워크 지원: Vite는 Vue, React, Preact, LitElement 등 다양한 프레임워크를 지원하며, 커스텀 플러그인을 통해 다른 프레임워크나 라이브러리와의 호환성도 확보할 수 있습니다.
  • CSS, 이미지, 기타 자산 처리: Vite는 CSS 모듈, CSS 프리프로세서(SCSS, Less 등), URL 참조를 통한 이미지와 기타 자산 처리를 지원합니다.

3. Webpack vs Vite

💡 사용량과 만족도 순위로 Webpack 과 Vite를 비교해 볼 수 있습니다.
Bundler 사용량 순위
Bundler 만족도 순위

번들러 생태계는 빠르게 변화하고 있습니다. 초기에 출시되었던 webpack은 많은 사람들이 사용하고 있으나, 시간이 지날수록 만족도는 감소하고 있는 추세입니다.

반면 Vite의 경우 2021년 30% 사용량으로 출발하였으나 무서운 속도로 사용량이 증가하고 있으며 특히 사용 후 사람들의 만족도가 굉장히 높아, ‘2021년, 2022년 가장 만족도가 높은 번들툴’로 선정되었습니다.

초기 번들러 Webpack과 현재 무서운 속도로 성장하고 있는 Vite를 비교해 보았습니다.

Webpack Vite
번들링 속도 대규모 프로젝트에서 초기 빌드 속도가 느릴 수 있다. 개발 서버를 통해 빠른 번들링 속도를 제공한다. 파일이 필요할 때마다 필요한 모듈만 번들링하여 신속한 개발이 가능하다.
개발 서버 개발 서버를 제공하지만, HMR등 추가적인 설정이 필요하다. 기본적으로 HMR을 포함한 빠르고 간단한 개발 서버를 제공한다.
환경 설정 다양한 설정 가능. 하지만 초기 설정하기에는 복잡할 수 있다. 기본 설정이 간단하며, 프로젝트 생성 시 초기 설정을 자동으로 처리한다.
생태계 많은 플러그인과 로더를 통해 다양한 기능을 제공한다. 대부분의 프로젝트에서 사용되고 있어 확장성이 우수하다. Vue.js와 같은 프론트엔드 프레임워크와의 통합에 중점을 두고 개발되어, Vue.js 프로젝트에서 특히 잘 작동하며, Vue 3의 새로운 기능을 최대한 활용 할 수 있다.
문서화 정리된 공식 문서와 다양한 자료들이 있어 사용자들이 쉽게 학습할 수 있다. 아직은 Webpack만큼의 방대한 문서와 자료는 없지만, 빠르게 성장하고 있다.
HMR(Hot Module Replacement) : 실시간 모듈 교체, HMR은 수정된 모듈을 즉시 반영하여 브라우저를 새로 고치지 않고도 개발자가 변경 사항을 즉시 확인할 수 있게 한다.

4. How to move?

💡 Vite로 마이그레이션 하는 두 가지 방법을 소개합니다. 두 가지 방법 모두 각자의 장단점이 있으며, 프로젝트 크기와 구조에 따라 적합한 방법을 선택해야 합니다. 마이그레이션을 진행할 때는 프로젝트의 안정성과 기능을 유지하면서 최소한의 변화로 마이그레이션을 완료하는 것이 중요합니다.

1️⃣ 기존 프로젝트에 디펜던시 설정 및 수정

✔️ Vite 추가

Vite 관련 라이브러리 설치

$ npm install vite @vitejs/plugin-vue --save-dev

✔️ 설정 추가

vite.config.js 파일 생성

// vite.config.js
import { fileURLToPath, URL } from 'node:url';

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

// <https://vitejs.dev/config/>
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: { // 기본 디렉토리 정의
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
  define: { // 환경변수 정의
    'process.env': process.env,
  },
  server: { // 개발 서버 포트 설정
    port: 7600,
  },
});

✔️ 기존 파일 수정

.env

  • VITE_ 라는 접두사를 붙여줍니다.
  • import.meta.env  객체를 통해 문자열 형태로 접근이 가능합니다.
// .env
VITE_CODEF_DOMAIN=http://localhost:8088
VITE_GA_KEY=

index.html

  • /public 경로에 있던 index.html을 root 로 이동합니다.
  • 파일을 수정합니다.
// index.html

// 1. BASE_URL 참조 제거
// 기존
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
// vite
<link rel="icon" href="/favicon.ico" />

// 2. entrypoint 추가
 <script type="module" src="/src/main.js"></script>

vue-cli dependency 삭제

  • vue-cli용 dependency
  • @vue/cli-plugin-babel
  • @vue/cli-plugin-eslint
  • @vue/cli-service
  • webpack 설정 dependency
  • copy-webpack-pluginvite-plugin-static-copy로 변경합니다.
$ npm uninstall @vue/cli-plugin-babel @vue/cli-plugin-eslint @vue/cli-service copy-webpack-plugin --save

package.json

  • build script를 업데이트합니다.
// package.json
  "scripts": {
		// 기존
    "serve": "vue-cli-service serve",
    "build-dev": "vue-cli-service build --mode development",
    "build-real": "vue-cli-service build --mode production",
		// vite
    "dev": "vite --host",
    "build-dev": "NODE_ENV=DEV vite build --mode=development",
    "build-real": "NODE_ENV=production vite build --mode=production",
    "preview": "vite preview"
  },

.vue extension처리

2️⃣ 신규 프로젝트 생성 및 소스 이동

✔️ Vite 프로젝트 생성 및 실행

// vite 프로젝트 설치 -> 프레임워크 vue 선택
$ npm create vite@latest

// 또는 vue 프로젝트 설치 (기본 빌드 도구 vite)
$ npm create vue@latest

// 실행
$ cd "프로젝트 명"
$ npm install
$ npm run dev

✔️소스 이동

프로젝트 파일 이동

  • .vue extension을 추가하며 이동합니다.

파일 수정

  • index.html
  • package.json
  • 기존 vue-cli용 dependency를 제거합니다.
  • webpack plugin을 제거합니다.
  • .env
  • VITE_ 접두사를 추가합니다.
  • import.meta.env.변수명 으로 호출합니다.

💡 참고 오류

5. 결과 및 이슈 해결 방법

💡 위의 두 번째 방법인 Vite 신규 프로젝트를 생성하여 기존 소스를 옮기는 형식으로 실제 마이그레이션을 진행해 보았습니다. 또한, 진행하면서 겪었던 이슈와 해결 방법에 대해 적어 보았습니다.

1️⃣ 신규 프로젝트 생성

$ npm create vite@latest

2️⃣ 패키지 버전 충돌

🚨 발생 원인

주로 두 패키지가 서로 다른 버전의 다른 패키지를 필요로 하는 경우 발생하는 문제입니다. @vitejs/plugin-vue 패키지가 vite 버전 2.5.10을 필요로 하는데, 프로젝트의 루트 레벨에서는 이미 Vite 버전 5.1.4를 사용하고 있습니다. 이에 따라 버전 충돌이 발생한 것입니다.

🙆‍♀️ 해결 방법

$ npm install —force

3️⃣ @vitejs/plugin-vue-3 패키지를 찾을 수 없다는 문제

🚨 발생 원인

@vitejs/plugin-vue-3 npm 레지스트리에 없어서 발생하는 문제입니다.

🙆‍♀️ 해결 방법

@vitejs/plugin-vue-3를 삭제하고 @vitejs/plugin-vue를 대신 사용했습니다. vite2.0 이상에서는 @vitejs/plugin-vue 패키지가 자동으로 vue3를 지원합니다.

4️⃣ Sass mixin 문제

🚨 발생 원인

sass mixin 부분을 인식하지 못하였습니다.

🙆‍♀️ 해결 방법

mixin.scss 파일 정의해서 import 하였습니다.

5️⃣ 라우터에서 파일 인식 못하는 문제

🚨 발생 원인

src/router/index.js 에서  @/pages/main 으로 했을 때는 vue 파일 경로를 인식하지 못합니다.

🙆‍♀️ 해결 방법

@/pages/main/index.vue 라고 명시해주어야 파일 인식이 가능했습니다.

6️⃣ import 파일 확장자 명시

🚨 발생 원인

기존에는 .vue를 파일마다 생략해도 됐지만 Vite에서는 확장자를 붙여줘야 인식을 합니다.

🙆‍♀️ 해결 방법

.vue 확장자를 붙여줍니다.

7️⃣ env 환경변수 설정 및 사용법 변경

🚨 발생 원인

기존 VUE_APP 접두사와 process.env를 인식하지 못했습니다.

🙆‍♀️ 해결 방법

접두사 VITE_ 로 변경하고 import.meta.env 로 사용하면 인식하게 됩니다. 변경 후에는 API 통신도 정상적으로 이루어졌습니다.

8️⃣ unmount 설정

🚨 발생 원인

createApp 메서드로 새로운 Vue 앱을 생성할때 기존에 마운트된 Vue 인스턴스와 충돌이 났습니다.

🙆‍♀️ 해결 방법

이전 앱이 마운트되어 있을 때 unmount()를 호출하며 이전에 마운트된 Vue 인스턴스를 제거하고 비워줍니다. 초기화 할 때 마다 깨끗해진 상태에서 시작하도록 해주었습니다.

9️⃣ 결과

성공적으로 마이그레이션한 페이지가 작동되는 것을 확인할 수 있습니다!

⚡Webpack vs Vite 빌드 속도 차이

그러면 과연 Vite를 사용한 프로젝트의 빌드는 Webpack을 사용한 동일한 프로젝트 빌드 속도에 비해 얼마나 빨라졌을까요?

  • Webpack 빌드 속도 (3분 11초 - 191초)
  • Vite 빌드 속도 (49초)

🫢 191초 걸리던 빌드가 49초로 기존 Webpack 빌드속도에 비해 75%나 빨라졌습니다!! (할렐루야!!)

Vite는 정말 이름 그대로 매우 빠른 번들러임이 확인되는 순간이었습니다.

저희 헥토데이터 서비스 개발팀은 Vite를 도입하고 난 뒤 업무의 질이 달라졌다는 팀원들의 후기가 줄줄이 이어졌고, 앞으로 더 빠른 번들러가 나오기 전까지는 계속 Vite를 이용하여 프로젝트를 진행할 계획입니다.

지금까지 번들러의 개념부터 저희 헥토데이터 FE팀의 Webpack에서부터 Vite 적용기를 살펴보았습니다.  다음 포스트를 기대해 주세요!

📎 참고 자료

헥토데이터는 데이터 기반 다양한 서비스를 지원하는 기업입니다. 온라인에 분산된 데이터를 실시간으로 제공하기 위해 클라이언트 엔진과 웹 API를 활용합니다. 유수의 비대면 대출 핀테크 서비스가 선택한 헥토데이터의 CODEF API. 꼼꼼한 보안과 빠른 대응으로 기업이 자사 서비스에만 집중할 수 있도록 돕는 CODEF API에 대해 아래 배너를 눌러 확인해 보세요.

02_----------------_230616-1본 페이지 내의 모든 콘텐츠는 저작권법에 의해 보호받는 저작물로서, 모든 사용 권리는 ㈜헥토데이터에게 있습니다. 별도의 저작권 표시 없이 무단으로 사용하는 것을 금지하며, 자세한 저작권 정책은 해당 링크를 참고하시기 바랍니다. Copyright 2024.㈜헥토데이터 All rights reserved.

© Hecto Data Co., Ltd. All right reserved. Published with Ghost


(주)헥토데이터ㅣ대표자 : 오승철

사업자 등록번호 : 113-86-32627


개인정보 처리방침