한국어

Webpack 5의 JavaScript 모듈 페더레이션으로 마이크로 프론트엔드의 강력한 기능을 활용하세요. 확장 가능하고 유지보수 용이하며 독립적인 웹 애플리케이션 구축 방법을 배워보세요.

Webpack 5를 이용한 JavaScript 모듈 페더레이션: 마이크로 프론트엔드를 위한 종합 가이드

끊임없이 진화하는 웹 개발 환경에서 크고 복잡한 애플리케이션을 구축하는 것은 어려운 과제일 수 있습니다. 기존의 모놀리식 아키텍처는 종종 개발 시간 증가, 배포 병목 현상, 코드 품질 유지의 어려움으로 이어집니다. 마이크로 프론트엔드는 이러한 문제들을 해결하기 위한 강력한 아키텍처 패턴으로 등장했으며, 팀들이 더 큰 웹 애플리케이션의 독립적인 부분들을 구축하고 배포할 수 있게 해줍니다. 마이크로 프론트엔드를 구현하기 위한 가장 유망한 기술 중 하나는 Webpack 5에서 도입된 JavaScript 모듈 페더레이션(JavaScript Module Federation)입니다.

마이크로 프론트엔드란 무엇인가?

마이크로 프론트엔드는 프론트엔드 앱을 더 작고 독립적인 단위로 분해하는 아키텍처 스타일로, 각 단위는 서로 다른 팀에 의해 자율적으로 개발, 테스트 및 배포될 수 있습니다. 각 마이크로 프론트엔드는 특정 비즈니스 도메인이나 기능을 담당하며, 런타임에 함께 구성되어 완전한 사용자 인터페이스를 형성합니다.

하나의 거대한 개발팀 대신 특정 영역에 집중하는 여러 개의 소규모 팀이 있는 회사와 같다고 생각하면 됩니다. 각 팀은 독립적으로 작업할 수 있어 개발 주기가 빨라지고 유지보수가 쉬워집니다. 아마존과 같은 대규모 전자상거래 플랫폼을 생각해보세요. 여러 팀이 제품 카탈로그, 쇼핑 카트, 결제 프로세스, 사용자 계정 관리를 각각 관리할 수 있습니다. 이 모든 것이 독립적인 마이크로 프론트엔드가 될 수 있습니다.

마이크로 프론트엔드의 장점:

마이크로 프론트엔드의 어려움:

JavaScript 모듈 페더레이션이란 무엇인가?

JavaScript 모듈 페더레이션은 Webpack 5의 기능으로, 별도로 컴파일된 JavaScript 애플리케이션 간에 런타임에 코드를 공유할 수 있게 해줍니다. 이를 통해 애플리케이션의 일부를 다른 애플리케이션에서 소비할 수 있는 "모듈"로 노출할 수 있으며, npm과 같은 중앙 저장소에 게시할 필요가 없습니다.

모듈 페더레이션을 애플리케이션의 연합 생태계를 만드는 방법으로 생각할 수 있습니다. 각 애플리케이션은 자체 기능을 제공하고 다른 애플리케이션의 기능을 소비할 수 있습니다. 이는 빌드 시점의 종속성을 제거하고 진정으로 독립적인 배포를 가능하게 합니다.

예를 들어, 디자인 시스템 팀은 UI 컴포넌트를 모듈로 노출할 수 있으며, 다른 애플리케이션 팀은 npm 패키지로 설치할 필요 없이 디자인 시스템 애플리케이션에서 직접 이러한 컴포넌트를 소비할 수 있습니다. 디자인 시스템 팀이 컴포넌트를 업데이트하면 변경 사항이 모든 소비 애플리케이션에 자동으로 반영됩니다.

모듈 페더레이션의 핵심 개념:

Webpack 5로 모듈 페더레이션 설정하기: 실용 가이드

Webpack 5로 모듈 페더레이션을 설정하는 실제 예제를 살펴보겠습니다. 호스트(Host) 애플리케이션과 원격(Remote) 애플리케이션이라는 두 개의 간단한 애플리케이션을 만들 것입니다. 원격 애플리케이션은 컴포넌트를 노출하고, 호스트 애플리케이션은 이를 소비합니다.

1. 프로젝트 설정

애플리케이션을 위해 `host`와 `remote`라는 두 개의 별도 디렉터리를 만듭니다.

```bash mkdir host remote cd host npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom cd ../remote npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom ```

2. 원격 애플리케이션 구성

`remote` 디렉터리에 다음 파일들을 생성합니다:

src/index.js:

```javascript import React from 'react'; import ReactDOM from 'react-dom/client'; import RemoteComponent from './RemoteComponent'; const App = () => (

Remote Application

); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

src/RemoteComponent.jsx:

```javascript import React from 'react'; const RemoteComponent = () => (

이것은 원격 컴포넌트입니다!

원격 애플리케이션에서 렌더링되었습니다.

); export default RemoteComponent; ```

webpack.config.js:

```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3001, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'remote', filename: 'remoteEntry.js', exposes: { './RemoteComponent': './src/RemoteComponent', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```

기본적인 HTML 구조를 가진 `public/index.html`을 생성합니다. 중요한 것은 `

`입니다.

3. 호스트 애플리케이션 구성

`host` 디렉터리에 다음 파일들을 생성합니다:

  • `src/index.js`: 애플리케이션의 진입점입니다.
  • `webpack.config.js`: Webpack 구성 파일입니다.

src/index.js:

```javascript import React, { Suspense } from 'react'; import ReactDOM from 'react-dom/client'; const RemoteComponent = React.lazy(() => import('remote/RemoteComponent')); const App = () => (

Host Application

원격 컴포넌트 로딩 중...
}>
); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

