--- id: wiki-2026-0508-micro-frontends title: Micro frontends category: 10_Wiki/Topics status: verified canonical_id: self aliases: [MFE, Micro-frontend Architecture] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [frontend, architecture, modular] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Module Federation / Single-SPA --- # Micro frontends ## 매 한 줄 > **"매 microservices 매 frontend 적용 — 매 large UI 매 independent deployable team-owned vertical slices 매 분할"**. ThoughtWorks Tech Radar (2016) 매 이름 채택, 매 Webpack 5 Module Federation (2020) 매 mainstream 진입, 매 2026 매 large enterprise frontend (Spotify, IKEA, DAZN) 매 standard, 매 Vite Module Federation + Native Federation 매 modern stack. ## 매 핵심 ### 매 핵심 가치 (vs monolith) - **Independent deploy**: 매 team 매 자기 slice 매 release pipeline. - **Tech heterogeneity**: 매 React + Vue + Svelte 매 공존 (단 cost ↑). - **Team scalability**: 매 vertical team ownership — 매 Conway's law 매 align. - **Incremental migration**: 매 legacy → modern 매 점진적 교체. ### 매 cost - **Bundle duplication**: 매 framework 매 여러 번 load. - **Cross-MFE state**: 매 shared store 매 design. - **Routing coordination**: 매 shell + child route 매 sync. - **Versioning skew**: 매 shared dep 매 version conflict. - **DX overhead**: 매 dev 매 multi-repo / multi-server. ### 매 composition strategies - **Build-time**: npm package — 매 monorepo + 매 publish (closest to monolith). - **Server-side**: SSI/ESI/Tailor — 매 edge composition (Podium, Mosaic). - **Run-time iframe**: 매 ultimate isolation — 매 worst UX. - **Run-time Web Components**: 매 framework-agnostic embed. - **Run-time Module Federation** (Webpack 5 / Vite): 매 sharing dep + dynamic import — 매 dominant 2026. - **Run-time Single-SPA**: 매 lifecycle orchestration framework. ### 매 응용 1. Large e-commerce (header/cart/product/checkout 매 별도 team). 2. Multi-tenant SaaS (workspace + apps marketplace). 3. Legacy modernization (strangler fig pattern). 4. White-label platforms (per-customer customization). ## 💻 패턴 ### Webpack Module Federation — host (shell) ```js // shell/webpack.config.js const { ModuleFederationPlugin } = require('webpack').container module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'shell', remotes: { cart: 'cart@https://cart.example.com/remoteEntry.js', product: 'product@https://product.example.com/remoteEntry.js', }, shared: { react: { singleton: true, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: true, requiredVersion: '^18.0.0' }, }, }), ], } ``` ### Module Federation — remote (cart MFE) ```js // cart/webpack.config.js new ModuleFederationPlugin({ name: 'cart', filename: 'remoteEntry.js', exposes: { './CartWidget': './src/CartWidget', './useCart': './src/hooks/useCart', }, shared: { react: { singleton: true }, 'react-dom': { singleton: true }, }, }) ``` ### Host consume (React lazy) ```tsx // shell/App.tsx import React, { lazy, Suspense } from 'react' const CartWidget = lazy(() => import('cart/CartWidget')) export function App() { return (
Loading cart…
}> ) } ``` ### Vite Module Federation ```ts // cart/vite.config.ts import federation from '@originjs/vite-plugin-federation' export default { plugins: [ federation({ name: 'cart', filename: 'remoteEntry.js', exposes: { './CartWidget': './src/CartWidget.tsx' }, shared: ['react', 'react-dom'], }), ], build: { target: 'esnext', minify: false, cssCodeSplit: true }, } ``` ### Single-SPA root config ```ts // root-config/index.ts import { registerApplication, start } from 'single-spa' registerApplication({ name: '@org/cart', app: () => System.import('@org/cart'), activeWhen: ['/cart'], }) registerApplication({ name: '@org/product', app: () => System.import('@org/product'), activeWhen: ['/products'], }) start() ``` ### Single-SPA child lifecycle ```ts // cart-app/src/main.ts import { h, createApp } from 'vue' import singleSpaVue from 'single-spa-vue' import Root from './Root.vue' const lifecycles = singleSpaVue({ createApp, appOptions: { render: () => h(Root) }, }) export const bootstrap = lifecycles.bootstrap export const mount = lifecycles.mount export const unmount = lifecycles.unmount ``` ### Web Components 매 framework-agnostic embed ```ts // cart-mfe.ts class CartElement extends HTMLElement { connectedCallback() { const root = this.attachShadow({ mode: 'open' }) // mount React/Vue/Svelte into shadow DOM mountReact(, root) } disconnectedCallback() { unmountReact(this.shadowRoot!) } } customElements.define('app-cart', CartElement) ``` ```html ``` ### Cross-MFE communication — Custom Events ```ts // 매 publish window.dispatchEvent(new CustomEvent('cart:item-added', { detail: { sku: 'A123', qty: 1 }, })) // 매 subscribe window.addEventListener('cart:item-added', (e) => { console.log('item added:', (e as CustomEvent).detail) }) ``` ### Shared shell store (BroadcastChannel) ```ts const channel = new BroadcastChannel('app-state') // MFE A channel.postMessage({ type: 'auth/login', user }) // MFE B channel.onmessage = ({ data }) => { if (data.type === 'auth/login') updateLocalState(data.user) } ``` ### CSS isolation strategies ``` 1. Shadow DOM (Web Components 매 자동 scope) 2. CSS Modules (build-time hash) 3. CSS-in-JS (runtime scope, e.g., styled-components) 4. PostCSS namespace plugin (legacy) 5. Tailwind prefix per MFE: `tw-cart-`, `tw-product-` ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Single team, single product | Monolith (MFE overkill) | | Multiple teams, shared shell | Module Federation | | Legacy → React migration | iframe → Web Components → MF | | Framework heterogeneity | Web Components / Single-SPA | | Maximum isolation (security) | iframe (last resort) | | Tight budget (LCP critical) | Build-time composition | | SSR + MFE | Server-side composition (Tailor, Mosaic) | | Vite stack | Native Federation / vite-plugin-federation | **기본값**: 매 React/Vue 균일 stack 매 Module Federation, 매 framework 혼재 매 Single-SPA + Web Components. ## 🔗 Graph - 부모: [[프론트엔드 및 UIUX 표준|Frontend-Architecture]] · [[Microservices]] - 변형: [[Module-Federation]] · [[Web-Components]] - Adjacent: [[Monorepo]] · [[Vite]] ## 🤖 LLM 활용 **언제**: 매 large team (50+ FE devs), 매 independent deploy 필요, 매 legacy modernization, 매 multi-tenant white-label. **언제 X**: 매 small team (<10), 매 single-page simple SPA, 매 LCP-critical landing — 매 monolith 적합. ## ❌ 안티패턴 - **매 component-level MFE**: 매 button 매 MFE — 매 latency overhead — 매 vertical slice 매 단위. - **Shared global state via window**: 매 race condition + 매 hidden coupling. - **Framework version skew**: 매 React 17 + 18 매 host — 매 hooks 깨짐. - **No design system**: 매 visual inconsistency — 매 shared tokens/components 필수. - **Synchronous load chain**: 매 cascade waterfall — 매 lazy + 매 parallel 매 host. - **MFE 매 small team 매 도입**: 매 over-engineering — 매 monolith + 매 module boundary 매 충분. ## 🧪 검증 / 중복 - Verified (ThoughtWorks Tech Radar, micro-frontends.org, Module Federation docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — composition strategies + MF/Single-SPA/WC patterns + comm matrix |