"번들링은 브라우저 한계의 우회책으로 시작. 2026 엔 브라우저가 따라잡고 — '기본 번들' 이 요구사항 아닌 습관 됨."
왜 번들링이 존재했지
2010 년대엔 브라우저가 ES 모듈 네이티브 로드 못 했어. 모든 import 문이 별도 네트워크 round-trip; 작은 모듈 100 개면 페이지 로드마다 request 100 개. 번들러 (webpack, browserify, 그 다음 Rollup, esbuild, swc, Vite, Turbopack) 가 이걸 풀었어:
- Import 그래프 정적 walk.
- 모든 모듈을 적은 출력 파일들로 concatenate.
- Minify, 죽은 코드 tree-shake, 옛 브라우저용으로 새 문법 lower.
브라우저 출하용엔 여전히 유용 (HTTP/2 도움, HTTP/3 가 더 도움 — 근데 tree-shaking 은 여전히 진짜). 서버 사이드 Node 코드엔? 대부분 cargo cult.
서버 사이드 Node 는 번들링 안 필요
그런데 대부분 TypeScript Node 서비스가 어쨌든 번들해, 보통 템플릿이 그래서. 비용: dev 의 빌드 단계, CI 의 빌드 단계, 디버그용 source map, 런타임이 이미 문법 이해해도 transpile pass (Node 22+ 가 모던 JS 네이티브 실행; "옛 Node 위한 transpile" 안 필요).
2026 Node 서비스엔: 그냥 소스 실행.
node --experimental-strip-types --env-file=.env server.ts. 빌드 없음, 번들 없음, source map 없음, 문제 없음.Node 에 여전히 번들할 때
- Single-executable apps (SEA) — SEA 입력으로 한 파일에 번들 원함. esbuild 또는 bun build 가 이거에 좋음.
- FaaS 배포 (AWS Lambda, Vercel Functions) — 큰 디렉토리에 deploy target 의 cold-start 페널티; 번들링이 줄임. 일부 프레임워크 (Next.js) 가 내부적으로 함.
- CLI 를 단일 파일로 배포 — 사용자가
npx your-cli, npm 에서 번들된 한 파일 받음, 네 풀 transitive 트리 안 끌어옴. - 무거운 라이브러리 tree-shake —
lodash의 20% 만 쓸 때, 번들러가 손댄 import 만 유지 가능. 모던 Node 는 로컬 디스크에서 tree-shake 안 함.
이 중 아무것도 적용 안 되면 번들러 안 필요할 거야. 소스 실행. 빌드 시간 절약.
Frontend 는 달라 — 거기선 번들링 건너뛰지 마
브라우저 코드엔 번들링 살아있어 — 근데 tooling 이 더 빨라. Vite 가 dev 를 unbundled 서빙 (브라우저에 native ESM + 즉석 변환), 프로덕션엔 번들 빌드 생성. esbuild 와 swc 가 webpack 이 몇 분 걸리던 transpile-then-bundle 을 초 안에 처리. 2026 프론트엔드 stack: dev 엔 Vite, 프로덕션 빌드엔 Vite-or-equivalent, underlying 컴파일러로 esbuild/swc.
Node + Frontend Monorepo Setup
흔한 2026 레이아웃:
apps/web— frontend, Vite/Next.js 사용, 프로덕션 번들.apps/api— Node 백엔드,node --experimental-strip-types로 소스 직접 실행, 번들 없음.packages/shared— 둘 다 쓰는 TypeScript 유틸리티,workspace:통해 참조, 타입 체크되지만 빌드 안 됨.
Frontend 는 브라우저가 필요로 해서 빌드 단계 있음. 백엔드는 없음. 공유 패키지는 둘 다 안 필요. 각 표면이 맞는 거 써, "세상 빌드" 세금 없음.