마이크로 프론트엔드 vs 모놀리식 프론트엔드: 적합한 아키텍처 선택하기
웹 애플리케이션의 복잡성과 규모가 커짐에 따라 개발자들은 유지보수성과 확장성 측면에서 아키텍처를 신중하게 선택해야 합니다. 모놀리식 프론트엔드(Monolithic Frontends) 와 마이크로 프론트엔드(Micro Frontends) 는 그 목적에 따라 서로 다른 장단점을 가진 두 가지 아키텍처입니다. 이 글에서는 두 아키텍처의 개념과 장단점, 그리고 프로젝트에 적합한 레포지토리 구조에 대해 설명합니다.
이미지 참고: https://radixweb.com/blog/guide-to-micro-frontend-architecture
1. 모놀리식 프론트엔드(Monolithic Frontend)
모놀리식 프론트엔드는 모든 애플리케이션이 하나의 코드베이스에 통합되어, 백엔드, 프론트엔드, 데이터베이스 등 모든 구성 요소가 함께 배포되는 전통적인 방식입니다. 주로 작은 규모의 애플리케이션에서 사용되며, 모든 코드를 단일 프로젝트로 관리합니다.
주요 특징:
- 단일 코드베이스: 애플리케이션의 모든 부분이 하나의 코드베이스로 통합됩니다.
- 일관된 기술 스택: 동일한 기술 스택으로 개발되며 일관성을 유지합니다.
- 중앙화된 배포: 애플리케이션의 모든 구성 요소가 한 번에 배포됩니다.
장점:
- 단순성: 모든 코드가 하나의 코드베이스에서 관리되기 때문에 개발과 배포가 비교적 쉽습니다.
- 퍼포먼스: 모든 기능이 하나의 유닛으로 실행되어 모듈 간 네트워크 호출이 필요 없어 성능이 빠릅니다.
- 일관성: 모든 팀이 동일한 기술 스택을 사용하므로 유지보수가 수월합니다.
단점:
- 확장성 문제: 애플리케이션이 커질수록 유지보수와 배포가 복잡해지며, 작은 변경도 전체 시스템에 영향을 미칠 수 있습니다.
- 기술 도입 제약: 새로운 기술 스택을 도입하려면 전체 애플리케이션을 수정해야 하므로 어려움이 따릅니다.
예시 폴더 구조:
/monolithic-app
│
├── /src
│ ├── /components
│ ├── /pages
│ └── App.js
│
├── /public
│ └── index.html
├── package.json
└── webpack.config.js
이 구조는 모든 파일이 src
폴더에 모여있으며, 각 페이지와 컴포넌트는 단일 코드베이스에서 관리됩니다.
예시 Webpack 설정:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
}
모놀리식 애플리케이션에서는 하나의 번들로 모든 자산을 빌드합니다.
실제 회사의 모놀리식 프론트엔드 아키텍쳐 적용 예시
-
Airbnb: Airbnb는 초기부터 모놀리식 아키텍처로 프론트엔드를 구축했습니다. 이는 작은 팀이 빠르게 새로운 기능을 추가하고 전 세계적으로 배포하는데 유리한 방식이었습니다. 모놀리식 구조 덕분에 모든 코드가 단일 코드베이스에 있어, 모든 기능을 중앙 집중식으로 관리할 수 있었습니다. 그러나 점점 시스템이 복잡해지면서, 부분적으로 마이크로 프론트엔드 아키텍처를 도입하기 시작했습니다.
-
Facebook: Facebook은 대부분의 기능이 모놀리식 구조로 시작되었습니다. 초기에는 사용자 수와 데이터 트래픽이 지금과 같지 않아 모놀리식 아키텍처가 적합했지만, 점차 성장하면서 일부 마이크로 프론트엔드로 전환해 각 기능을 독립적으로 관리하고 있습니다. 특히, 광고, 뉴스 피드, 메신저 등 독립적인 팀이 특정 기능을 집중 관리하고 있습니다.
모놀리식 프론트엔드는 언제 사용해야할까?
-
작은 스타트업 서비스: 기능이 제한적이고 초기 단계인 스타트업 웹 서비스는 모놀리식 프론트엔드를 사용하는 것이 효율적입니다. 예를 들어, 한정된 리소스를 가진 팀에서 하나의 코드베이스로 빠르게 애플리케이션을 개발하고 배포하는 것이 유리합니다.
-
단일 목적 웹 애플리케이션: 단일 기능을 수행하는 서비스, 예를 들어 개인 포트폴리오 사이트나 블로그 플랫폼은 모놀리식 아키텍처로 충분히 운영 가능합니다. 개발과 배포가 간단하고, 코드 관리가 수월합니다.
2. 마이크로 프론트엔드(Micro Frontends)
마이크로 프론트엔드는 애플리케이션을 작은 독립 모듈로 분할하여 각 모듈이 독립적으로 개발되고 배포되는 아키텍처입니다. 각 모듈은 독립적인 기술 스택을 가질 수 있으며, 주로 대규모 애플리케이션에서 사용됩니다.
주요 특징:
- 독립된 모듈: 각 모듈은 특정 기능을 담당하며 독립적으로 동작합니다.
- 기술 스택의 유연성: 각 모듈은 서로 다른 기술을 사용할 수 있습니다.
- 분산된 배포: 모듈별로 독립적으로 배포됩니다.
장점:
- 확장성: 각 모듈을 개별적으로 확장하거나 배포할 수 있어 전체 시스템의 복잡성을 줄입니다.
- 독립성: 모듈 간 문제가 발생해도 다른 모듈에 영향을 미치지 않습니다.
- 기술 선택의 자유: 각 팀이 자신이 맡은 모듈에 가장 적합한 기술을 선택할 수 있습니다.
단점:
- 복잡성: 여러 모듈을 관리해야 하므로, 통합과 상태 관리가 더 복잡해질 수 있습니다.
- 성능 문제: 모듈 간 통신으로 인해 추가적인 네트워크 오버헤드가 발생할 수 있습니다.
예시 폴더 구조:
/microfrontend-app
├── /app1
│ ├── /src
│ └── package.json
│
├── /app2
│ ├── /src
│ └── package.json
│
└── /container
├── /src
└── webpack.config.js
마이크로 프론트엔드에서는 각 모듈이 개별 폴더로 관리되며, container
에서 이를 통합합니다.
예시 Webpack 설정:
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Component': './src/Component',
},
shared: ['react', 'react-dom'],
}),
],
}
이 설정은 Module Federation을 사용하여 각 모듈을 독립적으로 개발하고, 필요에 따라 동적으로 로드할 수 있습니다.
실제 회사의 마이크로 프론트엔드 아키텍처 적용 예시
-
Amazon: Amazon은 마이크로 프론트엔드 아키텍처를 적용한 대표적인 기업 중 하나입니다. 전 세계적으로 수많은 기능(제품 검색, 리뷰, 결제 등)을 처리하는데, 각 기능이 독립적인 팀에 의해 관리되고 개발됩니다. 이 방식은 여러 팀이 병렬로 작업할 수 있도록 하여 빠른 배포와 유지보수를 가능하게 만듭니다. 예를 들어, 결제 모듈에서 오류가 발생하더라도 다른 기능들은 정상적으로 작동할 수 있습니다.
-
IKEA: IKEA는 온라인 쇼핑 시스템에서 마이크로 프론트엔드를 도입하여, 다양한 쇼핑 기능을 독립적으로 개발하고 배포할 수 있도록 합니다. 이는 IKEA가 세계 여러 나라에 맞춤형 기능을 제공하는데 필요한 확장성과 유연성을 제공합니다.
-
Spotify: Spotify의 웹 애플리케이션은 음악 재생, 추천, 사용자 관리 등의 다양한 기능을 독립적으로 개발하고 있습니다. 각 기능은 서로 다른 기술 스택을 사용하여 구축되며, 개별적으로 업데이트되고 배포됩니다. 이렇게 하면 특정 기능이 문제를 일으키더라도 전체 서비스에는 영향을 미치지 않습니다.
마이크로 프론트엔드는 언제 사용해야할까?
-
복잡한 이커머스 플랫폼: 예를 들어, 쿠팡이나 11번가와 같은 대형 전자상거래 플랫폼은 다양한 기능을 독립적으로 개발하고 유지해야 합니다. 마이크로 프론트엔드를 사용하면 결제 시스템, 제품 카탈로그, 리뷰 시스템 등을 독립적으로 개발하고 배포할 수 있어 유지보수와 확장이 용이합니다.
-
다국적 소셜 미디어 플랫폼: 글로벌 서비스를 제공하는 TikTok이나 Instagram과 같은 플랫폼은 다국적 요구사항을 수용하고 다양한 팀이 독립적으로 기능을 개발해야 합니다. 마이크로 프론트엔드는 독립적인 배포와 빠른 업데이트가 가능해 이런 복잡한 요구를 충족할 수 있습니다.
3. 레포지토리 구조: Monorepo, Multirepo, Metarepo
아키텍처에 맞는 레포지토리 구조를 선택하는 것도 매우 중요합니다.
다양한 레포지토리 구조에 대한 설명을 좀 더 구체적으로 확장해 보겠습니다. 각 구조는 팀 구성, 프로젝트 규모, 협업 요구사항에 따라 적합한 선택이 달라집니다. 레포지토리 구조는 코드의 일관성 유지, 개발 속도 향상, 그리고 배포의 효율성에 큰 영향을 미칩니다.
1. Monolithic Repository (모놀리식 레포지토리)
모놀리식 레포지토리는 프론트엔드와 백엔드를 포함한 모든 애플리케이션의 코드를 하나의 레포지토리에서 관리합니다. 이는 전통적인 방식으로, 작은 규모의 프로젝트에서 자주 사용됩니다.
- 장점:
- 간단한 관리: 모든 코드를 한 곳에서 관리하므로 의존성 관리가 쉽습니다.
- 배포 간편: 전체 애플리케이션을 한 번에 배포할 수 있어 관리 및 배포가 단순합니다.
- 단점:
- 확장성 부족: 애플리케이션이 커질수록 빌드 시간과 의존성 관리가 어려워집니다.
- 협업 제약: 대규모 팀이 병렬로 작업하기 어렵습니다. 한 부분의 수정이 전체 애플리케이션에 영향을 줄 수 있습니다.
monolithic-repo/
|-- src/
| |-- frontend/
| |-- backend/
|-- package.json
|-- README.md
2. Monorepo (단일 레포지토리)
모든 마이크로 프론트엔드 프로젝트를 하나의 레포지토리에서 관리하는 방식입니다. 각 마이크로 프론트엔드가 독립적인 모듈로 구성되지만, 레포지토리 안에서 함께 관리됩니다. 프로젝트의 일관성 유지와 협업이 필요한 상황에서 유리합니다.
-
장점:
- 중앙화된 관리: 의존성을 공유하며 모든 모듈을 같은 레포지토리에서 관리합니다.
- 팀 간 협업 향상: 동일한 코드베이스에서 작업하기 때문에 협업이 용이합니다.
- 일관된 빌드와 배포: 하나의 CI/CD 파이프라인에서 모든 모듈을 관리할 수 있습니다.
-
단점:
- 프로젝트가 커지면 복잡성 증가: 프로젝트가 확장될수록 의존성 충돌과 빌드 시간이 늘어날 수 있습니다.
- 각 모듈의 독립성 저하: 모듈 간의 강한 의존성으로 인해 독립적인 배포가 어려울 수 있습니다.
monorepo/
|-- frontend/
| |-- product/
| |-- cart/
|-- backend/
| |-- api/
| |-- database/
|-- package.json
|-- lerna.json
|-- README.md
3. Multirepo (다중 레포지토리)
각 마이크로 프론트엔드를 별도의 레포지토리에서 관리하는 방식입니다. 모듈 간의 완전한 독립성을 보장하며, 각 모듈은 별도의 레포지토리에서 독립적으로 배포 및 관리됩니다.
-
장점:
- 독립적 배포: 각 모듈이 완전히 분리되어 독립적으로 배포, 확장할 수 있습니다.
- 자유로운 기술 선택: 각 팀이 원하는 기술 스택을 자유롭게 선택해 사용할 수 있습니다.
-
단점:
- 복잡한 통합: 여러 레포지토리를 통합하는 과정이 복잡해지고, 의존성 관리가 어려울 수 있습니다.
- 종속성 관리 어려움: 각 레포지토리 간 버전 관리 및 종속성 충돌 문제가 발생할 수 있습니다.
product-repo/
|-- src/
|-- package.json
|-- README.md
cart-repo/
|-- src/
|-- package.json
|-- README.md
4. Metarepo (메타 레포지토리)
각 마이크로 프론트엔드가 개별 레포지토리에서 관리되지만, 중앙에 이들을 통합하는 메타 레포지토리가 존재하는 방식입니다. 독립성과 통합을 균형 있게 유지할 수 있습니다.
-
장점:
- 독립성과 중앙화의 균형: 각 팀이 독립적으로 작업할 수 있으며, 중앙에서 통합 관리를 할 수 있습니다.
- 중앙 집중식 빌드 및 배포: 중앙 메타 레포지토리에서 통합된 배포를 관리할 수 있습니다.
-
단점:
- 복잡성 증가: 관리해야 할 레포지토리가 많아지면서 복잡성이 증가합니다.
- 협업 문제: 중앙 메타 레포지토리에서의 충돌이 발생할 수 있으며, 이로 인해 팀 간 협업이 어려울 수 있습니다.
metarepo/
|-- integration/
|-- product-repo/
| |-- src/
|-- cart-repo/
| |-- src/
|-- package.json
|-- README.md
결론
- 마이크로 프론트엔드는 복잡하고 다기능을 가진 글로벌 서비스나 대규모 애플리케이션에 적합합니다. 다국적 이커머스 플랫폼, 소셜 미디어, 스트리밍 서비스 등이 해당됩니다.
- 모놀리식 프론트엔드는 간단하고 기능이 제한적인 서비스에 적합합니다. 초기 스타트업 웹 애플리케이션, 작은 프로젝트 또는 단일 기능 서비스가 그 예입니다.
마이크로 프론트엔드는 대규모, 복잡한 애플리케이션에 적합하며, 독립적인 배포와 확장성을 제공하지만 관리 복잡도가 증가할 수 있습니다. 반면, 모놀리식 프론트엔드는 소규모 프로젝트에 적합하며, 개발 및 배포가 간단하다는 장점이 있습니다.
프로젝트의 성격, 팀의 구조, 기술적 요구 사항을 고려하여 적절한 아키텍처를 선택하는 것이 성공적인 애플리케이션 개발의 핵심입니다.