Rollup.js - 번들링, 파일을 하나로 합쳐보자
번들링 이라는 말을 프론트엔드 개발자라면 많이 들어보셨을겁니다. 번들링은, 파일을 하나로 묶는 것을 말합니다. 그럼 왜 굳이 파일을 하나로 묶어야 할까요? 바로 HTTP 통신의 특성 때문입니다.
단발성으로 리소스를 요청하는 HTTP 특성상, 요청할 파일이 많으면 그만큼 요청을 많이 보내야해서 비효율적입니다. 그래서 번들링해서 파일을 하나로 묶으면 요청 횟수가 적어지니 효율적이겠죠.
그만큼 프론트엔드에서 번들링은 정말 중요합니다. 사용자가 우리의 웹사이트를 방문했을 때, 최대한 빠르게 웹 페이지를 보여줘야하기 때문입니다.
그럼 번들링은 어떻게 해야할까요? 바로 번들러라는 녀석을 이용하면 됩니다. 대표적으로 Webpack이 있습니다. 예전과 다르게 웹팩이 많이 개선되어서, 설정 없이도 간단한 번들링은 쉽게 가능합니다.

위 그림은 웹팩이 가장 왼쪽 위에 위치한 최초 진입점인 .js 파일을 읽어서, 그 파일이 참조 하고 있는 다른 여러 형식들의 파일들을 하나로 묶어 최종적으로 js, css, jpg, png로 만든다는 과정을 설명한 그림입니다. 이해가 안가셔도 됩니다. 그냥 최초 진입점이 될 파일 1개를 선택한다는 것만 알아두시면 됩니다.
그리고 번들러를 사용해야하는 큰 이유가 있습니다. 번들러는 이제 단순히 번들링만 하는 게 아니라, 용량 압축과 구형 브라우저 지원, Polyfill 등 하나로 묶는 것 등 굉장히 많은 이점과 편의성을 가져다줍니다.
거의 대부분 Webpack을 많이 사용하지만, 더욱 빠른 성능이나 Zero configuration을 강조한 후발 주자들도 많이 있습니다.
Rollup, Parcel, Esbuild 정도가 있습니다.
이번 포스팅에서는 Rollup을 이용해 번들링에 대해 간단하게 알아보겠습니다.
프로젝트 구성
먼저 프로젝트를 생성하고, 초기화해줍니다.
$ mkdir project && cd $_
$ yarn init -y
rollup을 사용하기 위해 패키지를 설치합니다. 이번 포스팅에선 faker.js도 같이 사용할 예정입니다.
$ yarn add -D rollup
$ yarn add faker
프로젝트를 번들링하기 위해 최초 rollup이 읽어들어야 할 파일이 있어야겠죠. 저는 src 디렉토리 아래에 main.js 파일과 faker.js 파일 2개를 만들도록 하겠습니다.
$ mkdir src
$ touch src/main.js
$ touch src/faker.js
여기까지 구성하셨다면 프로젝트의 구조는 다음과 같습니다.
project
|- node_modules/
|- src/
|-- main.js
|-- faker.js
|- package.json
|- yarn.lock
모듈 작성하기
자 그러면 진입점이 될 파일인 main.js를 작성하기 전에, faker.js을 이용해서 랜덤한 이름을 만들어주는 우리의 모듈(함수)부터 만들어보도록 하겠습니다.
import faker from "faker";
export const GenerateName = () => {
return faker.name.findName();
};
방금 만든 모듈을 이용해서 main.js를 구성해보도록 하겠습니다.
import { GenerateName } from "./faker";
function Init() {
const name = GenerateName();
console.log(`name: ${name}`);
}
Init();
이상으로 프로젝트를 실행시킬 때 마다 이름을 랜덤으로 출력해주는 간단한 모듈을 만들어보았습니다.
번들링하기
맨 처음 설명드린 것처럼, 번들러는 다수의 파일을 하나의 파일로 묶어주는 역할을 한다고 했습니다. 이 말에 따르면 우리의 프로젝트는 현재 2개의 파일로 분리되어 있지만, 결과는 1개의 파일로 나와야합니다.
커맨드라인 인터페이스를 이용하면 아주 간단하게 번들링을 할 수 있습니다. cli를 이용하기위해 package.json 내부에 scripts를 추가해주도록 합시다.
{
"scripts": {
"build": "rollup src/main.js --file dist/main.js"
}
}
옵션에 대한 설명은 두 번째 자리에 진입점이 될 파일을 넣고, --file 옵션에는 번들링된 결과 파일 명을 적어주면 되겠습니다.
프로젝트 내부에만 rollup을 설치했기 때문에 명령어를 터미널에 직접치면 작동하지 않습니다. 터미널에서도 실행시키고 싶다면
$ yarn add global rollup으로 설치해주세요.
그럼 이제 우리의 모듈을 번들링합시다.
$ yarn build
# log
$ rollup src/main.js --file dist/main.js
src/main.js → dist/main.js...
(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
faker (imported by src/faker.js)
created dist/main.js in 43ms
✨ Done in 0.45s.
성공적으로 번들링되었습니다! 현재는 경고가 하나 뜨는걸로 보이는데, 일단은 결과 파일을 살펴보도록 하겠습니다.
import faker from "faker";
const GenerateName = () => {
return faker.name.findName();
};
function Init() {
const name = GenerateName();
console.log(`name: ${name}`);
}
Init();
분리되어있던 faker.js 파일의 코드들이 main.js에 합쳐져있음을 확인할 수 있습니다.
우리의 모듈이 잘 동작하는지 테스트를 위해 package.json에 스크립트를 추가합시다.
{
"scripts": {
"build": "rollup src/main.js --file dist/main.js",
"start": "node dist/main.js"
}
}
$ yarn start
# log
import faker from 'faker';
^^^^^^
SyntaxError: Cannot use import statement outside a module
import 구문을 사용할 수 없다는 오류가 출력되고 있습니다. 이 부분은 rollup의 문제는 아니고, node에서 최신 자바스크립트 문법을 해석할 수 없기 때문에 발생하는 오류입니다.
감사하게도 번들링 과정에서 최신 자바스크립트 문법을 node에서 해석할 수 있도록 바꿔주는 옵션이 있습니다. package.json를 수정합시다.
{
"scripts": {
"build": "rollup src/main.js --file dist/main.js --format cjs"
}
}
수정한 뒤 결과 파일을 다시 살펴보도록 하겠습니다.
// dist/main.js
"use strict";
var faker = require("faker");
function _interopDefaultLegacy(e) {
return e && typeof e === "object" && "default" in e ? e : { default: e };
}
var faker__default = /*#__PURE__*/ _interopDefaultLegacy(faker);
const GenerateName = () => {
return faker__default["default"].name.findName();
};
function Init() {
const name = GenerateName();
console.log(`name: ${name}`);
}
Init();
이것 저것 코드가 많이 추가되었는데 다시 테스트 해보도록 하겠습니다.
$ yarn start
# log
$ node dist/main.js
name: Cesar Greenholt
✨ Done in 0.72s.
잘 작동하는걸 확인할 수 있습니다!
그냥 넘어가기 전에 포맷에 대한 간략한 설명입니다. --format 옵션에는 몇 가지가 있는데, node에서 사용하는 모듈이라면 cjs를 사용하면 되고, 브라우저에서 사용한다면 iife, 둘 다 사용하고 싶다면 umd 옵션을 주면 됩니다.
"무조건 umd로 하면 되겠네" 라고 생각하실 수 있지만, 당연히 번들링된 파일의 크기가 커집니다. 파일이 불필요하게 커지지 않도록 각 사용 환경에 맞게 구성하시면 되겠습니다.
Tree shaking
번들링을 하면서 얻을 수 있는 큰 장점 중 하나는 내 프로젝트가 가져오는 외부 모듈들이 아주 많을텐데, 그 중에 실제로 사용되는 코드들만 번들링 결과물에 포함시켜준다는 점입니다.
이를 Tree shaking이라고 합니다. 예시를 보도록 합시다.
// src/faker.js
import faker from "faker";
export const GenerateName = () => {
return faker.name.findName();
};
export const Test = () => {
return "Some string";
};
기존에 작성했던 faker.js 파일에 Test() 함수를 추가해서 내보내도록 했습니다.
main.js
import { GenerateName, Test } from "./faker";
function Init() {
const name = GenerateName();
console.log(`name: ${name}`);
}
Init();
그리고 Test 함수를 가져오도록 코드를 추가하고 번들링을 해보면 Test 함수가 포함되어 있어야 할 것 같지만, 모듈을 가져오는 부분에서 실제로 사용하진 않고 있기 때문에 결과물에 포함시키지 않습니다.
이러한 부분은 기능이 많은 다른 모듈들을 가져올 때 굉장한 도움이 됩니다.
rollup.config.js
번들러를 사용하다보면 CLI 설정 옵션이 너무 길어지는 상황이 발생합니다. 그리고 한 줄에 모두 작성해야하기 때문에 보기에도 좋지 않습니다. 또 번들링 환경에 따라 다른 결과 파일을 만들어내야할 수 도 있습니다.
그런 몇몇 상황들을 충족시키기 위해 자바스크립트 파일로 번들링 옵션을 설정할 수 있도록 기능을 제공하고 있습니다.
package.json 파일을 수정합시다.
{
"scripts": {
"build": "rollup -c"
}
}
코드가 많이 짧아졌습니다.
-c 뒤에는 설정 파일 경로를 넣어주면 되는데, 설정하지 않는다면 프로젝트 루트 디렉토리의 rollup.config.js 파일을 찾도록 되어있습니다. 이것도 같이 구성하도록 하겠습니다.
$ touch rollup.config.js
export default {
input: "src/main.js",
output: {
dir: "dist",
format: "cjs",
},
};
이렇게 구성해주면 원래 작성했던 cli 코드와 설정이 같아집니다. 테스트를 위해 yarn build를 이용해 번들링해보면 이전과 같은 결과가 나옵니다.
마무리
여기까지 다룰 수 있다면 다른 node 프로젝트에서 가져다 사용하기 위해 npm에 배포하는 데 큰 어려움은 없지만, rollup에 호환되지 않는 포맷으로 작성된 모듈들을 가져다가 사용하면서 생기는 문제가 있을 수 있습니다. 또 타입스크립트로 작성하고 싶거나, 공백까지도 모두 지워버려서 파일 크기를 최대한으로 줄이고 싶다거나 한다면 플러그인을 사용해야 합니다.
2부에서는 이러한 문제를 아주 쉽게 해결할 수 있는 플러그인에 대해서 알아보도록 하겠습니다.
같은 카테고리의 다른 글
[Nuxt 3] Composition API로 자동 스크롤링 기능 구현하기
이번 포스팅에서는 실시간 채팅 서비스에서 새로운 대화 내용이 추가되었을 때 자동으로 스크롤이 계속해서 아래로 내려가면서, 스크롤을 조작함에 따라 자동 스크롤이 활성화/비활성화되는 기능을 Vue 3에서 새로 추가된 Composition API를 통해 만들어볼겁니다.
Twilio 번호 구매 없이 연락처 인증 서비스 5분만에 구현하기
이번 포스팅에선 Twilio를 이용해 Node.js에서 개인 번호를 발급받지 않고, 핸드폰 번호 인증을 매우 간단하게 구현하는 방법에 대해 소개해드리겠습니다.
[Nuxt 3] 사이드 프로젝트 만들기 - 개발 환경 설정편
저번 사이드 프로젝트 만들기 - 기획편의 다음 편입니다. 이번엔 nuxt3의 주요 변경사항 일부를 알아보고, 쾌적한 개발 환경을 위해 몇 가지 세팅을 해보도록 하겠습니다.
[Nuxt 3] 사이드 프로젝트 만들기 - 기획편
올해 첫 개발 관련 주제를 뭘로할까 고민하다가 사이드 프로젝트 아이디어가 떠올라서 그걸 같이 만들어볼까 합니다. 하지만 이미 잘 알고 있던 기술을 사용해서 만들면 재미없겠죠. 사이드 프로젝트는 역시 신기술을 이용해서 만드는게 가장 좋습니다. 나만의 프로젝트를 만들면서 최신 기술도 마음껏 써볼 수 있으니까요.
평생 무료로 반응형 이메일 템플릿 무한대로 만들기 - mjml.io
저는 이메일을 데스크톱과 모바일 환경에서 매일매일 확인합니다. 그런데 아직도 모바일 디스플레이에 최적화되지 않은 이메일을 받을 때가 많습니다.
평생 무료로 커스텀 이메일 사용하기
안녕하세요. 또 다시 찾아온 평생 무료 시리즈입니다. 저는 틈만나면 1인 사이드 프로젝트를 진행하기 때문에, 어떻게든 공짜로 서버를 돌리기 위해 온갖 노력을 하고 있습니다. 그래서 무료로 이용하는 방법에 관한 글을 몇 개 올렸는데 GA를 살펴보니 다른 주제보다 조회수가 높더군요. 역시 공짜가 좋네요.
클립보드 이미지를 1초만에 링크로 만드는 툴 개발하기
저는 이 블로그를 운영하면서 가장 귀찮은 일이 하나 있습니다. 바로 이미지 주소를 만드는 일인데요, 저는 @nuxt/content 모듈을 이용해 마크다운 포맷을 이용하는 정적 블로그를 운영 중이라 글 작성 중에 원격 이미지 주소를 삽입하는 기능을 사용하지 않습니다.
평생 무료인 모니터링 도구 10분만에 만들기
서버를 운영하다보면 예상치 못한 서버 다운이나 응답 속도 저하를 반드시 겪게 됩니다. 원인은 둘째 치구요. 근데 문제는 서버 장애를 원천 차단할 방법이 사실상 없기 때문에, 우리 개발자들이 24시간 눈을 뜨고 지켜볼 수 밖에 없겠습니다.
Vue.js로 크롬 확장 프로그램 만들기 강의 - 3부
이전 포스팅에서는 Vite을 이용해 크롬 확장 프로그램을 만들기 위한 기본적인 프로젝트 환경 설정까지 마쳤습니다. 본격적으로 Vue.js 코드를 작성해보도록 합시다.
정말 너무 쉬운 Docker
우리가 Docker를 사용해야하는 가장 큰 이유는, 어떤 컴퓨터에서든 똑같은 개발 환경을 보장해주기 떄문입니다. 로컬 컴퓨터에서 열심히 개발하고 AWS에 코드를 올렸는데, 에러를 마주하며 스트레스를 받았던 경험이 한 번쯤은 있을겁니다. 내 컴퓨터랑 클라우드 컴퓨터의 환경이 100% 똑같지 않기 때문이죠. 근데 이 어려움을 한 번에 해결해준다? 쓰지 말아야 할 이유가 없습니다.
웹소켓과 socket.io
예전에 회사 프로젝트를 진행할 때, 지도에 실시간으로 사용자의 위치를 보여주는 기능이 필요해서 socket.io 를 사용해서 구현했던 적이 있습니다.
Vue.js로 크롬 확장 프로그램 만들기 강의 - 2부
이전 포스팅에서 index.html과 manifest.json 파일을 이용해서 확장 프로그램을 개발자 모드로 실행시키는 것 까지 진행했습니다.
Vue.js로 크롬 확장 프로그램 만들기 강의 - 1부
제가 최근 우연히 크롬 확장 프로그램을 개발했는데, 이게 생각보다 꽤 괜찮은 시장이라는 걸 알게 되었습니다.
웹팩보다 100배 빠른 번들러, esbuild
이번 포스팅은 떠오르는 차세대 자바스크립트 번들러 esbuild에 대한 내용입니다. 작년 Github에서 떠오르는 번들링 프로젝트 중 1위를 차지했고, 오늘을 기준으로 20만개의 가까운 Github Star를 받았습니다.
Rollup.js - 플러그인으로 완성도를 높이다
지난 포스팅에서 rollup.js 를 이용해 두 개의 자바스크립트 파일을 하나로 묶고, rollup.config.js 파일을 구성해서 CLI가 아닌 스크립트로 설정 파일을 관리하는 것 까지 진행했습니다.
코인 시세 1초만에 보는 크롬 확장 프로그램 만들기
가상화폐 거래소 API를 활용해 브라우저에서 단축키로 빠르게 코인 시세를 확인할 수 있는 툴을 크롬 확장 프로그램으로 만들어보았다.
평생 무료로 개인 블로그 운영하기
거의 대부분의 개발자들이 개인 블로그를 운영하라고 얘기한다. 나도 그렇게 생각한다. 왜냐면 분명히 내가 작성했던 코드인데도, 일주일만 지나도 기억이 안나기 때문이다. 그리고 웬만하면 공개해서 작성하라고 하고 싶다. 이미 우리는 누군가가 옛날에 썼던 글을 보고, 문제를 해결한 경험히 굉장히 많기 때문이다. 나는 이런 개발자들의 문화가 너무 좋다. 이런 개발자들의 문화가 다른 업종에도 접목된다면 정말 좋으련만.
Firebase를 대체할 오픈소스 프로젝트, Supabase
Supabase는 구글 Firebase를 엔터프라이즈 레벨에서도 사용 가능하도록 만든 오픈소스 프로젝트이다. 현재는 베타 서비스이다.