티스토리 뷰
토이 프로젝트를 시작하면서, Vite를 빌드 툴로 사용하기로 했다. 예전에 Vite가 빠르다고 들어서 사용해보고 싶었는데, 이번에 사용하게 되어 어떤 툴인지 정리해보려 한다.
Vite란?
Vite는 프랑스어로 빠르다라는 의미이며 Vue, React, Svelte 등 주요 프론트엔드 라이브러리, 프레임워크 커뮤니티에서 주목하고 있다.
이유가 뭘까? Vite를 사용하는 하는 이유와 등장배경을 알아보자.
Vite를 사용해야 하는 이유?
1. JavaScript의 모듈화
공식문서에 따르면, ESM(ES Modules)을 지원하기 전까지는 브라우저에서 JavaScript 코드를 모듈로 나눠서 사용하는 게 쉽지 않았다.
여기서 모듈이란 간단하게 말해서 코드를 기능별로 나눠서 관리하기 쉽게 만든 작은 단위이다.
예를 들어, 계산기 앱을 만든다고 생각해보자. 덧셈, 뺄셈, 곱셈, 나눗셈 기능을 각각 다른 파일로 만들어 놓으면 나중에 수정하거나 새 기능을 추가할 때 훨씬 편하지 않을까? 이렇게 나눠놓은 각각의 파일을 '모듈'이라고 부른다.
2. 모듈을 하나로 묶자! 번들링(Bundling)
그런데 브라우저는 이렇게 나눠진 파일들을 그대로 이해하지 못한다. 그래서 번들링(Bundling)이라는 방법을 사용하여 이를 해결한다.
번들링이란 여러 개의 모듈을 하나의 파일로 합치는 작업이다. 마치 여러 개의 퍼즐 조각을 맞춰 하나의 그림을 완성하는 것과 비슷한 것 처럼!
Webpack, Rollup, Parcel 같은 툴들이 이러한 번들링 작업을 도와주었고(Webpack 밖에 몰랐는데 다양하구나..), 덕분에 프론트엔드 개발자의 생산성이 크게 향상되었다.
3. 규모가 커진 앱, 더 커진 고민
하지만 앱의 규모가 점점 커지면서 문제가 발생한다. 바로 모듈의 수가 수천 개로 늘어나버린 것..!
100개였던 퍼즐 조각이 1000개로 늘어난 것과 같은 상황이 발생하게된다. 퍼즐 조각이 늘어나면 어떻게 될까? 예전보다 퍼즐을 맞추는데 시간이 오래걸리지 않을까?
번들링 도구도 마찬가지로, 이렇게 많아진 모듈을 처리하는 데 시간이 많이 걸리기 시작하게된다. 개발 서버를 켤 때도 오래걸리고, 코드를 수정하고 반영되는 데도 수 초 이상이 소요되었다.
4. Vite의 등장
이러한 상황속에서 등장한 것이 바로 Vite이다.
앞서 말했던 것 처럼 '빠르다'라는 의미를 가진 툴 답게, Vite는 매우 빠른 개발 환경을 만들어준다. 그렇다면 Vite는 어떤 방법으로 이러한 환경을 만들어주는 걸까?
1. 서버 구동 시간 개선
콜드 스타트 방식으로 개발 서버를 구동하는 경우, 개발 서버를 시작할 때 오랜 시간이 걸리게 된다.
이유는 번들러 기반의 도구의 경우, 앱 내의 모든 소스 코드에 대해 크롤링 및 빌드 작업을 마쳐야지만 실제 페이지를 제공할 수 있기 때문이다.
콜드 스타트 방식은 컴퓨터나 인터넷 서비스가 처음 시작할 때나 오랫동안 사용하지 않았다가 다시 시작할 때의 상태를 말한다.
예를 들어, 인터넷에 연결된 서비스가 처음 켜질 때, 모든 시스템이 준비되고 정상적으로 작동하기까지는 시간이 걸리는 경우가 이에 해당한다고 볼 수 있다.
Vite는 이러한 일련의 과정을 Dependencies, Source code 두 개로 나누어 일을 처리한다.
1) Dependencies
거의 변하지 않는 Plain JavaSciprt 코드이다.
라이브러리 같이 몇 백 개의 JS 모듈을 가지고 있는 것들을 말하는데, 이런 Dependencies에 대한 번들링 과정은 매우 비효율적이고 많은 시간이 소요되었다.
따라서 Vite는 로컬에 사이트를 불러오기 전에 프로젝트의 Dependencies를 사전 번들링(Pre-bundling)한다.
사전 번들링은 Esbuild를 사용하는데, 이 기능은 Webpack, Parcel과 같은 기존의 번들러 대비 속도가 10-100배 더 빠르다.
2) Source code
우리가 자주 바꾸는 Non-plain JavaSciprt 코드이다.
웹 페이지의 실제 내용이라고도 볼 수 있는데, Vite는 이 부분을 필요로 할 때 마다 바로바로 처리한다.
문서를 보면 Vite는 Native ESM을 이용해 소스코드를 제공한다고 적혀있다.
여기서 Native ESM가 정확히 무엇인지와, Vite가 본질적으로 브라우저가 번들러의 작업의 일부를 차지할 수 있도록 한다는 의미가 어떤 것인지 잘 이해가 되지 않아 추가적인 자료를 찾아보았다.
ESM이란?
ESM(ECMAScript Modules)은 모듈화 문법인 import, export를 별도의 도구 없이 브라우저 자체에서 이해할 수 있는 모듈 방식을 의미한다.
// app.js
import { sum } from './math.js';
console.log(sum(10, 20));
<script src="./app.js"></script>
기존의 브라우저에서는 import와 export를 해석할 수 있는 능력이 없었다. 하지만 이제는 script 태그에 아래와 같이 type="module" 속성을 추가하면 정상 동작하는 것을 볼 수 있다.
(이런 방식을 브라우저가 이 방식을 직접 이해하고 처리할 수 있다는 것으로 표현했구나..!)
<script type="module" src="./app.js"></script>
2. 빨라진 소스 코드 갱신
1) ESM을 이용해 수정된 부분만 갱신
이전에는 코드를 일부분만 수정해도 모든 부분을 번들링하는 과정이 필요했다.
따라서 서비스 규모가 커질수록 소스 코드 업데이트 시간 또한 증가하게 되는 문제가 있었다. Vite는 이를 해결하기 위해서 ESM을 이용해, 수정된 모듈과 관련된 부분만 업데이트가 되도록 했다.
2) HTTP 헤더 활용
또한 HTTP 헤더를 활용해서 전체 페이지 로드 속도를 개선했다.
필요에 따라 소스 코드는 304 Not Modified 로, 디펜던시는 Cache-Control: max-age=31536000,immutable을 이용해 캐시된다. 따라서 요청 횟수를 최소화되어 페이지 로딩이 빨라지게 되었다.
304 Not Modified
300번대 코드들은 요청된 자원에 대한 리디렉션을 의미한다. 그 중 304는 'Not Modified'로, 요청한 자원에 대해 변경된 사항이 없으므로 캐시되어있는 자원으로 리디렉션 하겠다는 의미를 갖는다.
즉, 브라우저로부터의 최초 요청 시에는 200번 응답을 받지만 이후에 자원에 변화가 없다면 일정 시간 동안은 304번 응답을 받게된다.
배포 시 번들링 과정이 필요한 이유
앞서 말한 것 처럼 Vite는 로컬에서 개발할 때, 번들링을 하지 않고 ESM 방식을 사용하기 때문에 로컬 서버 구동 속도가 매우 빠르다.
하지만 프로덕션에서는 번들링 되지 않은 ESM을 가져오는 것은, 중첩된 import로 인한 추가 네트워크 통신으로 인해 여전히 비효율적이기 때문에 Vite에서 이를 위한 여러 기능을 제공한다. (빌드 커맨드, 빌드 퍼포먼스 최적화)
번들링 시에 Esbuild를 사용하지 않는 이유
Vite는 현재 Esbuild가 아닌 Rollup을 번들러로 채택하고 있는데, 이유가 무엇일까? 개발 시에는 Esbuild를 사용하는데 말이다.
1. Esbuild
Esbuild에 관련한 글을 대강 훑어보자면, Esbuild는 2020에 등장했지만 아직까지도 메이저 버전이 릴리즈 되지 못했고, (현재 기준 v.0.23.1) 설정이 webpack, rollup 처럼 유연하지 못하며, 아직 안정성 관련 이슈가 있어 그런듯 하다.
2. Rollup
Rollup의 정체성은 '확장'인데, 작은 코드조각들을 거대하고 복잡한 어플리케이션 혹은 라이브러리로 만들어 준다고 스스로를 소개하고 있다.
"compiles small pieces of code into something larger and more complex, such as a library or application"
또 ES6 모듈 형태로 빌드할 수 있는 점, 빠른 속도, 가벼운 번들 생성 등 다양한 장점이 있다.
결론적으로 Vite는 Esbuild의 엄청난 퍼포먼스(JS 기반의 번들러보다 10배에서 100배까지 빠른 속도)라는 장점을 가져가면서, Rollup을 통해 번들링의 유연성을 챙겼다고 보면 될 것 같다.
오늘 Vite가 어떤 빌드 툴인지 알아보면서 흥미로운 시간을 가졌다.
인상 깊었던 것은 하나의 도구로 모든 것을 해결할 수 없다는 것이다. Esbuild, Rollup라는 각 도구의 강점을 적절히 활용해서 빠른 빌드 툴로 거듭나게 된 것이 실제로 우리가 개발할 때의 모습과 유사하다고 느꼈다.
항상 상황을 잘 판단해서 적재적소에 기술을 사용하는 것! 참 중요한 것 같다.
참고
'Language > JavaScript' 카테고리의 다른 글
[JavaScript] 고차 함수와 콜백 함수 (0) | 2024.03.30 |
---|---|
[JavaScript] innerHTML, innerText, textContent 차이점 (0) | 2024.03.27 |
[JavaScript] Rest parameter와 Arguments의 차이 (0) | 2024.03.25 |
[JavaScript] 요소의 속성을 설정하는 방법: setAttribute() (0) | 2024.03.23 |
[JavaScript] 요소의 속성 값을 가져오는 방법: getAttribute() (0) | 2024.03.23 |
- Total
- Today
- Yesterday
- js
- 비제어 컴포넌트
- react
- Next.js
- 리액트
- 제어 컴포넌트
- 프론트엔드
- rest parameter
- 취업까지달린다
- 비동기
- 동기
- 배열
- 유사배열객체
- arguments
- map
- CSS
- Target
- 스프린트프론트엔드6기
- 코드잇스프린트
- html
- 코드잇 스프린트
- currentTarget
- innerhtml
- javascript
- 객체
- Git
- 중급 프로젝트
- GitHub
- hydrationboundary
- tanstackquery
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |