테마
레거시 환경의 마이크로 프론트엔드 아키텍처(MFA)
레거시 시스템에서도 마이크로 프론트엔드가 필요한 이유와, 도입 시 마주하는 핵심 장벽(CSS 오염, 기술 설정 복잡도)을 이해하고 실습 환경을 구성한다.
학습 목표
- 대규모 조직에서 MFA가 필요해지는 과정을 설명할 수 있다.
- 레거시 환경에서 MFA 도입의 두 가지 핵심 장벽(CSS 오염, 기술 설정)을 식별하고 대응 전략을 수립할 수 있다.
- Turbo 모노레포 기반 MFA 실습 환경을 직접 구성할 수 있다.
- 개발 환경(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.js | 16 이상 |
| 패키지 매니저 | 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.json4.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=70025. 개발 환경 vs 프로덕션 환경의 CSS 차이
CRA 기반 프로젝트에서 CSS가 로딩되는 방식은 환경에 따라 크게 다르다. 이 차이를 이해하는 것은 MFA에서 스타일 격리 전략을 수립하는 데 필수적이다.
| 항목 | 개발 환경 | 프로덕션 환경 |
|---|---|---|
| CSS 로더 | style-loader | MiniCssExtractPlugin |
| 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에서의 활용법을 다룬다.