마이크로 프론트엔드의 장점과 장점
게시 됨: 2022-03-11마이크로 프론트엔드 아키텍처는 프론트엔드 앱이 느슨하게 함께 작동하는 반독립적인 개별 "마이크로 앱"으로 분해되는 디자인 접근 방식입니다. 마이크로 프론트엔드 개념은 마이크로서비스에서 막연하게 영감을 받아 명명되었습니다.
마이크로 프론트엔드 패턴의 이점은 다음과 같습니다.
- 마이크로 프론트엔드 아키텍처는 더 간단할 수 있으므로 추론하고 관리하기가 더 쉽습니다.
- 독립적인 개발 팀은 프론트엔드 앱에서 보다 쉽게 협업할 수 있습니다.
- "새" 앱을 나란히 실행하여 "이전" 앱에서 마이그레이션하는 방법을 제공할 수 있습니다.
최근 마이크로 프론트엔드가 많은 관심을 받고 있지만, 아직까지 단일한 지배적인 구현도 없고 명확한 "최고의" 마이크로 프론트엔드 프레임워크도 없습니다. 실제로 목표와 요구 사항에 따라 다양한 접근 방식이 있습니다. 더 잘 알려진 구현에 대해서는 참고 문헌을 참조하십시오.
이 기사에서 우리는 마이크로 프론트엔드 이론의 많은 부분을 건너뛸 것입니다. 다루지 않을 내용은 다음과 같습니다.
- 앱을 마이크로앱으로 "슬라이싱"
- 마이크로 프론트엔드가 CI/CD 모델에 맞는 방법을 포함한 배포 문제
- 테스트
- 마이크로앱이 백엔드의 마이크로서비스와 일대일 정렬되어야 하는지 여부
- 마이크로 프론트엔드 개념에 대한 비판
- 마이크로 프론트엔드와 기존 구성 요소 아키텍처의 차이점
대신, 마이크로 프론트엔드 아키텍처의 중요한 문제와 가능한 솔루션을 강조하여 구체적인 구현에 중점을 둔 마이크로 프론트엔드 자습서를 제공합니다.
우리의 구현을 Yumcha라고 합니다. 광둥어로 "얌차"의 문자적 의미는 "차 마시기"이지만 일상적인 의미는 "딤섬 먹으러 가다"입니다. 여기에서 아이디어는 매크로앱 내의 개별 마이크로앱(구성된 최상위 앱이라고 칭함 )이 딤섬 점심에 나오는 한입 크기의 다양한 바구니와 유사하다는 것입니다.
우리는 때때로 Yumcha를 "마이크로 프론트엔드 프레임워크"라고 부를 것입니다. 오늘날의 세계에서 "프레임워크"라는 용어는 일반적으로 Angular, React, Vue.js 또는 웹 앱에 대한 기타 유사한 상부 구조를 나타내는 데 사용됩니다. 우리는 그런 의미에서 프레임워크에 대해 전혀 이야기하고 있지 않습니다. 우리는 편의상 Yumcha 프레임워크라고 부릅니다. 실제로는 마이크로 프론트엔드 기반 앱을 구축하기 위한 도구와 몇 가지 얇은 레이어에 가깝습니다.
마이크로 프론트엔드 튜토리얼 첫 단계: 작성된 앱에 대한 마크업
매크로 앱과 이를 구성하는 마이크로 앱을 정의하는 방법에 대해 생각해 보겠습니다. 마크업은 항상 웹의 핵심이었습니다. 따라서 매크로 앱은 다음 마크업보다 더 복잡한 것으로 지정되지 않습니다.
<html> <head> <script src="/yumcha.js"></script> </head> <body> <h1>Hello, micro-frontend app.</h1> <!-- HERE ARE THE MICROAPPS! --> <yumcha-portal name="microapp1" src="https://microapp1.example.com"></yumcha-portal> <yumcha-portal name="microapp2" src="https://microapp2.example.com"></yumcha-portal> </body> </html>
마크업을 사용하여 매크로 앱을 정의하면 HTML 및 CSS의 기능에 완전히 액세스하여 마이크로 앱을 배치하고 관리할 수 있습니다. 예를 들어, 하나의 마이크로앱은 다른 것의 상단이나 측면에 놓이거나 페이지 모서리에 있거나 아코디언의 한 창에 있거나 어떤 일이 발생할 때까지 숨겨져 있거나 백그라운드에 영구적으로 남아 있을 수 있습니다. .
"포털"은 마이크로 프론트엔드에서 사용할 표준 HTML 요소를 정의하려는 초기 시도인 포털 제안에 사용된 마이크로앱에 대한 유망한 용어이기 때문에 마이크로 앱에 사용되는 사용자 정의 요소 이름을 <yumcha-portal>
지정했습니다.
<yumcha-portal>
사용자 정의 요소 구현
<yumcha-portal>
을 어떻게 구현해야 할까요? 물론 웹 구성 요소로 사용자 정의 요소이기 때문에! 우리는 마이크로 프론트엔드 웹 구성 요소를 작성하고 컴파일하기 위해 여러 강력한 경쟁자 중에서 선택할 수 있습니다. 여기서 우리는 폴리머 프로젝트의 최신 버전인 LitElement를 사용할 것입니다. LitElement는 대부분의 사용자 지정 요소 상용구를 처리하는 TypeScript 기반 구문 설탕을 지원합니다. <yumcha-portal>
을 페이지에서 사용할 수 있도록 하려면 위에서 했던 것처럼 관련 코드를 <script>
로 포함해야 합니다.
하지만 <yumcha-portal>
은 실제로 무엇을 합니까? 첫 번째 근사치는 지정된 소스로 iframe
을 생성하는 것입니다.
render() { return html`<iframe src=${this.src}></iframe>`; }
...여기서 render
는 html
태그가 지정된 템플릿 리터럴을 사용하는 표준 LitElement 렌더링 후크입니다. 이 최소한의 기능은 일부 사소한 사용 사례에 거의 충분할 수 있습니다.
iframe
s에 Microapp 포함
iframe
은 모두가 싫어하기를 좋아하는 HTML 요소이지만 실제로는 매우 유용하고 견고한 샌드박싱 동작을 제공합니다. 그러나 iframe
을 사용할 때 우리 앱의 동작과 기능에 잠재적인 영향을 줄 수 있다는 점을 인지해야 하는 긴 목록의 문제가 여전히 남아 있습니다.
- 첫째,
iframe
은 크기와 레이아웃 측면에서 잘 알려진 단점이 있습니다. - 물론 CSS는 좋든 나쁘든
iframe
에 완전히 격리 됩니다. - 브라우저의 "뒤로" 버튼은 합리적으로 잘 작동하지만
iframe
의 현재 탐색 상태는 페이지의 URL에 반영되지 않으므로 구성된 앱과 딥 링크의 동일한 상태에 도달하기 위해 URL을 잘라내어 붙여넣을 수 없습니다. 그들에게. - CORS 설정에 따라 외부에서
iframe
과 통신 하려면postMessage
프로토콜을 거쳐야 할 수도 있습니다 . -
iframe
경계를 넘어 인증을 위해 준비해야 합니다. - 일부 스크린 리더는
iframe
경계에서 비틀거리거나iframe
에 사용자에게 알릴 수 있는 제목이 필요할 수 있습니다.
이러한 문제 중 일부는 이 기사 뒷부분에서 논의할 대안인 iframe
을 사용하지 않음으로써 방지하거나 완화할 수 있습니다.
플러스 측면에서 iframe
에는 자체적인 독립적인 Content-Security-Policy
(CSP)이 있습니다. 또한 iframe
이 가리키는 마이크로 앱이 서비스 워커를 사용하거나 서버 측 렌더링을 구현하면 모든 것이 예상대로 작동합니다. iframe
에 다양한 샌드박싱 옵션을 지정하여 상단 프레임으로 이동하는 것과 같은 기능을 제한할 수도 있습니다.
일부 브라우저는 iframe
에 대해 loading=lazy
속성을 제공했거나 제공할 계획입니다. 이 속성은 사용자가 근처에서 스크롤할 때까지 스크롤 없이 볼 수 있는 iframe
로드를 지연하지만 지연 로드에 대한 세밀한 제어를 제공하지 않습니다. 우리는 원한다.
iframe
의 실제 문제는 iframe
의 내용이 검색하는 데 여러 네트워크 요청이 필요하다는 것입니다. 최상위 index.html
이 수신되고 해당 스크립트가 로드되고 HTML이 구문 분석됩니다. 그러나 그런 다음 브라우저는 iframe
의 HTML에 대한 또 다른 요청을 시작하고, 수신을 대기하고, 해당 스크립트를 구문 분석 및 로드하고, iframe
의 내용입니다. 많은 경우에 iframe
의 JavaScript는 여전히 회전하고 자체 API 호출을 수행하고 해당 API 호출이 반환되고 데이터가 보기 위해 처리된 후에만 의미 있는 데이터를 표시해야 합니다.
이로 인해 특히 여러 마이크로앱이 관련된 경우 바람직하지 않은 지연 및 렌더링 아티팩트가 발생할 수 있습니다. iframe
의 앱이 SSR을 구현하면 도움이 되지만 여전히 추가 왕복 여행의 필요성을 피할 수는 없습니다.
따라서 포털 구현을 설계할 때 직면하는 주요 과제 중 하나는 이 왕복 문제를 처리하는 방법입니다. 우리의 목표는 단일 네트워크 요청으로 각 마이크로앱이 미리 채울 수 있는 콘텐츠를 포함하여 모든 마이크로앱이 있는 전체 페이지를 중단하는 것입니다. 이 문제에 대한 해결책은 Yumcha 서버에 있습니다.
얌차 서버
여기에 제시된 마이크로 프론트엔드 솔루션의 핵심 요소는 마이크로앱 구성을 처리할 전용 서버를 설정하는 것입니다. 이 서버는 각 마이크로앱이 호스팅되는 서버에 요청을 프록시합니다. 물론 이 서버를 설정하고 관리하려면 약간의 노력이 필요합니다. 일부 마이크로 프론트엔드 접근 방식(예: 단일 스파)은 배포 및 구성의 용이성이라는 명목으로 이러한 특수 서버 설정의 필요성을 없애려고 합니다.
그러나 이 역방향 프록시를 설정하는 비용은 우리가 얻는 이점으로 상쇄됩니다. 사실, 마이크로 프론트엔드 기반 앱에는 그것 없이는 달성할 수 없는 중요한 동작이 있습니다. 이러한 역 프록시를 설정하는 데 사용할 수 있는 상용 및 무료 대안이 많이 있습니다.
역방향 프록시는 마이크로앱 요청을 적절한 서버로 라우팅하는 것 외에도 매크로앱 요청을 매크로앱 서버로 라우팅합니다. 해당 서버는 구성된 앱의 HTML을 특별한 방식으로 정리합니다. http://macroapp.example.com
과 같은 URL에서 프록시 서버를 통해 브라우저에서 index.html
에 대한 요청을 받으면 index.html
을 검색한 다음 반환하기 전에 간단하지만 중요한 변환을 수행합니다. 그것.
특히 HTML은 <yumcha-portal>
태그에 대해 구문 분석되며, 이는 Node.js 생태계에서 사용할 수 있는 유능한 HTML 파서 중 하나로 쉽게 수행할 수 있습니다. <yumcha-portal>
에 대한 src
속성을 사용하여 마이크로앱을 실행하는 서버에 연결하고 해당 index.html
(있는 경우 서버 측 렌더링 콘텐츠 포함)을 검색합니다. 결과는 HTML 응답에 <script>
또는 <template>
태그로 삽입되어 브라우저에서 실행되지 않습니다.

