본문으로 건너뛰기

Micro Frontends

무료2019-10-26#Front-End#Mind#微前端#前端Bundle化#前端多框架并存#微前端与组件化#微前端框架

마이크로 프론트엔드 모드는 도대체 무엇일까요?

一.简介

庞大한 한 덩어리의 백엔드 서비스로 인한 변경 및 확장方面的 제한을 해결하기 위해, 마이크로서비스 아키텍처 (Microservices) 가 나타났습니다:

微服务是面向服务架构(SOA)的一种变体,把应用程序设计成一系列松耦合的细粒度服务,并通过轻量级的通信协议组织起来

具体地,将应用构建成一组小型服务。这些服务都能够独立部署、独立扩展,每个服务都具有稳固的模块边界,甚至允许使用不同的编程语言来编写不同服务,也可以由不同的团队来管理

그러나 점점 무거워지는 프론트엔드 엔지니어링도 동일한 문제에 직면하고, 자연스럽게 마이크로서비스 사상을적용 (그대로) 프론트엔드에 응용하는 것을 생각하게 되었고, 이렇게 해서*마이크로 프론트엔드 (micro-frontends)*개념이 탄생했습니다:

Micro frontends, An architectural style where independently deliverable frontend applications are composed into a greater whole.

즉, 독립적으로 배포 가능한 여러 프론트엔드 애플리케이션으로 전체를 구성하는 아키텍처 스타일입니다. 구체적으로는, 프론트엔드 애플리케이션을 더 작고, 더 단순하며 독립적으로 개발, 테스트, 배포 가능한 작은 조각으로 분해하고, 사용자からは 여전히 응집된 단일 제품으로 보이도록 합니다:

Decomposing frontend monoliths into smaller, simpler chunks that can be developed, tested and deployed independently, while still appearing to customers as a single cohesive product.

二.特点

간단히 말해, 마이크로 프론트엔드의 이념은 마이크로서비스와 유사합니다:

In short, micro frontends are all about slicing up big and scary things into smaller, more manageable pieces, and then being explicit about the dependencies between them.

庞大한 전체를 제어 가능한 작은 조각으로 분할하고, 그들 사이의 의존관계를 명확히 합니다. 주요 이점은 다음과 같습니다:

  • 코드베이스가 더 작고, 더 응집성이 높으며, 유지보수성이 향상

  • 느슨하게 결합되고 자율적인 팀의 확장성이 향상

  • 점진적으로 업그레이드, 업데이트, 심지어 일부 프론트엔드 기능의 재작성이 가능해짐

简单、松耦合的代码库

한 덩어리의 프론트엔드 코드베이스와 비교하여, 마이크로 프론트엔드 아키텍처 하의 코드베이스는 더 작고/단순하며, 개발이 용이한 경향이 있습니다

더욱 중요한 것은, 모듈 간의 불합리한 암묵적 결합으로 인한 복잡성 상승을回避하는 것입니다. 명확하게 정의된 애플리케이션 경계를 통해 예기치 않은 결합 가능성을 낮추고, 서브애플리케이션 간 논리 결합 비용을 증가시키며, 개발자에게 애플리케이션 내 데이터와 이벤트의 흐름을 명확히 하도록 촉진합니다

增量升级

이상적인 코드는 당연히 모듈이 명확하고, 의존관계가 명확하며, 확장이 용이하고, 유지보수가 convenient 한 것입니다……그러나 실천에서는 다양한 이유로 인해:

  • 역사 프로젝트, 조상 대대로 내려온 코드

  • 납품プレッシャー, 당시에는 속도를 추구

  • 가깝고 익숙함, 당시에는 안정을 추구……

항상 그다지 이상적이지 않은 코드가 존재합니다:

  • 기술 스택이 낡았으며, 심지어 무리하게 여러 기술 스택을 혼용

  • 결합이 혼란스럽고, 손을 댈 수 없으며, 일부를 움직이면 전체에 영향

  • 리팩토링이 불철저하며, 리팩토링 - 中途半端, 다른 방식으로 리팩토링 - 또 中途半端……

이러한 코드를 완전히 리팩토링하는 경우, _최대의 문제는 충분한 리소스를 마련하여 한 번에 완료하는 것이 매우 어렵다_는 것입니다. 점진적으로 리팩토링하면서, 중간 버전이 원활하게 이전될 수 있음을 확보함과 동시에, 신기능을 지속적으로 배포해야 합니다:

In order to avoid the perils of a full rewrite, we'd much prefer to strangle the old application piece by piece, and in the meantime continue to deliver new features to our customers without being weighed down by the monolith.

따라서, 점진적 리팩토링을 실시하기 위해,新旧코드調和共存하고, 그 후 점차旧코드변환하고, 리팩토링이 완료될 때까지 계속할 수 있는 증분 업그레이드 능력이 필요합니다

