Last Updated: 2023-12-19

vite-tutorial-cover

이 포스팅을 보기 전에 Javascript 모듈 시스템과 모듈 번들러의 이해 글을 먼저 보기를 권장한다. Vite를 알기 전에 왜 Vite와 같은 빠른 번들러가 지속적으로 출시되는지 알게 된다면 Vite를 이해하는 데 도움이 될 것으로 생각한다.

위 포스팅을 요약하자면,

과거 웹 서비스의 용도는 정보를 전달하는 데 있었기에 그 규모와 복잡도가 낮아 자바스크립트의 모듈화가 필요하지 않았다. 단순하게 순차적 로드 방식으로 자바스크립트를 로드하기만 하면 되었지만, 점차 웹 서비스의 규모가 커지면서 복잡도도 향상되었다. 이에 비례하여 개발/관리되어야 하는 자바스크립트의 파일들이 많아지면서 Commonjs, AMD, UMD, ESM과 같은 모듈 시스템이 등장하게 되었다. 많은 기술들의 등장으로 자바스크립트가 모듈화되어 파일의 개수와 규모는 간소해졌지만 수많은 종속된 모듈들이 증가하면서 이에 따라 모듈의 효율성을 높기 위한 도구로 webpack, rollup, parcel과 같은 번들러가 출시되었다. 하지만 이런 번들러들도 커지는 프로젝트 규모를 감당하기 힘든지 성능적인 문제들이 발생하기 시작하였고 이를 해결하고자 Native 번들러가 출시되기 시작한다.


Javascript 모듈 시스템과 모듈 번들러의 이해 포스팅에 이어서 이번 포스팅에서는 Vite에 대해 알고 넘어가려고한다. 해당 포스팅에서는 문법과 같은 기술적인 측면보다는 Vite가 무엇이 왜 Vite와 같은 번들러가 출시되는지 관련된 동향과 함께 개념적으로 파악해보고자 한다.

Native Bundler

Vite를 설명하기 전에 먼저 알아야 할 것은 Native Bundler이다.

결과적으로는 개발 생산성은 번들러로 인해 과거보다 증가하였지만, 웹 기술과 다양한 프레임워크의 등장, 그리고 증가하는 모듈과 애플리케이션의 규모에 따라 결국 다시 개발 생산성은 저하되는 아이러니한 상황이 발생한다.

애플리케이션의 기술 발전과 처리되어야 하는 Javascript 모듈의 개수가 늘어남에 따라 번들링의 성능도 향상이 되어야 하며, 캐싱 및 최적화 작업으로 인하여 개선된 성능이지만 대규모 종속성 크롤링으로 인한 개발 서버의 속도(dev-server)가 저하된다. 또한 종속된 모듈이 많을수록 개발 서버의 가동 시간과 HMR(Hot Module Replacement)의 시간이 증가하며, 다양한 프레임워크가 출시되면서 이를 지원하기 위해 번들러의 설정이 복잡해지고 있다.

이러한 문제점을 해결하기 위해 Native의 성능을 자랑하는 esbuild와 같은 Native Bundler가 탄생하게 되었다.

현재까지 출시된 많은 번들러들은 대부분이 Node.js 기반으로 작성된 번들러이다. 이와 다르게 Native BundlerGo 또는 Rust와 같은 Native 언어를 기반으로 둔 번들러이며, 이에 따라 기존 번들러와 차별되는 성능을 보인다. Vite의 기반인 esbuild 역시 Go 언어로 작성되었으며, SWC의 경우 Rust 기반으로 작성되었다. 이 Native의 또 다른 의미로는 Node.js가 아니기 때문에 싱글 쓰레드인 Node.js와 다르게 멀티 스레드 환경에서 동작하기 때문에 이 또한 기존 번들러와 성능적 차이를 보이는 요인 중 하나이다.

esbuild

번들러로서의 역할

Native 번들러는 기존 번들러와 성능적인 차별화는 있지만 번들러로서의 역할이 부족하다. 번들러로서의 조건은 빠른 성능만이 아니다. 개발 서버 구동, Sass와 Less, Stylus 등 표준이 아닌 기술들을 실행하고 변환할 수 있는 기능과 같은 기존 번들러들이 제공되는 기능 즉, Dev-Server, Loader, Transpile, Code-Splitting, Tree Shaking, HMR과 같은 기능 지원이 미비하다.

이를 보완하고자 esbuild 기반으로 빠른 성능의 장점과 Rollup의 번들러로서의 기능을 제공하는 Vite가 등장한다.


Vite

Vite는 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드 도구로 개발 경험을 개선하여 속도와 성능에 중점을 둔 번들러이다.

Vite에서 제공하는 사전 번들링은 Go로 작성되어있는 esbuild를 사용하고 있기 때문에 Webpack, parcel과 같은 기존 번들러보다 10~100배 빠른 속도를 제공한다. 그리고 번들링 시 Rollup을 기반으로 다양한 빌드 커맨드를 사용하여 개발 경험을 높여준다.

Vite의 특징

Vite는 ESM 및 Native 언어를 통해서 기존 Javascript 기반의 번들러의 문제점을 해결했다.

