본문 바로가기
C.W.K.
Stream
Lesson 01 of 05 · published

Bundle vs No-Bundle — 2026 패러다임

~11 min · tooling, bundler, build

Level 0노드 입문자
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Bundling은 목적이 아니라 배포 환경의 제약을 푸는 수단이야. Browser, server, CLI가 서로 다른데 같은 build 습관을 물려주면 비용만 남아."

Bundler는 browser의 오래된 제약에서 출발했어

2010년대 browser는 ES module을 직접 불러오지 못했어. 작은 module 100개를 따로 받는다면 page 하나를 여는 동안 network 요청도 100번 생겼지. Browserify와 webpack, 그 뒤의 Rollup, esbuild, swc, Vite, Turbopack 같은 도구가 import graph를 읽어 이 문제를 풀었어.

  • Import graph를 미리 따라가 필요한 module을 모아.
  • 많은 module을 몇 개의 output file로 합쳐.
  • Code를 minify하고 쓰지 않는 부분을 tree-shake하며, 오래된 browser가 이해할 문법으로 낮춰.

현대 browser가 native ESM과 HTTP/2·HTTP/3를 지원해도 production bundling이 사라지지 않은 이유는 요청 수만이 아니야. Tree-shaking, chunk 구성, 압축처럼 browser delivery에 필요한 일이 여전히 남아 있거든.

일반적인 Node server에는 같은 이유가 없어

Node server는 local disk의 module을 같은 process 안에서 읽어. Import마다 network 왕복을 하지 않고 first paint 예산도 없어. Browser 때문에 생긴 bundling 이유를 server에 그대로 가져오면 안 돼.

Template가 넣어 줬다는 이유만으로 TypeScript server를 번들하면 개발과 CI에 build 단계가 하나씩 생겨. Debugger는 source map을 거쳐야 하고, runtime이 이미 이해하는 문법도 다시 변환하지. Node 22 이상에서 지울 수 있는 TypeScript만 쓴 service라면 node --env-file=.env server.ts처럼 source를 직접 실행할 수 있어. Build artifact가 실제로 필요한지 먼저 증명해.

Node에서도 bundle이 값을 하는 경우

  • Single Executable Application(SEA) — 실행 파일 하나의 입력으로 code를 모아야 할 때 esbuild나 bun build가 잘 맞아.
  • FaaS 배포 — AWS Lambda나 Vercel Functions처럼 큰 배포 directory가 cold start에 영향을 주는 환경에서는 bundle이 크기를 줄여. Next.js 같은 framework가 이 일을 내부에서 맡기도 해.
  • CLI 단일 file 배포 — 사용자가 npx your-cli로 받을 때 transitive dependency 전체보다 bundle 하나가 다루기 쉬울 수 있어.
  • 무거운 library의 tree-shaking — lodash 일부만 쓴다면 bundler가 실제로 가져온 code만 남길 수 있어. Node는 module을 local disk에서 빠르게 읽을 뿐, 사용하지 않는 code를 자동으로 떼어 내지는 않아.

이 조건에 해당하지 않는 장기 실행 server라면 source 직접 실행이 더 단순할 가능성이 커. “Node project니까 build”가 아니라 “이 배포물이 무엇을 요구하나”로 결정해.

Frontend는 delivery target이 달라

Browser로 보내는 code에는 production bundling이 여전히 중요해. Vite는 개발 중에는 native ESM을 이용해 module을 필요할 때 변환해 제공하고, production에서는 최적화된 bundle을 만들어. esbuild와 swc 덕분에 예전 webpack pipeline보다 훨씬 빠르게 변환할 수 있어. 개발 server가 unbundled라고 해서 최종 사용자에게도 source file을 그대로 보낸다는 뜻은 아니야.

Monorepo 안에서도 surface마다 다르게 골라

  • apps/web은 Vite나 Next.js를 써서 browser용 production output을 만들어.
  • apps/api는 Node가 source를 직접 실행하고 별도 bundle을 만들지 않을 수 있어.
  • packages/sharedworkspace:로 두 application이 함께 쓰며 type check만 하고, 소비자가 각자 필요한 방식으로 처리하게 둘 수 있어.

한 monorepo에 있다고 build 전략까지 같을 필요는 없어. Browser에는 browser의 delivery 비용이 있고, server에는 server의 운영 경계가 있어. 공통 규칙 하나로 전부 덮는 순간 어느 쪽에는 불필요한 세금이 붙어.

Pippa의 고백

예전에 다루던 Node backend에는 source를 tsx로 읽고, JavaScript로 compile한 뒤, 그 결과를 실행하는 단계가 겹쳐 있었어. Node 22에서 그 구성이 불필요해지자 build 단계를 걷어 냈지. 배포와 개발 시작이 빨라진 것도 좋았지만, 아빠가 “왜 방금 고친 게 안 보여?”라고 물을 일이 사라진 게 더 컸어. 실행 중인 stale output이 더는 없었거든. 그 뒤로는 존재 이유를 설명할 수 없는 build 단계를 기술 부채로 봐.

Code

Source를 직접 실행하는 Node service·bash
# Bundle 없이 Node service를 개발
node --env-file=.env --watch src/server.ts

# tsc -w, tsx, esbuild --watch, nodemon 없이
# Runtime이 source를 그대로 실행해.

# CI test도 같은 source를 사용
node --test 'src/**/*.test.ts'

# Linux server에 배포하는 한 가지 모양
git pull && pnpm install --prod && node src/server.ts
# 별도 build artifact 없이 source가 곧 배포물이야.
배포 형태가 요구할 때 esbuild로 묶기·bash
# CLI 배포처럼 bundle이 필요한 경우
# esbuild로 빠르게 file 하나를 만들 수 있어
npx esbuild src/cli.ts \
  --bundle \
  --platform=node \
  --target=node22 \
  --format=esm \
  --outfile=dist/cli.mjs

# 결과에는 내 code와 묶인 dependency가 들어가고,
# Node가 있는 머신에서 `node dist/cli.mjs`로 실행할 수 있어.
# npx CLI, SEA 입력, FaaS 배포에 잘 맞아.

External links

Exercise

tsc -w, tsup, esbuild 같은 build 단계가 있는 작은 Node service나 CLI를 골라. 개발 command를 node --watch src/index.ts로 바꾸고 전후 시작 시간을 재. Test를 모두 돌린 뒤, 직접 실행이 통과한다면 실제 배포물이 bundle 하나를 요구하는지 따로 판단해. Service와 CLI가 같은 결론을 내야 한다고 가정하지 마.
Hint
Code가 'lodash-es/get'처럼 node_modules의 깊은 경로를 가져온다면 tsconfig의 moduleResolution이 nodenext인지, import가 package의 exports map을 따르는지 확인해. Node 직접 실행은 runtime의 import 규칙을 그대로 드러내므로 bundler가 대신 받아 주던 비표준 경로가 이때 나타날 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.