Skip to content

통합 방식 설계: 런타임과 빌드타임

Webpack Module Federation을 이용한 런타임 통합과 Vite 기반 공통 패키지의 빌드타임 통합을 설계하고, 공통 모듈(UIKit, Shell Router)의 인터페이스를 정의한다.

학습 목표

  • 런타임 통합(Module Federation)에서 Host/Remote 역할 분담을 이해한다
  • Shell과 마이크로앱의 독립 렌더 라이프사이클이 갖는 장단점을 파악한다
  • 빌드타임 공유 패키지의 설계 원칙과 package.json 인터페이스를 이해한다
  • UIKit과 Shell Router의 모듈 구성과 주요 인터페이스를 설계할 수 있다
  • Module Federation의 shared 설정으로 중복 로드를 방지하는 방법을 안다

1. 런타임 통합: Module Federation

1.1 Host와 Remote 역할 분담

커리어업의 런타임 통합은 Webpack Module Federation을 기반으로 한다. Shell이 유일한 Host이고, 4개의 마이크로앱이 Remote가 된다.

역할포트책임
HostShell3000GNB, 인증, 라우팅, Remote 앱 로드
RemotePosting3001포스팅 기능 전체, 마운트 함수 expose
RemoteNetwork3002네트워킹 기능 전체, 일촌 프래그먼트 expose
RemoteEducation3003교육 기능 전체
RemoteJobs3004채용 기능 전체, 추천 프래그먼트 expose

Webpack Module Federation을 선택한 이유는 프로덕션 환경에서의 안정성이다. Vite의 Module Federation 플러그인은 아직 프로덕션에서 충분히 검증되지 않았으므로, 런타임 앱은 Webpack을 사용한다. 빌드타임 패키지는 간편한 Vite를 사용한다.

1.2 독립 렌더 라이프사이클

커리어업의 각 마이크로앱은 Shell과 별도의 React 렌더 라이프사이클을 갖는다. Shell이 제공하는 마운트 영역(DOM 요소)에 각 마이크로앱이 자체적으로 ReactDOM.createRoot()를 호출하여 독립된 React 트리를 구성한다.

구분하위 컴포넌트 방식독립 렌더 방식 (커리어업 채택)
렌더링Shell의 React 트리 안에 포함별도의 React 트리 생성
Props 전달Shell에서 직접 props 전달 가능이벤트 시스템으로 데이터 교환
상태 공유Context API 사용 가능사용 불가, 이벤트 기반 통신 필요
리렌더링Shell 리렌더 시 함께 리렌더Shell 리렌더와 독립적
독립성낮음 (Shell에 종속적)높음 (완전히 독립적)
기술 유연성Shell과 동일 React 버전 필수이론적으로 다른 프레임워크도 가능

독립 렌더 방식을 채택하면 추가 작업(이벤트 시스템 구축)이 필요하지만, 마이크로앱의 독립성을 최대한 보장할 수 있다. 이는 MFE 아키텍처의 핵심 가치인 팀 자율성과 독립 배포에 부합한다.


2. 빌드타임 공유: 공통 패키지

2.1 빌드타임 vs 런타임 공유 구분

커리어업에서 공유되는 코드는 두 가지 방식으로 나뉜다:

공유 방식대상도구특징
빌드타임UIKit, Shell Router, UtilsVite (라이브러리 모드)앱 빌드 시 포함, npm 패키지 형태
런타임마이크로앱, 프래그먼트Webpack Module Federation브라우저에서 동적 로드

2.2 패키지 인터페이스 원칙

빌드타임 공유 패키지는 package.json에 명시된 인터페이스만으로 소통한다. 패키지 내부 구현은 캡슐화되고, 소비자(앱)는 export된 모듈만 사용할 수 있다.

json
{
  "name": "@careerup/ui-kit",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./styles": "./dist/global.css"
  },
  "peerDependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}

핵심 포인트:

  • exports 필드로 외부에 공개할 진입점을 명시한다
  • peerDependencies로 React를 선언하여 앱 전체에서 한 번만 로드되도록 한다
  • types 필드로 TypeScript 타입 정의를 제공한다

2.3 Module Federation shared 설정

빌드타임 패키지가 여러 마이크로앱에 포함되면, 런타임에 같은 코드가 여러 번 로드될 수 있다. Module Federation의 shared 설정으로 이를 방지한다.

javascript
// webpack.config.js 예시
new ModuleFederationPlugin({
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
    '@careerup/ui-kit': { singleton: true },
    '@careerup/shell-router': { singleton: true },
  },
});

singleton: true로 설정하면 런타임에 해당 모듈이 단 한 번만 로드되고, 모든 마이크로앱이 동일한 인스턴스를 공유한다.


3. 공통 모듈 설계: UIKit

3.1 UIKit의 구성

UIKit(@careerup/ui-kit)은 커리어업 전체의 디자인 일관성을 보장하는 공통 컴포넌트 라이브러리이다.

모듈설명
global.cssCSS Reset, 기본 타이포그래피, CSS Custom Properties(색상, 간격 등)
Button공통 버튼 컴포넌트 (primary, secondary, ghost 등)
Card콘텐츠 카드 컴포넌트 (리스트 아이템 등에 범용 사용)
IconSVG 아이콘 컴포넌트 세트
Layout헤더, 사이드바, 콘텐츠 영역 등 레이아웃 컴포넌트