이 증분 업그레이드 능력은, 제품 기능의 저위험 부분 교체 를 가능하게 합니다. 의존항목 업그레이드, 아키텍처 교체, UI 개편 등을 포함합니다. 한편, 기술 선택의 유연성을 가져오고, 신기술, 새로운 인터랙션 모드의 실험적 시행착오에 도움이 됩니다

独立部署

독립 배포 능력은 마이크로 프론트엔드 시스템에서 매우 중요하며, 변경 범위를 축소하고 관련 리스크를 낮출 수 있습니다

따라서, 각 마이크로 프론트엔드는 자체 지속적 전달 파이프라인 (빌드, 테스트, 프로덕션 환경 배포 포함) 을 가져야 하며, 독립적으로 배포 가능하고, 다른 코드베이스나 전달 파이프라인의 현재 상태를 과도하게 고려할 필요가 없습니다:

오래된 시스템이 고정 주기의 분기별 릴리스 또는 수동 릴리스라도, 옆 팀이 미완성 또는 문제 있는 기능을 실수로 릴리스해도 상관없습니다. 즉, 마이크로 프론트엔드가 릴리스 준비 완료라면, 언제든지 릴리스 가능해야 하며, 개발 유지보수하는 팀에 의해 결정되어야 합니다

P.S.게다가 BFF 모드 와 결합하여 한 걸음 더 나아간 독립성을 실현할 수도 있습니다:

团队自治

코드베이스 및 릴리스 주기의 결합 해제 외에도, 마이크로 프론트엔드는 완전히 독립된 팀 형성에도 도움이 되며, 다른 팀이 각각 제품 기능의 구상부터 릴리스까지의 전 과정을 담당하고, 팀은 고객에게 가치를 제공하는 데 필요한 모든 것을 완전히 소유하여 신속하고 효율적으로 운영할 수 있습니다

이를 위해, 기술 기능을 기반으로 분할하는 것이 아니라, 비즈니스 기능을 중심으로 수직方向으로 팀을 편성해야 합니다. 가장 간단하게는, 최종 사용자가 볼 수 있는 콘텐츠를 기반으로 분할할 수 있습니다. 예를 들어, 애플리케이션 내의 각 페이지를 마이크로 프론트엔드로 하여, 하나의 팀에 전권负责시킵니다. 기술 기능 또는 횡단적 관심사 (스타일, 폼, 검증 등) 를 기반으로 편성된 팀과 비교하여, 이 방식은 팀 작업의 응집력을 향상시킬 수 있습니다

三.实现方案

구현상, 중요한 문제 는 다음과 같습니다:

  • 여러 Bundle 을 어떻게 통합할까?

  • 서브애플리케이션 간에 어떻게 영향을 격리할까?

  • 공공 리소스를 어떻게 재사용할까?

  • 서브애플리케이션 간에 어떻게 통신할까?

  • 어떻게 테스트할까?

多 Bundle 集成

마이크로 프론트엔드 아키텍처에는 일반적으로*컨테이너 애플리케이션 (container application)*이 있어 각 서브애플리케이션을 통합합니다. 책임은 다음과 같습니다:

  • 공공 페이지 요소 렌더링, 예를 들어 header, footer

  • 횡단적 관심사 (cross-cutting concerns) 해결, 인증 및 내비게이션 등

  • 각 마이크로 프론트엔드를 하나의 페이지로 통합하고, 마이크로 프론트엔드의 렌더링 영역과 타이밍 제어

통합 방식은 3 종류로 분류됩니다:

  • 서버 측 통합: 예를 들어 SSR 템플릿 조립

  • 빌드 시 통합: 예를 들어 Code Splitting

  • 런타임 통합: 예를 들어 iframe, JS, Web Components 등의 방식

服务端集成

서버 측 통합의 핵심은각 부분의 템플릿 (각 마이크로 프론트엔드) 이 독립적으로 릴리스할 수 있음을 어떻게 보장할까입니다. 필요하면, 서버 측에도 프론트엔드에 대응하는 구조를 구축할 수도 있습니다:

각 서브서비스가 대응하는 마이크로 프론트엔드를 렌더링하여 서비스를 제공하고, 메인 서비스가 각 서브서비스에 리퀘스트를 전송

构建时集成

일반적인 빌드 시 통합 방식은 서브애플리케이션을 독립적인 npm 패키지로 릴리스하고, 메인 애플리케이션의 의존항목으로 공동으로, 배포용 JS Bundle 을 하나 구축 생성하는 것입니다

그러나, _빌드 시 통합의 최대 문제는 릴리스 단계에서 결합을 일으킨다_는 것입니다. 서브애플리케이션에 변경이 있으면, 전체를 재컴파일해야 하며, 제품의 부분적인 소변경도 새 버전을 릴리스해야 함을 의미합니다. 따라서, 이 방식은 권장되지 않습니다

