Vite: Fastest Build Tool
계기
최근 여러 군데 면접을 보면서 가장 기억 나는 프로젝트에 대한 대답으로 CRA -> Vite 전환을 뽑았는데, 왜 VITE 가 빠른가요 ? 라는 질문에 명확하게 대답하지 못했습니다. 실제로 적용해보니 빠른건 알겠는데, 정확히 왜 빠른가 ? 에 대해 확실하게 알고 있지 못해서 어려움이 있어 이번 기회에 이를 정리해보고자 합니다.
웹 브라우저의 동작 방식과 번들러
CRA 와 Vite 를 비교하기 위해서는 먼저 웹 브라우저의 동작 방식을 알아야 합니다. MDN - 웹 페이지를 표시한다는 것: 브라우저는 어떻게 동작하는가 를 참고해 간단히 요약하면,
- 입력된 URL 주소를 해석해 , 서버에 요청을 보냅니다.
- 서버는 요청을 보고 , HTML , CSS , JS 등의 response 를 브라우저에게 보내줍니다.
- 브라우저가 이 response 를 받아서 아래와 같은 작업을 실행합니다
- HTML 파일을 읽어 DOM ( Document Object Model ) 트리 구조를 만듭니다.
- CSS 파일을 읽어 CSSOM ( CSS Object Model ) 의 스타일 구조를 만듭니다.
- 또한 JS 파일을 다운로드합니다.
이 과정에서 JS , CSS , 이미지 등등을 브라우저가 이해하고 로딩할 수 있게 여러개의 번들로 만드는데 , 이 동작을 도와주는게 번들러 ( Bundler ) 입니다. 번들러는 코드를 압축하거나 분할하고, 최신 문법을 구형 브라우저에서 작동하도록 ( 트랜스파일링 ) 하는 등의 최적화 작업을 수행합니다.
웹 어플리케이션이 점점 커지게 되면 해당 번들링 과정에서 빌드 시간이 오래 걸릴 뿐만 아니라 , 브라우저가 번들을 다운로드하고 처리하는 과정에서 많은 시간이 소요될 수 있습니다. 이 과정에서 여러 종류의 번들러가 사용되는데 , 이 때 사용되는 도구들의 차이가 추후 설명할 CRA 와 VITE 에서의 속도 차이를 발생시킵니다.
이후 DOM 과 CSSOM 을 결합해 화면에 보여줄 렌더링 트리를 만듭니다. 해당 렌더링 트리를 기반으로 레이아웃을 만들고 화면에 그림을 그리게 ( Painting ) 됩니다. 또한 번들 파일 내부의 JS 코드를 실행해 DOM 을 조작하고, 웹 페이지를 완성합니다.
CRA의 빌드 방식
CRA ( Create React App ) 의 경우 , 개발자가 별도의 설정을 진행할 필요 없이 미리 최적화된 설정으로 개발을 진행할 수 있도록 제공하고 있습니다. 내부적으로는 Webpack 을 사용해서 번들링을 진행합니다.
다만 Webpack 의 경우 애플리케이션의 모든 모듈을 탐색 후 의존성 그래프를 만들게 되는데 규모가 커질수록 , 의존성이 복잡해질수록 그래프를 분석하는데 많은 시간이 걸리고 , 이 그래프를 가지고 번들링이 진행될 때 많은 연산과 시간이 걸리게 됩니다. 또한 개발 환경에서 변경이 발생하면 변경된 모듈 뿐만 아니라 , 의존성이 연결되어 있는 다른 모듈을 포함해 거의 대부분의 모듈을 다시 빌드하게 됩니다. 이 과정에서 더 많은 시간이 소요되게 됩니다. Vite 는 이 단점을 극복해 빠른 속도를 제공합니다.
Vite 가 뭔데 ?
공식 문서에서는 Vite 를 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드 툴 이라고 소개하고 있습니다. 그러면서 크게 두 가지 부분으로 구성되어 있다고 말하는데,
- 네이티브 ES 모듈을 통해 소스 파일을 제공하는 개발 서버로, 다양한 기능과 놀라울 정도로 빠른 Hot Module Replacement(HMR)를 제공합니다.
- Rollup을 사용해 코드를 번들링하는 빌드 명령어로, 프로덕션을 위해 고도로 최적화된 정적 에셋을 출력하도록 구성되어 있습니다.
Vite 의 빌드 방식
Vite 는 기존 번들러와는 다른 방식으로 속도를 크게 개선했는데 , 중요한 아이디어는 개발 단계에서는 번들링 하지 않고, 브라우저의 ESM 기술을 사용 한다는 점 입니다.
최신 웹 브라우저는 ECMAScript Modules (ESM) 을 기본적으로 지원합니다. ESM 은 <script type='module'> 태그를 사용해 JS 파일을 모듈 단위로 로드하고 , 그 의존성은 import 와 export 로 관리합니다. Vite 는 이를 활용해 개발 서버에서는 따로 코드를 번들링하지 않고, 브라우저가 특정 모듈이 필요하다면 해당 모듈을 즉시 브라우저에게 제공하는 식입니다. 위 방식을 통해 CRA 가 전체 애플리케이션을 위해 빌드하는 시간을 줄일 수 있었습니다. 또한 브라우저가 HTML 파일을 파싱하면서 script 태그를 보고 필요한 js 모듈을 요청하면 해당 모듈만 빠르게 제공해 콘텐츠를 바로 보여줄 수 있다는 점이 있습니다.
또한 HMR ( Hot Module Replacement ) 방식에서도 차이가 있는데 , 기존 CRA 에서 사용하는 Webpack 의 경우 파일이 변경되면 의존성 그래프를 다시 만들고 , 관련있는 모듈을 재빌드하면서 많은 시간이 걸렸습니다. 하지만 Vite 는 ESM 을 사용해 변경된 모듈과 그 영향받는 모듈만을 빠르게 파악해서 업데이트할 수 있습니다. 이로써 개발자가 특정 코드를 수정하고 , 빠른 시간내에 변경점을 파악할 수 있다는 장점이 있습니다.
마지막으로 Production 빌드의 경우, ESM 기반의 Rollup 이라는 번들러를 사용해서 최종 번들 크기를 최소화하고, 최적화된 번들을 제공합니다.
결국 Vite 는 ESM 을 적극적으로 사용해 개발 단계에서는 빠른 업데이트를 제공하고 , production 에서는 번들 크기를 최적화합니다. 이로써 CRA 가 가지고 있던 단점을 해결하고 , 보다 빠르게 개발을 진행할 수 있게 되었습니다.
후기
Vite 가 빠른 이유를 정리해 보았는데 , 이전에는 실제로 적용해 보아서 느꼈다면 이번에는 확실한 이유를 통해 이해하게 되었습니다. 또한 희미하게 알고 있거나 , 까먹었던 정보들도 정리할 수 있어서 좋았습니다. 이제는 확실하게 왜 Vite 가 빠르고 , 왜 사용해야 하는지 말할 수 있을 것 같습니다 .