View

728x90
반응형

프론트엔드 개발을 조금이라도 해봤다면 웹팩(Webpack)이라는 단어를 한 번도 들어보지 못한 사람은 없을 것이다. 다만 정작 "왜 이것을 쓰는지", "누가 만든 것인지" 제대로 설명할 수 있는 사람은 의외로 적다. 나도 예전에는 npm run build를 치면 무언가 알아서 돌아가는 마법 상자 정도로만 알고 있었다.

 

이 글은 웹팩 사용 이유를 6가지로 정리하고, 독일 개발자 Tobias Koppers가 어떻게 이것을 만들게 되었는지, 그리고 Vite와 Turbopack이 치고 올라오는 2026년 시점에서 웹팩이 아직도 의미가 있는지까지 살펴보는 것이 목표다. 주니어든 중급이든 번들러 개념이 헷갈린다면 한번 읽어보면 도움이 될 것이다.

 

번들러 없으면 프론트엔드는 어떤 지옥이 펼쳐지는가

 

웹팩 이야기를 하기 전에, 이것이 왜 필요했는지부터 짚고 가야 한다. 번들러(bundler)가 없던 시절을 한 번만 상상해보면 "아 이래서 필요하구나"라는 소리가 바로 나온다.

 

script 태그 서른 개를 박던 jQuery 시대

 

2010년대 초반 프론트엔드는 정말 원시적이었다. HTML 파일 하나에 , , 이런 식으로 태그 수십 개를 줄줄이 박아야 했다. 프로젝트가 커지면 HTML 헤드 부분이 100줄을 넘어가는 것도 흔한 일이었다.

 

이렇게 하면 무엇이 문제인가?

 

  • 네트워크 요청 개수 폭발: HTTP/1.1 시대에 파일이 30개면 요청도 30번 발생한다. TTFB 지옥이다.
  • 로드 순서 꼬임: a.js가 b.js를 참조하는데 b.js를 더 아래에 두면 그냥 터진다.
  • 전역 스코프 오염: 모든 변수가 window에 붙는다. $를 한 번 덮어쓰면 다른 라이브러리도 같이 죽는다.

 

의존성 순서가 꼬이면 코드가 그냥 터지는 구조

 

정말 웃긴 점은 이것이 실수가 아니라 "당시의 정상"이었다는 사실이다. 개발자가 수동으로 파일 로딩 순서를 관리해야 했다. 팀원 한 명이 새 스크립트를 위쪽에 끼워 넣으면, 다른 팀원의 코드가 의존성을 찾지 못하고 죽는다. 이런 사고가 하루에 서너 번씩 터졌다.

 

CommonJS는 Node.js용, 브라우저는 읽지 못한다

 

Node.js가 인기를 끌면서 CommonJS 스타일(require())이 표준처럼 자리잡았는데, 문제는 브라우저가 require를 모른다는 점이었다. 개발자 입장에서는 서버 코드와 브라우저 코드를 다른 방식으로 작성해야 했고, 코드 재사용이 거의 불가능했다.

 

누군가는 이 간극을 메워야 했다. 그 시점에 등장한 것이 Browserify였고, 곧이어 훨씬 강력한 웹팩이 등장한다.

 

웹팩이 정확히 무엇인지 한 줄로 정리하면

 

 

출처: Codementor

 

웹팩 공식 문서의 표현을 그대로 옮기면 "웹팩은 모던 자바스크립트 애플리케이션을 위한 정적 모듈 번들러다". 한 줄짜리 정의지만 살펴보면 꽤 많은 것이 담겨 있다.

 

"모듈 번들러"라는 단어부터 해부

 

  • 모듈: 기능 단위로 쪼개놓은 코드 조각이다. import/export나 require로 다른 파일을 불러오는 방식이다.
  • 번들러: 이 조각들을 의존성 그래프를 따라 모아서, 브라우저가 한 번에 읽을 수 있는 파일(번들)로 합쳐주는 도구다.

 

즉 웹팩은 흩어져 있는 JS 파일과 거기서 참조하는 CSS, 이미지, 폰트까지 모아서 "하나 또는 몇 개의 최적화된 파일"로 묶어주는 역할을 한다.

 