Native ESM 지원으로 별도의 번들링 없이 개발 서버를 실행할 수 있으며, ESM이기 때문에 별도의 변환 작업 없이 브라우저에 직접적으로 제공하며, esbuild를 통해 종속성 모듈을 사전 번들링하여 개발 서버의 성능을 향상 시킨다. 또한 preload 스텝을 이용한 병렬적(Parallel)으로 모듈을 로드하기 때문에 빌드에 최적화되어 있다.

요약하자면,

  • Native ESM 지원으로 별도의 번들링 없이 개발 서버 실행 및 브라우저 직접 제공
  • esbuild를 통해 종속성 모듈을 사전 번들링
  • preload 스텝을 이용한 병렬적(Parallel)으로 모듈을 로드하여 빌드의 최적화

비동기 방식 모듈 로드 최적화
async-chunk-loading-optimization

병렬처리
parallel-processing

기존 번들러의 문제점 해결

Vite는 기존 번들러의 단점인 느린 피드백 루프에 초점을 맞춰 브라우저에서 지원하는 ESM 및 Natvie 언어로 작성되어 기존 문제점을 해결하였다.

Dev-Server의 성능 저하

Javascript 번들러의 개발 서버 구동은 코드-스타트 방식(최초로 실행되어 이전에 캐싱한 데이터가 없는 경우)으로 애플리케이션 내의 모든 소스 코드에 대해 크롤링, 종속성 그래프를 생성하였고 빌드 작업이 끝나야만 실제로 페이지를 제공하였기 때문에 서버의 구동 시간이 오래 걸렸다. 이것은 애플리케이션의 규모가 커짐에 따라 비례하여 증가하기 때문에 규모가 클수록 더욱 느리다.

Vite는 이를 두 가지 방안으로 나누어 개발 서버의 성능 향상시켰다.

Dependencies(종속성)의 사전 번들링
기존 번들러는 수백개에 이르는 종속된 Javascript 모듈을 비효율적으로 번들링하였고 이로 인해 많은 시간을 소모하였다. Vite의 경우 esbuild를 통해 종속된 모듈을 사전에 번들링하여 webpack, parcel 대비 10-100배 빠르도록 설계되었다.

Native ESM을 이용한 소스 코드 제공
Vite는 브라우저와 Node.js가 이해할 수 있는 Native ESM으로 소스 코드를 제공하기 때문에 별도의 컴파일링 없이 브라우저를 번들러로 사용하였기 때문에 성능적으로 향상되었다.

HMR(Hot Module Replacement)의 성능 저하

Javascript 번들러는 소스 코드를 업데이트하게 되면 번들링 과정을 다시 걸쳤으며, 이로 인해서 애플리케이션의 규모에 비례하여 HMR 속도도 저하되었다. 이에 반면 Vite의 경우 특정 모듈이 수정될 경우 ESM을 이용하여 수정된 부분만 교체 후 브라우저에서 해당 모듈을 요청하면 변경된 모듈만 전달하고 이과 정을 전부 ESM을 이용하기 때문에 애플리케이션의 규모와 상관없이 일정한 HTML 성능을 유지한다.

Bundle Base와 ESM Base의 차이

Bundle Base의 경우 모든 종속성 모듈을 번들링하지만 Native ESM의 경우에는 경로 기반 검색으로 해당 모듈을 사용해야만 처리한다. 다시 말해, Native ESM 기반의 Dev-Server는 경로 기반으로 현재 화면에서 해당 모듈을 사용해야만 처리하기 때문에 배포에 필요한 번들링이나 HMR 속도가 빠른 것이다.

bundle-base-dev-server

nativeesm-base-dev-server

번들러의 비교

지금도 물론 Webpack의 점유율이 높지만, 점차 급격하게 Vite가 상승하는 것을 확인 할 수 있다.

지원 브라우저

Native ESM 모듈과 Dynamic Import를 지원하는 브라우저를 대상으로 지원한다. 레거시 브라우저는 프로덕션용으로 빌드 시 @vitejs/plugin-legacy를 이용하여 지원할 수 있다.

support-browser

성능테스트

vue-cliVite를 대상으로 100개의 컴포넌트를 기준으로 측정한 성능 테스트이다. 측정 대상은 개발서버 구동 속도, HMR, Build 속도이다. 이 테스트 벤치마킹은 개발 환경과 컴포넌트의 개수에 따라 달라지므로 참고만하도록 하자.

Dev-Server HMR(Hot Module Replacement) Build
vue-cli 8초 0.6초 8.3초
vite 0.6초 즉시 반영 4.2초

지금까지 Vite의 개념적인 내용을 파악해 보았다.

Vite의 출시로 인해 Frontend 환경의 큰 변화를 가져다주었다. 지금 당장 실무에 반영해도 되겠냐는 의견이 있었다면, 나는 당장이라도 반영하라고 전하고 싶다. 그만큼 좋은 효과를 뽑아낼 수 있을 것이며, 지속적으로 Vite는 안정화되어 가고 있기 때문에 실무에 반영은 고민하지 않아도 된다고 생각한다. 물론 Vite를 반영하기 위해서는 이에 따른 특정 부분에 대한 마이그레이션이 필요하겠지만, Vite 자체로 가져다주는 효과를 생각한다면 충분히 감안해도 될 것이다.

다음 포스팅은 Vite의 문법과 설정 사항 등의 테크니컬적인 세부 내용을 살펴볼 예정이다.