Skip to content

레거시 환경의 마이크로 프론트엔드 아키텍처(MFA)

레거시 시스템에서도 마이크로 프론트엔드가 필요한 이유와, 도입 시 마주하는 핵심 장벽(CSS 오염, 기술 설정 복잡도)을 이해하고 실습 환경을 구성한다.

학습 목표

  1. 대규모 조직에서 MFA가 필요해지는 과정을 설명할 수 있다.
  2. 레거시 환경에서 MFA 도입의 두 가지 핵심 장벽(CSS 오염, 기술 설정)을 식별하고 대응 전략을 수립할 수 있다.
  3. Turbo 모노레포 기반 MFA 실습 환경을 직접 구성할 수 있다.
  4. 개발 환경(style-loader)과 프로덕션 환경(추출된 CSS)의 차이를 이해할 수 있다.

1. 대규모 조직에서 MFA가 필요해지는 과정

서비스가 성장하면 하나의 어플리케이션 안에 수많은 담당자와 담당 조직이 생겨난다. 각 조직은 자신이 맡은 메뉴를 확장하고 세분화하는 과정에서 조직 간 업무 결합도 증가중복 개발 문제를 겪게 된다.

1.1 조직 간 업무 결합도 증가

사용자 관점에서 하나로 인식되는 어플리케이션이라도 내부적으로는 여러 부서가 각자의 영역을 담당한다. 시간이 지나면서 기능의 담당자나 담당 부서가 바뀌거나, 동일한 기능을 여러 부서가 자신의 업무에 포함시켜야 하는 상황이 발생한다. 결제, 인증, 빌링과 같은 공통 기능은 서로 다른 부서라 하더라도 상호작용이 필수적이다.

1.2 중복 개발의 문제

성공한 서비스는 고객의 다양한 니즈에 따라 기능이 확장되고, 하나의 도메인 안에서도 세분화된 조직이 생겨난다. 이 과정에서 동일한 기능을 여러 팀이 각각 개발하는 중복이 발생한다. 각 정보나 기능에 대한 조직별 오너십을 확립하면 중복 리소스 투입을 방지하고 전문성을 높일 수 있다.

2. MFA 도입 방식: 빌드타임 vs 런타임

마이크로 프론트엔드를 실현하는 방법은 크게 두 가지로 나뉜다.

구분빌드타임 통합런타임 통합
방식배포 전 하나의 코드로 합침실행 중 필요한 서비스 조각을 다운로드
예시모노레포, npm 라이브러리iframe, Web Component, Module Federation, Runtime Injection
장점단순한 빌드 파이프라인독립 배포 가능, 조직 간 결합도 최소화
단점한 팀의 변경이 전체 재배포 유발런타임 오버헤드, 설정 복잡도

3. 레거시 환경의 MFA 도입 장벽

아무리 좋은 아키텍처라도 조직의 특성, 구성, 히스토리를 종합적으로 고려해야 한다. 레거시 환경에서 MFA 도입의 핵심 장벽은 두 가지다.

3.1 CSS 오염(CSS Pollution)

웹 어플리케이션의 디자인은 CSSOM 트리를 통해 렌더링된다. 마이크로앱을 인젝션할 때 기대하는 것은 기존 어플리케이션의 CSSOM 트리에 영향을 주지 않으면서 마이크로앱의 스타일이 독립적으로 동작하는 것이다.

하지만 인젝션된 앱의 CSS가 기존 앱의 디자인에 영향을 미칠 수 있다. 실 서비스를 운영하는 부서들은 이러한 위험에 대해 신중하고 보수적인 태도로 접근할 수밖에 없다.

CSS 오염이 발생하는 주요 시나리오:

  • 전역 셀렉터(*, body, div)가 마이크로앱에서 호스트까지 전파
  • 동일한 클래스명이 호스트와 마이크로앱에 동시 존재
  • CSS 우선순위(specificity) 충돌
  • !important 남용으로 인한 스타일 오버라이드

3.2 기술 설정의 복잡도

MFA는 서로 다른 조직들이 만든 여러 컴포넌트가 유기적으로 동작해야 하는 아키텍처다. 각 조직은 서로 다른 업무 히스토리, 기술 스택, 인력 구조를 가진다. 이런 상황에서 복잡한 설정과 생소한 라이브러리 도입을 강요하면 실무 도입에 대한 거부감만 커진다.