entry → loader → plugin → output 흐름

 

웹팩 설정을 이해하려면 이 4단어만 기억하면 된다.

 

  1. entry: 시작점이다. "이 파일부터 의존성을 따라가서 모두 모아와"라고 지정하는 지점이다.
  2. loader: 변환기다. .ts 파일을 JS로, .scss를 CSS로, .png를 인라인 데이터 URL로 바꿔주는 역할을 한다.
  3. plugin: 번들 전체 과정에 훅을 걸어서 작업을 수행하는 도구다. HTML 자동 생성, 압축, 환경 변수 주입 같은 것이다.
  4. output: 최종 산출물 위치다. "dist 폴더에 main.[hash].js로 뽑아라"라고 지시한다.

 

// webpack.config.js (webpack 5 기준)
module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.[contenthash].js',
  },
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader', 'css-loader'] },
      { test: /\.(png|jpg)$/, type: 'asset/resource' },
    ],
  },
};

 

이것이 webpack.config.js의 기본 골격이다. 실제 프로덕션에서는 여기에 플러그인이 붙고 최적화 옵션이 붙어서 수백 줄까지 늘어난다.

 

JS만 번들링하는 것이 아니다 — CSS, 이미지, 폰트도 모두 처리한다

 

웹팩의 진짜 강점은 "모든 것을 모듈로 취급한다"는 점이다. import './style.css' 한 줄을 쓰면 CSS도 JS 번들에 들어간다. 이미지도 import logo from './logo.png' 이렇게 작성하면 알아서 처리된다. 이것이 프론트엔드 개발 방식 자체를 바꿔버렸다.

 

프론트엔드에서 웹팩을 쓰는 진짜 이유 6가지

 

각설하고, 여기서부터가 본론이다. 웹팩 사용 이유를 하나씩 살펴보자.

 

모듈 시스템 통일 — ESM, CommonJS, AMD를 모두 처리한다

 

프론트엔드 생태계에는 모듈 시스템이 너무 많았다. CommonJS, AMD, UMD, ES Modules(ESM)... 라이브러리마다 다른 방식으로 배포된다. 웹팩은 이 모든 포맷을 인식해서 하나로 합쳐준다. import로 작성했든 require로 작성했든 최종 번들에서는 동일하게 동작한다. 이 "호환성 해결사" 역할만으로도 쓸 가치가 있다.

 

코드 스플리팅으로 초기 로딩 속도 확보

 

SPA(Single Page Application)가 커지면 번들 사이즈가 3~5MB까지 쉽게 도달한다. 이것을 한 번에 다운받게 하면 초기 로딩이 5초 이상 걸린다. 웹팩의 코드 스플리팅(code splitting) 은 라우트 단위, 컴포넌트 단위로 번들을 쪼개서 필요할 때만 다운받게 해준다.

 

// 동적 import — 웹팩이 알아서 청크 분리해줌
const AdminPanel = () => import('./AdminPanel');

 

이 한 줄을 넣으면 AdminPanel은 별도 청크로 빠지고, 관리자 페이지에 진입할 때만 로드된다. 초기 번들 사이즈가 30~50% 줄어드는 경우도 흔하다.

 

트리 셰이킹으로 사용하지 않는 코드 제거하기

 

트리 셰이킹(tree shaking) 은 "import했지만 실제로 사용하지 않는 함수를 번들에서 제거"하는 기능이다. 예를 들어 lodash에서 debounce 하나만 사용하는데 라이브러리 전체(70KB)가 번들에 들어가면 낭비다. 웹팩은 ESM 정적 분석으로 사용하지 않는 export를 찾아내서 제거한다. webpack 5에서 이 부분이 많이 개선되었다.

 

HMR — 저장하면 새로고침 없이 바로 반영

 

HMR(Hot Module Replacement) 이 없는 개발 환경은 상상할 수 없다. 코드를 수정하고 저장할 때마다 브라우저를 새로고침해야 한다면, 로그인 상태나 모달을 열어놓은 상태가 모두 날아간다. 웹팩의 HMR은 변경된 모듈만 런타임에 교체해서 앱 상태를 유지한 채로 업데이트해준다. React Hot Reload, Vue HMR 같은 도구도 모두 웹팩 HMR 위에서 동작한다.

 

