[번들러] Vite

이윤우·2023년 4월 4일
0

번들러

목록 보기
1/1
post-thumbnail

번들러

1) 번들러 등장 배경

과거에는 스크립트를 직접 HTML 파일에 삽입하는 방식으로 개발하였습니다. 이러한 방식은 코드의 모듈화와 의존성 관리가 어려웠습니다. 모듈간에 변수가 겹쳐 충돌이 발생할 수도 있고 이 때문에 어떤 모듈을 먼저 로드해야 하는지 로드 순서에도 신경을 써야 했습니다.

2008년엔 브라우저 외부에서도 JavaScript를 실행시킬 수 있는 Google의 V8 엔진(Node.js)이 공개되면서 모듈화에 대한 필요성이 부각되면서 CommonJS가 등장하게 되었습니다. 서버 프로그래밍의 특성상 코드를 미리 만들어주고 파일에서 코드를 동적으로 불러와도 상관없었지만 브라우저의 경우는 js파일을 저장하지 못하고 매번 불러와야 했기 때문에 언제나 로딩과 비동기를 고려해야 했습니다. (스크립트는 순서대로 실행해야 하는데 누가 먼저 로딩될지 모르기 때문)

그래서 비동기가 가능하게 하는 AMD라는 방식을 가지고 브라우저에서 돌아가는 모듈방식을 만들어서 프로그램의 덩치가 커질 수 있도록 제공하였습니다. 하지만 이 방식은 여러 파일을 로딩하도록 만들었고 순서를 맞춰야 했습니다. 브라우저 특성상 js 파일을 잘게 동시에 여러파일을 호출하게 되면 속도 문제가 발생하고 특정 js파일의 로딩이 지연되면 전체가 지연되는 등의 문제가 있어 역시 널리 쓰이지 않게 되었습니다.

여러개 파일을 비동기로 로딩하는 것이 문제라면 그냥 처음부터 파일을 하나로 합쳐서 전달하는 아이디어가 나오게 되었고 그 역할을 하는 것이 바로 번들러입니다.

2) 번들러의 문제점

번들러는 기존 모듈 방식의 문제점을 해결할 수 있었지만 느린 빌드 속도가 문제였습니다. 기존에는 JS를 작성하면 바로 브라우저에서 실행이 가능했지만 이제는 모든 파일들을 하나로 만들어주는 작업을 선행 해야 했기에 수정을 할 때마다 매번 새롭게 빌드가 필요했고 이 빌드속도가 느렸기 때문에 코드를 수정하는대로 즉시 반영된다는 장점이 많이 퇴색되었습니다.

3) esbuild


기존 빌드 속도보다 100배나 빠른 빌드도구가 탄생하게 되었습니다. 기존 번들러와 달리 go 언어로 작성되어 스크립트 기반의 느린 js가 아니라 native의 최대한의 기능을 이용해서 훨씬 더 빠른 빌드가 가능하도록 만들었습니다.

하지만 많은 사람들이 사용하는 번들러인 webpack은 단순한 빌드 도구가 아니었습니다. DevServer, 각종 Loader를 통한 트랜스 파일, 코드 스프리팅, 트리셰이킹, HMR, CSS, HTML, asset 지원 등 빌드도구를 넘어서서 개발을 할 수 있게 해주는 통합 툴이었지만 esbuild는 단순한 빌드도구이기 때문에 많이 쓰이지 않았습니다.

4) snowpack

esbuild로 빌드하고 브라우저의 표준방식으로 개발은 하고 production을 만들기 위해서는 기존 번들툴로 결과물을 만들어내는 방식의 snowpack이 출시되었습니다. 어차피 개발을 하는 동안에는 완성된 코드가 아니라 빠른 수정반영이 중요했기 때문입니다.

Vite

Multi-Page App

아래와 같은 구조의 소스 코드를 갖오 있다고 가정해봅시다.

├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
    ├── index.html
    └── nested.js

개발 시, /nested/ 디렉터리 아래에 있는 페이지는 간단히 /nested/로 참조가 가능합니다. 일반적인 정적 파일 서버와 다르지 않습니다.

빌드 시에는, 사용자가 접근할 수 있는 모든 .html 파일에 대해 아래와 같이 빌드 진입점을 명시해줘야만 합니다.

// vite.config.js

import { resolve } from 'path'
import { defineConfig } from 'vite'

export default defineConfig({
	build: {
    	rollupOptions: {
        	input: {
            	main: resolve(__dirname, 'index.html'),
              	nested: resolve(__dirname, 'nested/index.html')
            }
        }
    }
})

상대경로

export default defineConfig({
	base: './', // 상대경로 지정
})

0개의 댓글