핵심 원칙: 다른 부서는 우리와는 전혀 다른 환경, 조직, 문화로 어플리케이션을 제작하고 운영한다. 어떤 환경과 설정에서 개발하는지에 상관없이 이용할 수 있도록 만드는 것이 레거시 MFA 도입의 키포인트다.

4. 실습 프로젝트 환경 구성

4.1 기술 스택

도구버전/설명
Node.js16 이상
패키지 매니저npm workspace
모노레포 도구Turborepo
앱 생성 도구Create React App (CRA)
컨테이너Docker + Nginx

4.2 프로젝트 생성

bash
# Turborepo 프로젝트 생성 (CRA 기반)
npx create-turbo@latest mfa-monorepo --use-npm

# 프로젝트 구조
mfa-monorepo/
  apps/
    docs/          # 마이크로앱 제공자 (포트 7001)
    web/           # 소비자 어플리케이션 (포트 7002)
  packages/
    ui/            # 공통 UI 패키지
  package.json     # 루트 워크스페이스 설정
  turbo.json

4.3 워크스페이스 설정

루트 package.json에서 React, React DOM, React Router DOM의 호이스팅을 방지해야 한다. 각 앱이 서로 다른 버전의 라이브러리를 사용할 수 있도록 하기 위해서다.

json
{
  "workspaces": {
    "packages": ["apps/*", "packages/*"],
    "nohoist": [
      "**/react",
      "**/react-dom",
      "**/react-router-dom"
    ]
  }
}

4.4 포트 설정

각 앱의 .env 파일에서 포트를 지정한다:

# apps/docs/.env
PORT=7001

# apps/web/.env
PORT=7002

5. 개발 환경 vs 프로덕션 환경의 CSS 차이

CRA 기반 프로젝트에서 CSS가 로딩되는 방식은 환경에 따라 크게 다르다. 이 차이를 이해하는 것은 MFA에서 스타일 격리 전략을 수립하는 데 필수적이다.

항목개발 환경프로덕션 환경
CSS 로더style-loaderMiniCssExtractPlugin
HTML 삽입 방식<style> 태그 (인라인)<link> 태그 (외부 파일)
HMR 지원지원 (실시간 반영)미지원
스타일 위치document.head 내부별도 .css 파일
번들 포함 여부JS 번들에 CSS 포함CSS 파일 분리

5.1 왜 이 차이가 MFA에서 중요한가

  • 개발 환경: style-loader가 CSS를 <style> 태그로 document.head에 직접 삽입한다. 마이크로앱의 CSS가 호스트 앱의 head에 추가되므로 CSS 오염이 즉시 발생한다.
  • 프로덕션 환경: CSS가 별도 파일로 추출되어 <link> 태그로 참조된다. 마이크로앱의 CSS 파일이 호스트 앱에서 로드되면 동일하게 오염이 발생한다.

두 환경 모두에서 스타일 격리가 필요하며, 이를 위해 Shadow DOM을 활용하는 전략을 다음 단계에서 학습한다.

5.2 Docker로 프로덕션 환경 확인

dockerfile
FROM nginx:1.21
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY build/ /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
bash
# 빌드 및 실행
cd apps/docs
npm run build
docker build -t docs .
docker run -p 7001:7001 docs

프로덕션 빌드 후 브라우저 개발자 도구에서 확인하면 <style> 태그 대신 <link rel="stylesheet"> 태그로 CSS가 로드되는 것을 볼 수 있다.


핵심 정리

항목내용
MFA 필요성대규모 조직에서 업무 결합도 감소와 중복 개발 방지를 위해 필수
통합 방식빌드타임(모노레포, npm)과 런타임(iframe, Module Federation, Runtime Injection)
CSS 오염MFA 도입의 가장 큰 장벽 -- 전역 스타일이 앱 간에 간섭
기술 설정 장벽레거시 조직에 복잡한 설정을 강요하면 도입 자체가 무산됨
환경 차이개발(style-loader, <style>)과 프로덕션(MiniCssExtractPlugin, <link>)의 CSS 로딩 방식이 다름
핵심 원칙어떤 환경에서 개발하든 이용 가능하도록 만드는 것이 레거시 MFA의 키포인트

다음 단계

CSS 오염 문제를 해결하기 위한 Shadow DOM 기반 스타일 격리 기법을 학습한다. Shadow DOM API의 개념, open/closed 모드 차이, React에서의 활용법을 다룬다.

다음: 02-ShadowDOM-스타일-격리