생산성

JavaScript 번들 비대화 원인과 npm 패키지 문제 해결 방법

JavaScript 번들 비대화 원인과 npm 패키지 문제 해결 방법

페이지가 느리다는 건 알겠는데, 정확히 뭐가 느린 건지 모르는 상황. 빌드 결과물이 수십 MB에 달하고, Lighthouse 점수는 빨간불인데 어디서부터 손을 대야 할지 막막하죠. 그리고 이 문제, 2026년 현재 더 심각해지고 있어요.

핵심 요약

  • npm 생태계 패키지 수는 2026년 기준 약 280만 개를 넘었고, 패키지 하나가 의존하는 다른 패키지 수는 중앙값 기준 47개예요 (npm Registry 공식 통계).
  • HTTP Archive의 2025년 Web Almanac 데이터에 따르면, 모바일 기준 중앙값 JavaScript 페이로드는 472KB(gzip 전 기준 약 1.4MB)로 2022년 대비 23% 증가했어요.
  • moment.js, lodash, date-fns 등 흔히 쓰는 유틸리티 라이브러리가 번들 비대화의 핵심 원인으로 지목돼요 — 실제로 tree-shaking이 제대로 안 되는 경우가 절반 이상이에요.
  • webpack, Rollup, esbuild 세 빌더의 번들 크기 차이는 동일 코드 기준 최대 30% 이상 벌어져요.
  • 번들 비대화 문제 해결의 핵심은 도구 교체가 아니라 의존성 감사에서 시작해요.

JavaScript 번들이 커지는 구조적 배경

npm이 처음 등장한 건 2010년이에요. 당시엔 패키지 재사용이라는 개념 자체가 신선했죠. 그런데 지금은요?

npm install 한 번에 수백 개의 패키지가 node_modules 폴더에 쌓여요. 간단한 React 앱 하나를 CRA로 만들면 약 1,300개 이상의 패키지가 설치되고, 디스크 사용량은 300MB를 넘기는 경우가 흔해요. 이게 전부 번들로 들어가는 건 아니지만, 의도하지 않은 코드가 번들에 섞이는 건 훨씬 더 쉬운 일이에요.

문제가 구조적으로 커진 건 크게 세 가지 흐름 때문이에요.

첫째, 패키지 의존성의 깊이가 깊어졌어요. A 패키지가 B를 쓰고, B는 C를 쓰고, C는 또 D를 써요. 이 체인이 깊어질수록 내가 실제로 필요한 기능과 관계없는 코드가 번들에 섞여 들어가요.

둘째, CJS(CommonJS)와 ESM(ES Modules)의 혼재가 문제예요. tree-shaking은 ESM 기반에서만 제대로 작동하는데, npm에 올라온 패키지 중 상당수가 아직 CJS 형식이에요. Bundlephobia 분석(2025년 4분기 기준)에 따르면, 상위 1,000개 패키지 중 약 38%가 여전히 CJS 전용 배포를 해요.

셋째, 편의 우선 개발 문화예요. npm install 한 줄로 기능을 추가할 수 있으니, 10줄짜리 유틸 함수를 직접 짜는 대신 100KB짜리 라이브러리를 통째로 설치하는 경우가 많죠.


번들 비대화의 세 가지 실제 원인

원인 1: 통째로 import하는 라이브러리

번들 크기 문제를 파고들다 보면 가장 먼저 만나는 패턴이에요.

// ❌ 이렇게 쓰면 lodash 전체가 번들에 들어가요 (약 72KB gzip)
import _ from 'lodash';
_.debounce(fn, 300);

// ✅ 이렇게 쓰면 debounce 하나만 들어가요
import debounce from 'lodash/debounce';

moment.js는 더 심각해요. gzip 기준 약 67KB인데, 로케일 데이터가 전부 함께 묶여요. 한국어 하나만 필요한데 40개 언어 데이터가 번들로 들어가는 거예요. Bundlephobia 기준 date-fns는 동일 기능 대비 약 75% 더 가볍고, tree-shaking도 잘 돼요.

원인 2: 중복 패키지 버전 충돌

프로젝트 규모가 커지면 같은 패키지의 여러 버전이 동시에 설치되는 경우가 생겨요. react-query v4v5가 함께 들어가거나, lodash 4.17.154.17.21이 동시에 존재하는 상황이요.

npm ls --depth=0이나 npx depcheck 명령어로 이 상태를 바로 확인할 수 있어요. 실제 프로젝트 감사 사례를 보면, 중복 버전 제거만으로 번들 크기를 15~20% 줄이는 경우가 드물지 않아요.

원인 3: 개발 전용 코드가 프로덕션 빌드에 섞이는 경우