运行时集成

통합 타이밍을 빌드 시에서 런타임으로 늦추면, 릴리스 단계의 결합을回避할 수 있습니다. 일반적인 런타임 통합 방식에는 다음과 같습니다:

  • iframe

  • JS: 예를 들어 프론트엔드 루트

  • Web Components

직관적으로는 iframe 이 좋지 않아 보입니다 (퍼포먼스, 통신 비용 등). 그러나 여기서는 확실히 합리적인 선택지입니다. iframe 은 확실히 가장 간단한 방식이며, 스타일 격리 및 글로벌 변수 격리를 자연스럽게 지원하기 때문입니다

그러나, 이*네이티브한 격리성은, 애플리케이션의 각 부분을 함께 연결하는 것이 매우 어렵다_는 것을 의미하며, 루트 제어, 히스토리 스택 관리, 딥링크 (deep-linking), 반응형 레이아웃 등이 비정상적으로 복잡해져, iframe 방안의 유연성을 제한합니다

또 다른 가장 일반적인 방식은 프론트엔드 루트로, 각 서브애플리케이션이 렌더링 함수를 공개하고, 메인 애플리케이션이 기동 시 각 서브애플리케이션의 독립 Bundle 을 로드한 후, 루트 규칙에 따라 대응하는 서브애플리케이션을 렌더링합니다. 현재 보면, 가장 유연한 방식입니다

또 다른 유사 방식은 Web Components 로, 각 서브애플리케이션을 커스텀 HTML 요소로 캡슐화하고 (프론트엔드 루트 방안의 렌더링 함수가 아님), Shadow DOM 에 의한 스타일 격리 등의 이점을 획득합니다

影响隔离

서브애플리케이션 간, 및 서브애플리케이션과 메인 애플리케이션 간의 스타일, 스코프 격리는 반드시 고려해야 할 문제이며, 일반적인 해결책은 다음과 같습니다:

资源复用

리소스 재사용은 UI 일관성과 코드 재사용에 중요한 의미가 있지만, 모든 재사용 가능한 리소스 (컴포넌트 등) 를 처음부터 재사용을 위해 끌어낼 필요는 없습니다. 권장되는 방식은, 전기에 어느 정도의 중복을 허용하고, 각 Bundle 이 각각의 코드베이스에서 컴포넌트를 생성하며, 비교적 명확한 컴포넌트 API 가 형성될 때까지 기다린 후 재사용 가능한 공공 컴포넌트를 구축하는 것입니다

한편, 리소스는 다음과 같은 3 종류로 분류됩니다:

  • 기초 리소스: 로직 기능을 전혀 포함하지 않는 아이콘, 태그, 버튼 등

  • UI 컴포넌트: 일정 UI 로직을 포함한 검색박스 (자동 완성 등), 테이블 (정렬, 필터, 페이지네이션 등) 등

  • 비즈니스 컴포넌트: 비즈니스 로직을 포함

그 중에서, 서브애플리케이션 간 비즈니스 컴포넌트 재사용은 권장되지 않습니다. 고도의 결합을 일으키고, 변경 비용을 증가시키기 때문입니다

공공 리소스의 소속 및 관리에 대해서는, 일반적으로 두 가지 모드가 있습니다:

  • 공공 리소스는 모든 사람에게 소속, 즉 명확한 소속이 없음

  • 공공 리소스는 집중 관리,专人负责

실천 경험에서 보면, 전자는 명확한 규범이 없고, 기술 비전에서 일탈한 어지러운 집합이 되기 쉽고, 후자는 리소스 생성과 사용의 탈절을 일으킵니다. 비교적 권장되는 모드는오픈소스 소프트웨어의 관리 모드입니다:

Anyone can contribute to the library, but there is a custodian (a person or a team) who is responsible for ensuring the quality, consistency, and validity of those contributions.

즉, 누구나 공공 리소스를 보충할 수 있지만, 품질, 일관성, 정확성을 보장하기 위해 감시하는 사람 (또는 팀) 이 있어야 합니다

应用间通信

커스텀 이벤트 를 통한 간접 통신은 직접 결합을回避하는 일반적인 방식입니다. 게다가, React 의 단방향 데이터 플로우 모델도 의존관계를 더 명확히 할 수 있으며, 마이크로 프론트엔드에 대응하면, 컨테이너 애플리케이션에서 서브애플리케이션에 데이터와 콜백 함수를 전달합니다