환경별 빌드 분리 — dev는 빠르게, prod는 최적화

 

웹팩은 mode: 'development' / mode: 'production' 두 가지 프리셋을 제공한다. 개발 모드에서는 소스맵을 켜고 압축을 끄며, 프로덕션 모드에서는 minify와 tree shaking, 청크 해싱까지 모두 적용한다. webpack-merge로 공통 설정과 환경별 설정을 분리하는 것이 일반적인 패턴이다.

 

Module Federation — 마이크로프론트엔드의 유일무이한 답

 

이것이 webpack 5의 진짜 킬러 기능이다. Module Federation은 서로 다른 웹팩 빌드끼리 런타임에 모듈을 주고받을 수 있게 해준다. 쉽게 말하면 "앱 A에서 빌드한 컴포넌트를 앱 B가 런타임에 가져다 쓸 수 있다"는 의미다. 마이크로프론트엔드(여러 팀이 각자 배포하는 거대 프론트엔드 아키텍처)에서 거의 유일한 표준 해법이다.

 

Vite는 플러그인으로 비슷한 시도를 하고 있지만 완성도는 아직 웹팩이 훨씬 앞선다. 이것이 대기업들이 쉽게 웹팩을 버리지 못하는 이유 중 하나다.

 

웹팩을 만든 Tobias Koppers는 어떤 사람인가

 

 

출처: GOTO Conferences (141KB)

 

번들러 이야기만 하다 보면 놓치기 쉬운데, 웹팩은 회사가 만든 것이 아니라 한 명의 개발자가 석사 논문을 쓰다가 만든 프로젝트가 기원이다.

 

2012년 독일 대학원생의 개인 프로젝트로 시작되다

 

Tobias Koppers(@sokra)는 독일 개발자로, 2012년 3월에 webpack의 첫 커밋을 올렸다. 당시 그는 석사 논문을 쓰던 대학원생이었고, Google Web Toolkit(GWT)의 코드 스플리팅 기능에 꽂혀서 "JS에서도 이것이 가능하면 좋겠다"는 생각으로 개인 프로젝트를 시작했다.

 

웹팩 1.0 정식 릴리스는 2014년 2월이다. 초기에는 Browserify에 밀려 관심을 받지 못하다가, React + Redux 생태계가 코드 스플리팅과 HMR을 원하면서 2015년부터 급성장한다.

 

GWT 코드 스플리팅에 꽂힌 이유

 

Tobias는 본인 블로그와 인터뷰에서 "GWT가 Java 코드를 청크로 나누어 필요할 때만 로드하는 구조를 보았을 때, JS 생태계에는 왜 이것이 없는지 이해가 되지 않았다"고 밝혔다. 당시 JS 번들러(Browserify 등)는 그저 파일을 하나로 합치는 수준이었고, 동적 로딩 개념 자체가 빈약했다.

 

이 "청크 단위로 로드"라는 아이디어가 웹팩의 핵심 철학이 되었고, 오늘날의 코드 스플리팅, 동적 import, Module Federation까지 모두 이 뿌리에서 비롯되었다.

 

Open Collective로 풀타임 전환, 현재는 Vercel에서 Turbopack 리드

 

웹팩이 점점 커지면서 Tobias는 본업과 오픈소스 유지보수 사이에서 번아웃을 겪었다. 2017년경 Open Collective를 통해 스폰서십으로 풀타임 전환했고, 수년간 웹팩을 혼자서 사실상 유지했다.

 

그러다가 2021년에 Vercel에 합류한다. 현재는 Vercel에서 Turbopack이라는 차세대 번들러를 Rust로 개발하는 중이다. 웹팩의 후계자 격인데, 아직은 Next.js 내부에서 베타로 쓰이는 수준이다.

 

흥미로운 점은 Tobias가 웹팩을 버린 것이 아니라, "웹팩의 한계를 알기 때문에 더 나은 것을 만들겠다"는 맥락으로 Turbopack을 개발하고 있다는 사실이다. @wSokra 트위터에 가끔 올라오는 설계 이야기가 매우 흥미롭다.

 