webpack.config.js:

```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3000, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { remote: 'remote@http://localhost:3001/remoteEntry.js', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```

기본적인 HTML 구조를 가진 `public/index.html`을 생성합니다(원격 앱과 유사). 중요한 것은 `

`입니다.

4. Babel 설치

`host`와 `remote` 디렉터리 양쪽 모두에서 Babel 종속성을 설치합니다:

```bash npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader ```

5. 애플리케이션 실행

`host`와 `remote` 디렉터리 양쪽 모두에서 `package.json`에 다음 스크립트를 추가합니다:

```json "scripts": { "start": "webpack serve" } ```

이제 두 애플리케이션을 모두 시작합니다:

```bash cd remote npm start cd ../host npm start ```

브라우저를 열고 `http://localhost:3000`으로 이동합니다. 호스트 애플리케이션 내에 원격 컴포넌트가 렌더링된 것을 볼 수 있습니다.

주요 구성 옵션 설명:

고급 모듈 페더레이션 기술

모듈 페더레이션은 훨씬 더 정교한 마이크로 프론트엔드 아키텍처를 구축하는 데 도움이 되는 많은 고급 기능을 제공합니다.

동적 원격(Dynamic Remotes)

Webpack 구성에 원격 애플리케이션의 URL을 하드코딩하는 대신 런타임에 동적으로 로드할 수 있습니다. 이를 통해 호스트 애플리케이션을 다시 빌드하지 않고도 원격 애플리케이션의 위치를 쉽게 업데이트할 수 있습니다.

예를 들어, 원격 애플리케이션의 URL을 구성 파일이나 데이터베이스에 저장하고 JavaScript를 사용하여 동적으로 로드할 수 있습니다.

```javascript // webpack.config.js 파일에서 remotes: { remote: `promise new Promise(resolve => { const urlParams = new URLSearchParams(window.location.search); const remoteUrl = urlParams.get('remote'); // remoteUrl이 'http://localhost:3001/remoteEntry.js'와 같다고 가정합니다 const script = document.createElement('script'); script.src = remoteUrl; script.onload = () => { // 모듈 페더레이션의 핵심은 원격 앱이 // 원격 앱에 지정된 이름으로 사용 가능하다는 것입니다 resolve(window.remote); }; document.head.appendChild(script); })`, }, ```

이제 `?remote=http://localhost:3001/remoteEntry.js` 쿼리 매개변수를 사용하여 호스트 앱을 로드할 수 있습니다.

버전 관리되는 공유 모듈

모듈 페더레이션은 각 모듈의 호환 가능한 버전 하나만 로드되도록 공유 모듈의 버전 관리 및 중복 제거를 자동으로 처리할 수 있습니다. 이것은 많은 종속성을 가진 크고 복잡한 애플리케이션을 다룰 때 특히 중요합니다.

Webpack 구성에서 각 공유 모듈의 버전 범위를 지정할 수 있습니다.

```javascript // webpack.config.js 파일에서 shared: { react: { singleton: true, eager: true, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: true, eager: true, requiredVersion: '^18.0.0' }, }, ```

사용자 정의 모듈 로더

모듈 페더레이션을 사용하면 다른 소스나 다른 형식에서 모듈을 로드하는 데 사용할 수 있는 사용자 정의 모듈 로더를 정의할 수 있습니다. 이는 CDN이나 사용자 정의 모듈 레지스트리에서 모듈을 로드하는 데 유용할 수 있습니다.

마이크로 프론트엔드 간 상태 공유

마이크로 프론트엔드 아키텍처의 어려움 중 하나는 서로 다른 마이크로 프론트엔드 간에 상태를 공유하는 것입니다. 이 문제를 해결하기 위해 다음과 같은 여러 접근 방식을 취할 수 있습니다:

모듈 페더레이션으로 마이크로 프론트엔드를 구현하기 위한 모범 사례

모듈 페더레이션으로 마이크로 프론트엔드를 구현할 때 염두에 두어야 할 몇 가지 모범 사례는 다음과 같습니다:

실제 세계에서의 모듈 페더레이션 적용 사례

구체적인 사례 연구는 종종 기밀이지만, 모듈 페더레이션이 매우 유용할 수 있는 몇 가지 일반적인 시나리오는 다음과 같습니다:

결론

Webpack 5의 JavaScript 모듈 페더레이션은 마이크로 프론트엔드 아키텍처를 구축하는 강력하고 유연한 방법을 제공합니다. 이를 통해 별도로 컴파일된 JavaScript 애플리케이션 간에 런타임에 코드를 공유하여 독립적인 배포, 기술 다양성 및 향상된 팀 자율성을 가능하게 합니다. 이 가이드에서 설명한 모범 사례를 따르면 모듈 페더레이션을 활용하여 확장 가능하고 유지보수 용이하며 혁신적인 웹 애플리케이션을 구축할 수 있습니다.

프론트엔드 개발의 미래는 의심할 여지 없이 모듈식 및 분산 아키텍처로 기울고 있습니다. 모듈 페더레이션은 이러한 현대적인 시스템을 구축하기 위한 중요한 도구를 제공하여 팀이 더 빠른 속도, 유연성 및 복원력을 갖춘 복잡한 애플리케이션을 만들 수 있도록 합니다. 기술이 성숙해짐에 따라 훨씬 더 혁신적인 사용 사례와 모범 사례가 등장할 것으로 기대할 수 있습니다.