Skip to main content

Command Palette

Search for a command to run...

Webpack 번들링 : externals로 라이브러리 경량화 전략 (React 중심)

Published
•3 min read•View as Markdown

프론트엔드 개발자라면 누구나 한 번쯤 고민해 봤을 Webpack 번들링 최적화 주제를 다뤄보려 합니다.
특히, 재사용 가능한 라이브러리를 개발하고 배포할 때 필수인 externals 옵션에 대해 자세히 알아보겠습니다.

이 글은 실제 개발 과정에서 발생할 수 있는 문제점과 그 해결책을 중심으로 구성되어 있습니다.


🧐 Webpack externals 옵션이란?

externals 옵션은 Webpack에게 "특정 모듈은 번들에 포함시키지 마라" 라고 지시하는 설정입니다.
즉, 해당 모듈은 실행 환경(런타임)에서 사용 가능할 것으로 가정하고, 최종 번들 파일에는 포함시키지 않습니다.

주요 용도와 이점

  1. 번들 크기 최적화: React, Lodash 등 대형 라이브러리를 CDN이나 사용자 환경에서 제공받아 번들 크기를 획기적으로 줄일 수 있습니다.

  2. 캐싱 효율성 증대: 자주 변하지 않는 라이브러리 파일을 분리하여 브라우저 캐시 활용도를 높여 초기 로딩 속도를 개선합니다.

  3. 환경 의존성 처리: Node.js 내장 모듈(fs, path 등)을 브라우저 번들에서 제외할 때 사용합니다.

🛠️ 기본 설정 방법 (예시: React)

React와 ReactDOM을 CDN으로 로드하고 싶다면, webpack.config.js에서 다음과 같이 설정합니다.

JavaScript

// webpack.config.js

module.exports = {
  // ... (다른 설정)
  externals: {
    // 사용자가 import React from "react"를 하면,
    // 전역 변수 'React'를 사용하도록 처리합니다.
    'react': 'React',

    // 사용자가 import ReactDOM from "react-dom"를 하면,
    // 전역 변수 'ReactDOM'을 사용하도록 처리합니다.
    'react-dom': 'ReactDOM'
  }
};

이렇게 설정하면, 사용자는 HTML 파일에 반드시 <script> 태그를 이용해 React를 먼저 로드해야 합니다.


📦 라이브러리 개발자라면 externals는 필수!

직접 개발한 컴포넌트 라이브러리를 배포할 때 externals를 사용하는 것은 단순한 최적화를 넘어 호환성과 안정성을 위한 핵심 전략입니다.

🎯 핵심 목표: 중복 번들링 방지

내 라이브러리도 React를 사용하고, 이 라이브러리를 사용하는 외부 애플리케이션도 React를 사용합니다. externals를 지정하지 않으면 다음과 같은 문제가 발생합니다.

1. 🎈 번들 크기 폭발 (Bundle Bloating)

  • 문제: 라이브러리 번들 안에 React 코드가 통째로 포함되고, 사용자 애플리케이션 번들에도 React 코드가 포함됩니다.

  • 결과: 최종 애플리케이션은 React 코드를 두 번 로드하게 되어 번들 크기가 커지고 네트워크 비용이 증가합니다.

2. 🚨 런타임 오류 및 Hook 문제 (Fatal Error)

이것이 가장 치명적인 문제입니다.

  • externals를 설정하지 않으면 메모리에 두 개의 독립적인 React 인스턴스 (라이브러리용 A, 사용자 앱용 B)가 생성됩니다.

  • 당신의 라이브러리 컴포넌트가 인스턴스 A의 Hook을 사용하려 하지만, 사용자 앱의 렌더링 컨텍스트는 인스턴스 B에 묶여 충돌이 발생합니다.

  • 결과: 유명한 Invalid Hook Call Warning 오류나 Context Provider/Consumer 오류 등 예측 불가능한 런타임 버그가 발생합니다.

✅ React를 externals로 설정하는 방법

라이브러리 번들링 시에는 여러 모듈 시스템(CommonJS, AMD, Global)을 지원하는 UMD 스타일로 설정하는 것이 가장 안전합니다.

JavaScript

// webpack.config.js (라이브러리 배포용)

module.exports = {
  // ...
  externals: {
    'react': {
      // CommonJS 환경 (Node.js, Webpack 등)에서는 'react' 모듈 이름으로 참조
      commonjs: 'react', 
      commonjs2: 'react',
      amd: 'react',
      // 브라우저 전역 환경에서는 'React' 변수를 참조
      root: 'React' 
    },
    'react-dom': {
      commonjs: 'react-dom',
      commonjs2: 'react-dom',
      amd: 'react-dom',
      root: 'ReactDOM'
    }
  },
  // ...
};