웹팩의 단점 — 솔직히 살펴보자

 

좋은 이야기만 하면 광고글이 된다. 웹팩의 아픈 부분도 짚고 가자.

 

설정 지옥 — webpack.config.js 500줄의 트라우마

 

웹팩을 써본 사람이라면 공감할 텐데, webpack.config.js 설정 난이도가 정말 만만치 않다. 로더, 플러그인, 옵티마이제이션, 리졸버 같은 개념을 모두 이해해야 하고, 에러 메시지도 친절한 편이 아니다. 주니어가 webpack 설정을 처음 만지면 몇 시간은 그냥 날아간다.

 

이 문제 때문에 create-react-app, Next.js, Vue CLI 같은 "설정을 숨겨주는 프레임워크"가 대세가 되었다. 직접 설정할 일이 점점 줄어드는 추세다.

 

콜드 스타트가 느리다 — Vite 대비 체감 2~10배

 

웹팩은 개발 모드에서도 번들링을 한다. 프로젝트가 1000개가 넘는 모듈을 가지면 첫 npm run dev가 10~30초씩 걸린다. Vite는 esbuild로 의존성만 미리 처리하고 나머지는 네이티브 ESM으로 브라우저에 바로 전달하므로, 체감상 1~2초 안에 뜬다.

 

물론 webpack 5에서 영구 캐싱(filesystem cache)이 들어가면서 두 번째부터는 빨라졌다. 다만 첫 시동 속도는 여전히 Vite 대비 불리하다.

 

런타임 오버헤드와 번들 사이즈 이슈

 

웹팩은 모듈 간 호환성 처리를 위해 런타임 코드(wrapper)를 삽입한다. 이것이 작은 앱에서는 별 문제가 아니지만, 초소형 라이브러리에서는 오버헤드 비율이 꽤 크게 느껴진다. esbuild, Rollup 같은 도구가 같은 코드를 더 작게 뽑는 경우가 많다.

 

2026년 현재, 웹팩을 써야 하는가 말아야 하는가

 

이것이 가장 많이 받는 질문이다. 2026년 프론트엔드 번들러 선택은 확실히 바뀌었다.

 

신규 프로젝트는 Vite가 기본값이 된 현실

 

State of JS 2024 조사 기준, Vite와 웹팩이 사용률에서 거의 비등한 수준까지 따라붙었고, 만족도(positive sentiment)에서는 Vite가 웹팩을 압도적으로 앞질렀다. 신규 React, Vue, Svelte 프로젝트는 거의 다 Vite를 기본으로 제안한다. create-react-app은 2023년 3월에 React 공식 문서에서 추천이 빠졌고, 2025년 2월 공식적으로 deprecated(Sunsetting Create React App) 처리되었다. 대신 Vite 템플릿이 권장된다.

 

신규 프로젝트, 순수 SPA, 빠른 DX가 중요하다면 → Vite가 답이다.

 

레거시 유지보수와 Module Federation이면 여전히 웹팩

 

다만 "이미 웹팩으로 돌아가는 거대 프로젝트"를 Vite로 이주하는 것은 거의 불가능에 가깝다. 로더 생태계가 너무 방대하고, 커스텀 설정이 촘촘하게 박혀 있다.

 

특히 Module Federation을 써야 하는 마이크로프론트엔드 환경은 아직도 웹팩이 사실상 유일한 선택이다. 쿠팡, 네이버, 카카오 같은 대형 프론트엔드 조직이 웹팩을 버리지 못하는 이유다.

 

Rspack — 웹팩 호환 Rust 번들러의 등장

 

2024년 8월에 Rspack 1.0이 정식 릴리스되었다. ByteDance에서 만든 것으로, 웹팩의 API를 그대로 호환하면서 Rust로 다시 구현한 도구다. 체감 5~10배 빠르다. 기존 webpack.config.js를 거의 그대로 쓰면서 속도 이득만 챙길 수 있어서, "웹팩에서 Vite로 가지 못하는 조직"의 현실적 이주 경로로 주목받고 있다.

 

다만 플러그인 호환성이 아직 100%는 아니므로 도입 전에 의존성 체크는 필수다.

 

