PromleeBlog
sitemap
aboutMe

posting thumbnail
마이크로 프론트엔드 (대규모 앱 개발 아키텍쳐) - React, 알고 쓰자 10일차
Intro to Micro Frontends Solving Large-Scale App Development - React Explained Day 10

📅

🚀

들어가기 전에 🔗

애플리케이션의 기능이 점점 많아지고, 개발에 참여하는 팀의 규모가 커지면 기존의
모놀리식(Monolithic)
프론트엔드 방식, 즉 하나의 큰 덩어리로 개발하고 배포하는 방식은 여러 어려움에 부딪히게 됩니다.
이러한 문제를 해결하기 위해 서버 개발 영역에서 먼저 등장했던
마이크로서비스 아키텍처(MSA)
의 개념을 프론트엔드에 적용한 것이 바로
마이크로 프론트엔드(Micro Frontend, MFE)
입니다.
오늘은 이 마이크로 프론트엔드가 무엇인지, 어떤 장점이 있고 어떻게 구현할 수 있는지, 그리고 도입 시 고려해야 할 점은 무엇인지 알아보겠습니다.

🚀

마이크로 프론트엔드란? 🔗

마이크로 프론트엔드는 하나의 거대한 프론트엔드 애플리케이션을 여러 개의
작고, 독립적으로 배포 가능한
프론트엔드 애플리케이션(마이크로 앱)으로 나누어 개발하는 아키텍처 스타일입니다.
사용자에게는 여전히 하나의 일관된 웹사이트나 앱처럼 보이지만, 내부적으로는 여러 개의 독립적인 부분들이 모여 동작하는 형태입니다.

핵심 목표와 특징 🔗

Monolithic & Micro Architecture
Monolithic & Micro Architecture

모놀리식과의 비교 🔗

특징모놀리식 프론트엔드마이크로 프론트엔드
코드베이스
단일 거대 코드베이스여러 개의 작은 코드베이스
개발
모든 팀이 동일 코드베이스 작업팀별 독립적인 코드베이스 작업
배포
전체 애플리케이션 단위 배포마이크로 앱 단위 독립 배포 가능
기술 스택
단일 기술 스택 (변경 어려움)기술 스택 다양성 가능 (점진적 변경 용이)
팀 구조
기능별 팀 또는 거대 단일 팀도메인/기능 중심 자율적 팀
결합도
높음 (변경 영향 범위 큼)낮음 (변경 영향 범위 제한적)
복잡성
초기에는 낮으나, 규모 증가 시 급증초기 설정 복잡성 높음, 개별 앱은 단순

🚀

통합 방식 🔗

여러 개의 독립적인 마이크로 앱들을 어떻게 사용자에게 하나의 애플리케이션처럼 자연스럽게 보여줄 수 있을까요?
이를
통합(Integration)
이라고 하며, 주로 사용자의 브라우저에서 이루어지는
런타임 통합(Runtime Integration)
방식이 많이 사용됩니다.

런타임 통합 방식들 🔗

Single-SPA: 라우팅과 라이프사이클 관리 🔗

Single-SPA는 마이크로 프론트엔드 애플리케이션의
라우팅
라이프사이클(로드, 마운트, 언마운트)
관리를 도와주는 JavaScript 프레임워크입니다.
➡️

역할 🔗

➡️

동작 방식 🔗

  1. 컨테이너 앱 (루트 앱)
    Single-SPA 설정을 포함하는 메인 애플리케이션입니다.
  2. 애플리케이션 등록
    각 마이크로 앱을 Single-SPA에 등록합니다. 이때 어떤 URL 경로에서 활성화될지, 앱 코드를 어떻게 로드할지 등을 설정합니다.
  3. 라우팅
    URL이 변경되면 Single-SPA는 등록된 정보를 바탕으로 해당 경로에 맞는 마이크로 앱을 활성화하고, 필요 없는 앱은 비활성화(언마운트)합니다.
Single-SPA 아키텍처
Single-SPA 아키텍처

🚀

Webpack Module Federation 🔗

마이크로 앱들이 서로 독립적이라 하더라도, 공통으로 사용하는 라이브러리(React, lodash 등)나 컴포넌트(디자인 시스템의 버튼 등)가 있을 수 있습니다.
이런 공유 자원을 각 마이크로 앱마다 중복해서 포함하면 전체 애플리케이션의 크기가 불필요하게 커집니다.
Webpack 5 버전부터 도입된
Module Federation
은 이 문제를 해결하는 강력한 기능입니다.