이 설정을 통해 라이브러리는 사용자 환경의 단일한 React 인스턴스만을 사용하도록 보장되며, 이는 peerDependencies 모델을 기술적으로 실현하는 가장 정확한 방법입니다.


🌟 결론

Webpack의 externals 옵션은 라이브러리 개발자에게 선택이 아닌 필수입니다.
이 설정을 통해 번들 크기를 줄이고, React와 같은 핵심 의존성의 중복 로드를 방지하여 사용자 애플리케이션의 안정성과 성능을 동시에 확보할 수 있습니다.

성공적인 라이브러리 배포를 위해 externals 전략을 꼭 활용해 보세요!


🧾 작성 참고

본 글은 Gemini를 활용하여 작성되었습니다. 기술 정보의 정확성을 위해 항상 노력하지만, 혹시 내용에 보완할 점이 있다면 언제든지 의견을 나눠주세요!

More from this blog

LangGraph의 astream_events: 에이전트 실행을 실시간으로 들여다보기

💡 한 줄 요약: astream_events()는 LangGraph 그래프 실행 중 발생하는 모든 이벤트(LLM 토큰, 툴 호출, 노드 시작/종료 등)를 실시간 스트림으로 받을 수 있는 비동기 API입니다. 들어가며 AI 에이전트가 응답을 생성하는 데 25초가 걸린다고 상상해보세요. 사용자는 평균 8초 후에 페이지를 이탈합니다. 하지만 스트리밍을 도입

Jun 20, 20266 min read

LLM은 어떻게 글을 읽고 쓰는가 — 입력부터 출력까지

대화형 AI에게 질문을 던지면, 마치 사람처럼 문장을 이해하고 답을 써 내려가는 것처럼 보인다.하지만 그 안에서 벌어지는 일은 생각보다 단순하고, 또 생각보다 기계적이다.이 글에서는 두 가지 질문에 답해 본다.LLM은 어떻게 글을 만들어내는가,그리고 우리가 입력한 프롬프트는 모델에 어떤 모습으로 들어가는가. 1부. LLM은 어떻게 글을 만들어내는가 핵심은

Jun 10, 20264 min read

useEffect 지옥이란 무엇이며, 어떻게 안전하게 사용하는가

React를 어느 정도 사용하다 보면 한 번쯤은“useEffect 지옥에 빠졌다”는 말을 듣거나 직접 느껴본 적이 있을 것이다. useEffect가 계속 늘어나고 의존성 배열은 점점 길어지고 왜 실행되는지 이해하기 어려워지며 eslint-disable-next-line 이 늘어나는 상태 하지만 많은 사람들이 오해한다.useEffect 지옥은 useEffect가 많아서 생기는 문제가 아니다. 이 글에서는 ‘useEffect 지옥’의 ...

Jan 12, 20263 min read

Zod란 무엇인가: TypeScript에서 런타임 검증과 타입 안정성을 동시에 해결하는 방법

TypeScript 프로젝트를 하다 보면 반드시 마주치는 문제가 있다.바로 “타입은 있는데, 데이터는 믿을 수 없다”는 것이다. TypeScript는 컴파일 타임에는 강력하지만,런타임에 들어오는 데이터에 대해서는 아무런 보장을 해주지 않는다. API 요청 데이터 사용자 입력(Form) 환경 변수 (process.env) 외부 JSON / 설정 파일 이 모든 것은 타입 시스템 바깥에서 들어온다. 이 문제를 해결하기 위해 등장한 라이브러...

Jan 10, 20263 min read

Flatpak을 이해하기 위한 배경 지식

배포판, 라이브러리 충돌, 그리고 OSTree까지 리눅스 데스크톱에서 Flatpak이 표준처럼 자리 잡은 데에는 분명한 이유가 있다.그 이유를 이해하려면 단순히 “Flatpak은 패키징 시스템이다”를 넘어서,리눅스 배포판 구조, 라이브러리 버전 충돌, OSTree라는 기술까지 함께 이해해야 한다. 이 글에서는 다음 질문에 답해본다. 리눅스에서 말하는 배포판이란 무엇인가? 라이브러리 버전 충돌은 왜 발생하는가? Flatpak은 이 문제를 어...

Jan 8, 20265 min read

Dev note

32 posts