Next.js, 그리고 거대 프레임워크가 웹팩을 떠받쳐온 이유

 

Next.js 14까지는 기본 번들러가 웹팩이었다. Next.js 15에서 Turbopack이 dev 모드 기준 stable로 승격되었고, 2025년 10월 Next.js 16에 와서 Turbopack이 기본 번들러로 전환되었다. 그래도 next dev --webpack 옵션으로 여전히 웹팩을 선택할 수 있고, 광범위한 레거시 앱과 플러그인 생태계가 웹팩 기반이라는 사실은 변함없다. "웹팩의 안정성과 생태계 성숙도"를 단번에 대체하기 어렵다는 뜻이기도 하다.

 

웹팩은 죽지 않았다, 다만 역할이 바뀌었을 뿐이다

 

정리하면 이런 그림이다.

 

  • 초심자라면 웹팩 개념은 반드시 알아야 한다. 왜일까? 지금도 Next.js, Nuxt 같은 프레임워크 내부에 자리잡고 있고, 설정 커스터마이징을 해야 할 일이 반드시 생기기 때문이다.
  • 신규 프로젝트는 Vite로 시작하는 것이 맞다. DX 차이가 너무 크다.
  • 엔터프라이즈와 Module Federation 환경이라면 웹팩이다. 대안이 아직 없다.
  • 기존 웹팩 프로젝트의 속도를 개선하고 싶다면 Rspack 이주를 검토하라. config를 거의 그대로 쓰면서 속도 이득이 크다.

 

상황별 번들러 추천표

 

상황 추천 번들러 이유
신규 React/Vue SPA Vite DX 압도적
Next.js 앱 Next 기본값 (웹팩) 프레임워크 종속
마이크로프론트엔드 Webpack 5 Module Federation
거대 레거시 유지보수 Webpack 또는 Rspack 호환성 + 속도
라이브러리 배포 Rollup / tsup 작은 번들
초고속 빌드 필요 esbuild / Rspack Rust/Go 기반

 

Tobias Koppers가 2012년 독일의 한 연구실에서 석사 논문을 쓰다가 시작한 프로젝트가, 10년 넘게 프론트엔드 생태계 전체를 떠받치는 토대가 되었다. 지금은 더 빠른 도구들이 등장했지만, 그 도구들도 모두 웹팩이 만들어놓은 개념(모듈 그래프, 코드 스플리팅, HMR) 위에서 움직인다.

 

웹팩 사용 이유를 한 줄로 정리하자면, "프론트엔드를 모듈 단위로 개발하고 최적화하여 배포할 수 있게 만든 최초의 실용적 표준이기 때문"이다. 신규 프로젝트에서 직접 쓸 일이 줄어들어도, 개념을 이해하는 것은 여전히 필수다. 외워두면 언젠가 반드시 도움이 된다.

 

자주 묻는 질문 (FAQ)

 

Q: 웹팩이 무엇인지 한 줄로 설명하면?

여러 JS 모듈과 CSS/이미지 같은 에셋을 하나(또는 여러 개)의 번들 파일로 합쳐주는 모듈 번들러다.

 

Q: 웹팩을 만든 사람은 누구인가?

독일 개발자 Tobias Koppers가 2012년 3월에 첫 커밋한 개인 프로젝트로 시작되었다. 현재는 Vercel에서 Turbopack 개발을 리드하고 있다.

 

Q: 2026년에도 웹팩을 써야 하는가?

신규 프로젝트는 Vite가 낫다. 다만 Module Federation이나 거대 레거시 유지보수라면 여전히 웹팩이 답이다.

 

Q: 웹팩과 Vite의 차이는 무엇인가?

웹팩은 개발 중에도 번들링한다. Vite는 개발 시 esbuild와 네이티브 ESM으로 번들링하지 않고 바로 띄워서 빠르다. 프로덕션 빌드는 Vite도 Rollup으로 번들링한다.

 

Q: webpack 5와 webpack 4의 차이는?

webpack 5는 영구 캐싱, Module Federation, Asset Modules, 빌트인 트리 셰이킹 개선이 크다. webpack 4 대비 빌드 속도가 개선되고 번들 크기가 감소되었다.

728x90
반응형
Share Link
reply
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31