핵심 개념 🔗

Module Federation은 별도로 빌드된 여러 개의 JavaScript 애플리케이션(번들)이
런타임
에 코드를 동적으로 공유할 수 있게 해줍니다.

간단한 설정 예시 🔗

Module Federation 설정은 Webpack 설정 파일에서 이루어집니다.
Remote 앱의 webpack.config.js
// Remote 앱 (예: 'profileApp')의 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const deps = require('./package.json').dependencies; // 공유 의존성 버전 관리
 
module.exports = {
  // ... 기타 설정 ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'profileApp', // Remote 앱의 고유 이름
      filename: 'remoteEntry.js', // Host가 참조할 진입점 파일
      exposes: {
        // 외부에 노출할 모듈 경로 매핑 ('./UserProfile' 키로 접근)
        './UserProfile': './src/UserProfile',
      },
      shared: { // 공유할 의존성 설정
        ...deps, // package.json의 모든 의존성 공유 (간단 예시)
        react: { singleton: true, requiredVersion: deps.react },
        'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
      },
    }),
  ],
};
Host 앱의 webpack.config.js
// Host 앱 (예: 'containerApp')의 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const deps = require('./package.json').dependencies;
 
module.exports = {
  // ... 기타 설정 ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'containerApp',
      remotes: {
        // 사용할 Remote 앱 정보 등록 (profileApp@http://localhost:3001/remoteEntry.js)
        profileApp: 'profileApp@http://localhost:3001/remoteEntry.js',
      },
      shared: { // 공유할 의존성 설정 (Remote와 동일하게)
        ...deps,
        react: { singleton: true, requiredVersion: deps.react },
        'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
      },
    }),
  ],
};
Host 앱에서 Remote 컴포넌트 사용
// Host 앱의 컴포넌트에서 Remote 컴포넌트 사용
import React, { lazy, Suspense } from 'react';
const RemoteUserProfile = lazy(() => import('profileApp/UserProfile'));
 
function App() {
  return (
    <div>
      <h1>컨테이너 앱</h1>
      <Suspense fallback="Loading Profile...">
        <RemoteUserProfile />
      </Suspense>
    </div>
  );
}
이 설정을 통해 containerAppprofileApp이 노출한 UserProfile 컴포넌트를 마치 자신의 코드인 것처럼 가져와 사용할 수 있으며, React와 같은 공유 라이브러리는 중복 로드되지 않습니다.
Q: "Webpack Module Federation이란 무엇이고 마이크로 프론트엔드에서 어떤 문제를 해결하나요?"
A: "독립적으로 빌드된 여러 웹팩 애플리케이션이 런타임에 코드를 동적으로 공유하는 기능입니다. MFE에서 마이크로 앱 간의 컴포넌트 공유나 공통 라이브러리 중복 로드 문제를 효율적으로 해결합니다."

🚀

마이크로 프론트엔드 도입 시 고려사항 🔗

마이크로 프론트엔드는 많은 장점을 제공하지만, 도입과 운영에 따르는 복잡성과 고려사항들도 있습니다.
Module Federation은 내부적으로 의존성 그래프를 사용하여 공유 모듈과 버전을 관리합니다. Single-SPA는 라우팅 테이블(해시 테이블 유사 구조)을 사용하여 URL과 마이크로 앱을 매핑할 수 있습니다.

🚀

결론 🔗

오늘은 대규모 프론트엔드 애플리케이션 개발의 복잡성을 해결하기 위한 아키텍처 패턴인 마이크로 프론트엔드에 대해 알아보았습니다.
마이크로 프론트엔드는 모든 프로젝트에 맞는 Silver bullet은 아닙니다.
애플리케이션의 규모, 팀 구조, 기술적 요구사항 등을 충분히 고려하여 도입 여부를 신중하게 결정해야 합니다.
만약 도입하기로 결정했다면, 오늘 살펴본 기술들과 고려사항들을 바탕으로 체계적인 계획과 점진적인 접근 방식을 취하는 것이 중요합니다.
다음 시간에는 프론트엔드 개발에서 API 통신을 어떻게 효과적으로 처리하는지, 비동기 작업 관리 전략에 대해 알아보겠습니다. Axios, Fetch 비교부터 AbortController, GraphQL 클라이언트까지 다양한 API 통신 방법을 살펴보겠습니다.

참고 🔗