3.2 UIKit 설계 원칙

원칙설명
기술 비의존성Emotion, Styled Components 등 특정 CSS-in-JS에 의존하지 않는다
기본 CSS 사용CSS Modules 또는 순수 CSS로 작성하여 어떤 앱에서든 사용 가능
cu- 접두사모든 클래스에 cu- 접두사를 붙여 다른 앱 스타일과 충돌 방지
Peer DependencyReact를 peerDependency로 선언하여 중복 번들링 방지
Vite 라이브러리 모드Vite의 라이브러리 모드로 빌드하여 ES Module과 CommonJS 동시 지원

4. 공통 모듈 설계: Shell Router

4.1 Shell Router의 구성

Shell Router(@careerup/shell-router)는 Shell과 마이크로앱 사이의 라우팅 동기화인증 정보 교환을 담당하는 핵심 인프라 패키지이다.

4.2 모듈별 상세 인터페이스

라우팅 훅

모듈사용처입력출력/동작
useAppEvent마이크로앱Memory Router의 navigate 함수Shell의 네비게이션 이벤트를 수신하여 Memory Router 경로 변경, 내부 경로 변경 시 Shell에 알림
useShellEventShellBrowser Router의 navigate 함수마이크로앱의 네비게이션 이벤트를 수신하여 Browser URL 변경, URL 변경 시 마이크로앱에 알림

컴포넌트

모듈사용처설명
AppRoutingManager마이크로앱useAppEvent 훅을 내부적으로 사용하는 래퍼 컴포넌트. React Router의 <Outlet />과 연결하여 마이크로앱의 라우팅을 처리한다. 마이크로앱은 이 컴포넌트만 import하면 된다.

팩토리 함수

모듈사용처설명
mount(el, App)마이크로앱의 expose마운트 대상 DOM 요소와 루트 컴포넌트를 받아 ReactDOM.createRoot로 렌더링하는 함수를 생성한다. Shell이 이 함수를 호출하여 마이크로앱을 삽입한다.

인증 모듈

모듈사용처설명
useUserEventShell마이크로앱의 사용자 정보 요청 이벤트를 수신하고, 현재 로그인된 사용자의 토큰과 정보를 이벤트로 응답한다.
getUserAsync마이크로앱Shell에 사용자 정보를 요청하는 비동기 함수. Promise를 반환하며, Shell의 응답 이벤트를 받을 때까지 대기한다.

5. Webpack Module Federation 설정 계획

5.1 Shell (Host) 설정 구조

javascript
// apps/shell/webpack.config.js
new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    posting: 'posting@http://localhost:3001/remoteEntry.js',
    networking: 'networking@http://localhost:3002/remoteEntry.js',
    education: 'education@http://localhost:3003/remoteEntry.js',
    jobs: 'jobs@http://localhost:3004/remoteEntry.js',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
    'react-router-dom': { singleton: true },
    '@careerup/ui-kit': { singleton: true },
    '@careerup/shell-router': { singleton: true },
  },
});

5.2 마이크로앱 (Remote) 설정 구조

javascript
// apps/posting/webpack.config.js
new ModuleFederationPlugin({
  name: 'posting',
  filename: 'remoteEntry.js',
  exposes: {
    './App': './src/App',
    './mount': './src/mount',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
    'react-router-dom': { singleton: true },
    '@careerup/ui-kit': { singleton: true },
    '@careerup/shell-router': { singleton: true },
  },
});

5.3 프래그먼트를 expose하는 Remote

네트워킹과 채용 앱은 자신의 앱 전체(./App)뿐만 아니라, 프래그먼트도 함께 expose한다:

javascript
// apps/networking/webpack.config.js - exposes 부분
exposes: {
  './App': './src/App',
  './mount': './src/mount',
  './FriendWidget': './src/fragments/FriendWidget',  // 프래그먼트
},

6. 전체 통합 아키텍처 요약


핵심 정리

  1. 런타임 통합: Shell이 유일한 Host, 4개 마이크로앱이 Remote. Webpack Module Federation으로 결합한다
  2. 독립 렌더 라이프사이클: 각 마이크로앱은 별도의 ReactDOM.createRoot()로 독립 React 트리를 형성한다. Shell의 리렌더와 무관하게 동작한다
  3. 빌드타임 공유: UIKit과 Shell Router는 Vite 라이브러리 모드로 빌드하고, package.json 인터페이스로만 소통한다
  4. UIKit: 기술 비의존적인 기본 CSS로 공통 컴포넌트를 작성하고, cu- 접두사로 스타일 충돌을 방지한다
  5. Shell Router: 라우팅 동기화(useAppEvent/useShellEvent)와 인증 공유(useUserEvent/getUserAsync)를 담당하는 핵심 인프라 패키지이다
  6. shared 설정: Module Federation의 singleton: true로 React, UIKit, Shell Router의 중복 로드를 방지한다
  7. 빌드타임 패키지는 어떤 빌드 도구로든 만들 수 있지만, 패키지 제작에 간편한 Vite를 사용한다

다음 단계

다음 문서 ../11-공통-모듈-구현/01-UI-라이브러리-개발에서는 UIKit 패키지를 실제로 구현한다. Vite 라이브러리 모드 설정, global.css 작성, Button/Card/Icon 컴포넌트 개발, 그리고 빌드 및 다른 앱에서의 사용법을 다룬다.