process.env.NODE_ENV 체크가 제대로 안 되면 개발 모드 경고 코드, 디버깅 유틸, 테스트 픽스처가 프로덕션 번들에 통째로 들어가요. React 자체도 개발 빌드와 프로덕션 빌드의 크기 차이가 약 두 배예요 — 개발 빌드 기준 약 140KB gzip, 프로덕션은 약 45KB.


번들러별 비교: 어떤 도구가 더 잘 걸러낼까

빌더 선택은 생각보다 큰 변수예요.

기준webpack 5Rollupesbuild
기본 번들 크기중간가장 작음중간
tree-shaking 정확도좋음최상보통
빌드 속도느림중간매우 빠름
CJS 패키지 처리자동 변환플러그인 필요자동 변환
코드 스플리팅최상좋음제한적
적합한 상황복잡한 앱라이브러리 배포빠른 빌드 우선

Rollup이 tree-shaking에서 우위를 보이는 이유는 초기 설계 자체가 ESM 기반이기 때문이에요. webpack은 플러그인 생태계가 넓고 코드 스플리팅 제어가 세밀한 대신, 번들 크기 최적화에는 별도 설정이 많이 필요해요.

esbuild는 빌드 속도가 압도적이에요 — Go 언어로 짜여 있어서 webpack 대비 수십 배 빠르지만, 복잡한 tree-shaking 시나리오에서는 다소 보수적으로 동작해요. Vite는 내부적으로 esbuild(개발 서버)와 Rollup(프로덕션 빌드)을 조합하는 방식으로 두 장점을 절충하는 구조예요.


지금 당장 실행할 수 있는 감사 순서

한 번에 다 고치려다 더 복잡해지는 경우가 많아요. 단계별로 접근하는 게 훨씬 효과적이에요.

1단계 — 번들 가시화 (1시간 이내)

webpack-bundle-analyzer 또는 rollup-plugin-visualizer를 붙이면 어떤 패키지가 얼마나 차지하는지 한눈에 보여요. 보통 이 단계에서 “이 패키지가 이렇게 큰 줄 몰랐다"는 발견이 나와요.

2단계 — 대체재 조사 (Bundlephobia 활용)

bundlephobia.com에서 현재 쓰는 패키지 이름을 검색하면 gzip 크기, tree-shaking 지원 여부, 가벼운 대체재까지 바로 알려줘요. momentday.js(약 2KB gzip), lodashradash나 직접 구현 등 교체 경로가 명확해요.

3단계 — Dynamic import 도입

초기 로딩에 필요없는 코드는 나중에 불러오는 패턴이에요.

// 버튼 클릭 시점에 차트 라이브러리를 불러와요
const { Chart } = await import('chart.js');

이 패턴 하나로 초기 번들을 20~30% 줄인 사례가 많아요. 대시보드나 관리자 페이지처럼 특정 기능이 조건부로 사용되는 경우에 특히 효과가 커요.

4단계 — CI에 번들 크기 검사 추가

bundlesize 또는 size-limit 패키지를 CI 파이프라인에 붙이면, PR마다 번들 크기 변화를 자동으로 리포팅해요. 인지하지 못한 사이에 번들이 커지는 걸 사전에 차단하는 구조예요. Vercel, Netlify 모두 이 훅을 공식 지원해요.


앞으로 6-12개월, 뭘 주시해야 할까

번들 비대화 문제는 도구 문제가 아니라 습관과 감시 체계 문제예요.

  • ES2025 top-level await와 모듈 페더레이션 확산으로 런타임 번들 분리 패턴이 더 일반화될 거예요.
  • npm 7+의 workspaces 기능이 성숙해지면서 모노레포에서의 중복 패키지 문제가 줄어들 가능성이 있어요.
  • Bun의 번들러 기능이 안정화 단계에 접어들고 있어서, 2026년 하반기엔 esbuild의 강력한 경쟁자가 될 수 있어요.

지금 당장 webpack-bundle-analyzer 하나만 붙여도 번들의 절반은 이미 설명이 돼요. 어떤 패키지가 가장 먼저 눈에 들어오던가요? 그 패키지가 정말 필요한 건지, 아니면 편의상 설치된 건지 — 거기서 시작하면 돼요.

참고자료

  1. Use npm Packages in the Browser with Browserify
  2. Windows 환경에서 ait build 시 TypeScript loader ParseError 발생 - 개발 - 앱인토스 개발자 커뮤니티
  3. How to Install Claude Code in 2026: Complete Guide for Mac, Windows & Linux | LaoZhang AI Blog

Photo by HackerNoon on Unsplash