이 설정의 장점은 무엇보다도 작성된 페이지에 대한 index.html
에 대한 첫 번째 요청에서 서버가 개별 마이크로앱 서버에서 개별 페이지를 전체적으로 검색할 수 있다는 것입니다. any - 추가 서버 왕복 없이 iframe
을 채우는 데 사용할 수 있는 콘텐츠를 포함하여 완전한 단일 페이지를 브라우저에 제공합니다(underused srcdoc
속성 사용). 프록시 서버는 또한 마이크로앱이 제공되는 위치에 대한 모든 세부 정보가 엿보는 눈으로부터 은폐되도록 합니다. 마지막으로 애플리케이션 요청이 모두 동일한 출처에서 이루어지기 때문에 CORS 문제를 단순화합니다.
클라이언트로 돌아 <yumcha-portal>
태그가 인스턴스화되고 서버가 응답 문서에 배치한 콘텐츠를 찾고 적절한 시간에 iframe
을 렌더링하고 콘텐츠를 srcdoc
속성에 할당합니다. iframe
을 사용하지 않는 경우(아래 참조), 해당 <yumcha-portal>
태그에 해당하는 콘텐츠가 사용자 정의 요소의 shadow DOM(사용 중인 경우)에 삽입되거나 문서에서 직접 인라인됩니다.
이 시점에서 이미 부분적으로 작동하는 마이크로 프론트엔드 기반 앱이 있습니다.
이것은 Yumcha 서버의 흥미로운 기능 측면에서 빙산의 일각에 불과합니다. 예를 들어 마이크로앱 서버의 HTTP 오류 응답을 처리하는 방법 또는 매우 느리게 응답하는 마이크로앱을 처리하는 방법을 제어하는 기능을 추가하고 싶습니다. 응답하다! 이 주제와 다른 주제는 다른 게시물로 남겨 둡니다.
Yumcha macroapp index.html
변환 로직은 서버리스 람다 함수 방식으로 쉽게 구현되거나 Express 또는 Koa와 같은 서버 프레임워크용 미들웨어로 구현될 수 있습니다.
스텁 기반 Microapp 제어
클라이언트 측으로 돌아가서 효율성, 지연 로딩 및 버벅거림 없는 렌더링에 중요한 마이크로앱을 구현하는 방법에 대한 또 다른 측면이 있습니다. 다른 네트워크 요청을 생성하는 src
속성을 사용하거나 서버에 의해 채워진 콘텐츠로 채워진 srcdoc
속성을 사용하여 각 마이크로앱에 대한 iframe
태그를 생성 할 수 있습니다. 그러나 두 경우 모두 사용자가 해당 마이크로앱에 액세스하지 않더라도 모든 스크립트 및 링크 태그 로드, 부트스트래핑, 초기 API 호출 및 관련 데이터 처리를 포함하여 해당 iframe
의 코드가 즉시 시작됩니다.
이 문제에 대한 우리의 솔루션은 처음에 페이지의 마이크로앱을 활성화될 수 있는 작은 비활성화된 스텁으로 표시하는 것입니다. 활성화는 사용되지 않는 IntersectionObserver
API를 사용하여 표시되는 마이크로앱의 영역에 의해 구동되거나 더 일반적으로 외부에서 전송되는 사전 알림에 의해 구동될 수 있습니다. 물론 마이크로앱이 즉시 활성화되도록 지정할 수도 있습니다.
어쨌든 마이크로 앱이 활성화된 경우에만 iframe
이 실제로 렌더링되고 해당 코드가 로드 및 실행됩니다. LitElement를 사용하여 구현하고 활성화 상태가 activated
인스턴스 변수로 표시된다고 가정하면 다음과 같습니다.
render() { if (!this.activated) return html`{this.placeholder}`; else return html` <iframe srcdoc="${this.content}" @load="${this.markLoaded}"></iframe>`; }
마이크로 앱 간 통신
매크로 앱을 구성하는 마이크로 앱은 정의상 느슨하게 결합되어 있지만 여전히 서로 통신할 수 있어야 합니다. 예를 들어 탐색 마이크로앱은 사용자가 방금 선택한 다른 마이크로앱이 활성화되어야 한다는 알림을 보내야 하며 활성화될 앱은 이러한 알림을 수신해야 합니다.
우리의 미니멀리즘적 사고방식에 따라 많은 메시지 전달 기계를 도입하는 것을 피하고 싶습니다. 대신 웹 구성 요소의 정신에서 DOM 이벤트를 사용합니다. 우리는 임박한 이벤트의 모든 스텁에 미리 알리고 해당 이벤트 유형이 활성화되도록 요청한 모든 항목을 기다린 다음 모든 마이크로 앱이 수신할 수 있는 문서에 대해 이벤트를 전달하는 간단한 브로드캐스트 API를 제공합니다. 그것. 모든 iframe
이 동일한 출처임을 감안할 때 iframe
에서 페이지로 또는 그 반대로 손을 뻗어 이벤트를 발생시킬 요소를 찾을 수 있습니다.
라우팅
이 시대에 우리는 모두 SPA의 URL 표시줄이 애플리케이션의 보기 상태를 나타내기 때문에 잘라내고, 붙여넣고, 메일로 보내고, 텍스트로 연결하고, 앱 내 페이지로 직접 이동할 수 있는 링크를 기대하게 되었습니다. 그러나 마이크로 프론트엔드 앱에서 애플리케이션 상태는 실제로 각 마이크로 앱에 대해 하나씩 상태의 조합입니다. 이것을 어떻게 표현하고 통제할 것인가?
솔루션은 각 마이크로앱의 상태를 단일 복합 URL로 인코딩하고 해당 복합 URL을 함께 넣고 분리하는 방법을 알고 있는 작은 매크로앱 라우터를 사용하는 것입니다. 불행히도 이를 위해서는 각 마이크로앱에 Yumcha 관련 로직이 필요합니다. 매크로앱 라우터에서 메시지를 수신하고 마이크로앱 상태를 업데이트하고, 반대로 복합 URL을 업데이트할 수 있도록 매크로앱 라우터에 해당 상태의 변경 사항을 알려야 합니다. 예를 들어, Angular의 경우 YumchaLocationStrategy
또는 React의 경우 <YumchaRouter>
요소를 상상할 수 있습니다.
비 iframe
케이스
위에서 언급했듯이 iframe
에서 마이크로 앱을 호스팅하는 것은 몇 가지 단점이 있습니다. 두 가지 대안이 있습니다. 페이지의 HTML에 직접 인라인으로 포함하거나 shadow DOM에 배치합니다. 두 대안 모두 iframe
의 장단점을 어느 정도 반영하지만 때로는 다른 방식으로 반영됩니다.
예를 들어 개별 마이크로앱 CSP 정책은 어떻게든 병합되어야 합니다. 스크린 리더와 같은 보조 기술은 iframe
보다 더 잘 작동해야 합니다(아직 모두 지원하는 것은 아님). "범위"라는 서비스 워커 개념을 사용하여 마이크로앱의 서비스 워커를 등록하는 것은 간단해야 하지만 앱은 서비스 워커가 "/"
가 아닌 앱 이름으로 등록되었는지 확인해야 합니다. iframe
과 관련된 레이아웃 문제는 인라인 또는 섀도우 DOM 메서드에 적용되지 않습니다.
그러나 Angular 및 React와 같은 프레임워크를 사용하여 빌드된 응용 프로그램은 인라인 또는 Shadow DOM에서 작동하지 않을 가능성이 높습니다. 이를 위해 우리는 iframe
s를 사용하기를 원할 것입니다.
인라인 및 섀도 DOM 메서드는 CSS와 관련하여 다릅니다. CSS는 shadow DOM에 깔끔하게 캡슐화됩니다. 어떤 이유로 외부 CSS를 shadow DOM과 공유하고 싶다면 구성 가능한 스타일시트 또는 이와 유사한 것을 사용해야 합니다. 인라인 마이크로앱을 사용하면 모든 CSS가 페이지 전체에서 공유됩니다.
결국 <yumcha-portal>
에서 인라인 및 섀도우 DOM 마이크로앱에 대한 로직을 구현하는 것은 간단합니다. 서버 로직에 의해 HTML <template>
요소로 페이지에 삽입된 주어진 마이크로앱에 대한 콘텐츠를 검색하고 복제한 다음 일반적으로 요소의 shadow DOM인 LitElement가 renderRoot
라고 부르는 것에 추가합니다. 인라인(섀도우가 아닌 DOM)의 경우 요소 자체( this
)로도 설정됩니다.
하지만 기다려! 마이크로앱 서버에서 제공하는 콘텐츠는 전체 HTML 페이지입니다. html
, head
및 body
태그가 있는 마이크로앱용 HTML 페이지를 매크로앱용 페이지 중간에 삽입할 수 없습니다.
마이크로앱 서버에서 검색된 마이크로앱 콘텐츠가 래핑되는 template
태그의 단점을 활용하여 이 문제를 해결합니다. 최신 브라우저에서 template
태그를 만나면 "실행"하지는 않지만 구문 분석 을 수행하고 <html>
, <head>
및 <body>
태그와 같은 잘못된 콘텐츠를 제거합니다. , 내부 내용을 유지하면서. 따라서 <head>
의 <script>
및 <link>
태그와 <body>
의 내용이 보존됩니다. 이것이 바로 마이크로앱 콘텐츠를 페이지에 삽입하기 위해 원하는 것입니다.
마이크로 프론트엔드 아키텍처: 악마는 디테일에 있다
마이크로 프론트엔드는 (a) 더 나은 아키텍처 접근 방식으로 판명되고 (b) 오늘날 웹의 무수한 실제 요구 사항을 충족하는 방식으로 구현하는 방법을 알아낼 수 있는 경우 웹 앱 생태계에 뿌리를 내릴 것입니다.
첫 번째 질문과 관련하여 아무도 마이크로 프론트엔드가 모든 사용 사례에 적합한 아키텍처라고 주장하지 않습니다. 특히, 단일 팀이 마이크로 프론트엔드를 채택하는 그린필드 개발에 대한 이유는 거의 없습니다. 어떤 유형의 컨텍스트에서 어떤 유형의 앱이 마이크로 프론트엔드 패턴에서 가장 많은 이점을 얻을 수 있는지에 대한 질문은 다른 주석가에게 남겨 두겠습니다.
구현 및 실행 가능성 측면에서 이 기사에서 언급하지 않은 몇 가지, 특히 인증 및 보안, 코드 복제 및 SEO를 포함하여 우려해야 할 세부 사항이 많다는 것을 확인했습니다. 그럼에도 불구하고 이 기사가 마이크로 프론트엔드에 대한 기본 구현 접근 방식을 제시하기를 희망합니다.
서지
- 마이크로 프론트 엔드 - 각진 스타일 - 1부
- 마이크로 프론트 엔드 - 앵귤러 스타일 - 파트 2
- 마이크로프론트엔드를 사용하여 AngularJS 애플리케이션 진화
- 마이크로 프론트엔드
- UI 마이크로서비스 — 안티 패턴 반전(마이크로 프론트엔드)
- UI 마이크로서비스 — 안티패턴?
- Micro-Frontends를 사용한 페이지 구축은 Yumcha와 같은 역 프록시 및 SSI 접근 방식을 사용하므로 적극 권장합니다.
- 마이크로 프론트엔드 리소스
- 지휘대
- 마이크로 프론트엔드를 이해하지 못합니다. 이것은 마이크로 프론트엔드 아키텍처 유형과 사용 사례에 대한 꽤 좋은 개요입니다.
- Vue.js, AWS Lambda 및 Hypernova를 사용하는 서버리스 마이크로 프런트엔드
- Micro Frontends: 훌륭하고 포괄적인 개요입니다.