게다가, 루트 파라미터는 공유, 북마크 등의 시나리오에 사용할 수 있을 뿐만 아니라, 통신 수단으로도 사용할 수 있으며, 많은 이점이 있습니다:

  • 구조가 정의된 오픈 스탠다드를 따름

  • 페이지 레벨 공유, 글로벌 액세스 가능

  • 길이 제한으로 인해, 필요한 소량 데이터만 전달하도록 촉진

  • 사용자 지향, 도메인 모델링에 도움이 됨

  • 선언적, 의미적으로 더 일반적 ("this is where we are", rather than "please do this thing")

  • 서브애플리케이션 간에 간접 통신을 강제하며, 직접 상대를 의존하지 않음

그러나 원칙적으로, 어떤 방식을 채택하더라도, 서브애플리케이션 간 통신을 가능한 한 축소해야 합니다. 대량의 약한 의존으로 인한 강한 결합을回避하기 위함입니다

测试

각 서브애플리케이션은 자체 완전한 테스트 방안을 가져야 하며, 특수한 점은, 유닛 테스트, 기능 테스트 외에, 통합 테스트 도 필요합니다:

  • 통합 테스트: 서브애플리케이션 간 통합의 정확성을 보장, 예를 들어 서브애플리케이션 횡단 인터랙션 조작

  • 기능 테스트: 페이지 조립의 정확성을 보장

  • 유닛 테스트:底层 비즈니스 로직과 렌더링 로직의 정확성을 보장

아래에서 위로 피라미드 구조를 형성하며, 각 층은 그 하층에서 커버하지 못하는 부분만 검증하면 됩니다

四.示例

五.缺点

물론, 이 아키텍처 모드는 백리 있어 일해 없지가 않으며, 몇 가지 문제도随之而来ます:

  • 의존항목의 중복을 일으키고, 사용자의 트래픽 부담을 증가

  • 팀 자치도의 증가, 협업을 파괴할 가능성

流量负担

독립 구축은 공공 리소스의 중복을 의미하며, 사용자의 트래픽 부담을 증가합니다

매우 이상적인 해결책은 없습니다. 간단한 방안은 공공 의존을 (서브애플리케이션의) 구축 산물에서 제외하는 것이지만, 빌드 시 결합을 도입합니다:

Now there is an implicit contract between them which says, "we all must use these exact versions of these dependencies".

操作/管理上的复杂性

마이크로 프론트엔드를 채택하기 전에, 먼저 몇 가지 문제를 고려해야 합니다:

  • 기존 프론트엔드 개발, 테스트, 릴리스 플로우를 어떻게 확장하여 많은 애플리케이션을 지원할까?

  • 분산된, 제어가 약화된 툴 시스템 및 개발 실천은 신뢰할 수 있을까?

  • 다양한 프론트엔드 코드베이스에 대해, 어떻게 품질 기준을 구축할까?

总之, 이전과不同的是, 마이크로 프론트엔드는一堆의 작은 것을 생성합니다. 따라서, 이 방법을 채택하기 위해 필요한 기술과 조직의 성숙도를 갖추고 있는가를 고려해야 합니다

六.总结

백엔드에 대한 마이크로서비스와 유사하게, 프론트엔드 비즈니스도 어느 규모로 발전한 후, 복잡도를 분해하기 위한 아키텍처 모드가 필요해지고, 이렇게 해서마이크로서비스 사상의 프론트엔드 영역에서의 응용, 즉 마이크로 프론트엔드가 나타났습니다. 주요 목적은 다음과 같습니다:

  • 기술 아키텍처상의 더욱 확장성 (모듈 경계가 명확, 의존관계가 명확)

  • 팀 조직상의 자치권

  • 개발 플로우상에서 독립 개발, 독립 전달이 가능

최대의 의의는여러 기술 스택 병존 능력을 언락한 것으로, 특히 점진적 리팩토링 중 아키텍처 업그레이드 과도기에 적합합니다:

Suddenly we are not tightly coupled with one stack only, we can refactor legacy projects supporting the previous stack and a new one that slowly but steadily kicks into production environment without the need of a big bang releases (see strangler pattern).

저비용으로 신기술 스택을 시도하는 것을 허용하며, 심지어 가장 적합한 기술 스택을 선택하여 다른 일을 하는 것을 허용합니다 (마이크로서비스에서 다른 언어로 다른 서비스를 작성하는 것을 허용하는 것과 유사):

we can use different version of the same library or framework in production without affecting the entire application, we can try new frameworks or approaches seeing real performances in action, we can hire the best people from multiple communities and many other advantages.

参考資料

  • Micro Frontends

  • [I don't understand micro-frontends.](https://medium.com/ @lucamezzalira/i-dont-understand-micro-frontends-88f7304799a9)

  • Micro Frontends

  • [Micro frontends—a microservice approach to front-end web development](https://medium.com/ @tomsoderlund/micro-frontends-a-microservice-approach-to-front-end-web-development-f325ebdadc16)

댓글

아직 댓글이 없습니다

댓글 작성