Back to blog
Jan 18, 2025
6 min read

[번역] How Vercel adopted microfrontends

Vercel이 마이크로프론트엔드를 도입한 방법

원문 : https://vercel.com/blog/how-vercel-adopted-microfrontends

Vercel이 마이크로프론트엔드로 원활한 사용자 경험을 유지하면서 빌드 시간을 단축하고 개발자 속도를 개선한 방법을 알아보세요.

Vercel의 메인 웹사이트는 하나의 대규모 Next.js 애플리케이션으로, 웹사이트 방문자와 로그인한 대시보드에 모두 서비스를 제공합니다. 하지만 Vercel이 성장함에 따라 이러한 설정은 개선의 기회를 제공했습니다. 빌드 시간이 길어지고 종속성 관리가 더 복잡해졌으며 워크플로우 최적화가 필요했습니다. 사소한 변경으로 인해 전체 빌드가 트리거되어 격리된 개발 및 CI 파이프라인에 영향을 미쳤습니다.

변화가 필요한 것은 분명했습니다.

아키텍처를 재고하여 수직형 마이크로프론트엔드로 전환함으로써 개발 환경을 간소화하고 프리뷰 빌드 시간과 로컬 개발 컴파일을 40% 이상 개선했습니다.

또한 다른 마이크로프론트엔드에 대한 코드를 제거하여 종속성을 간소화함으로써 페이지 무게를 줄이고 최종 사용자 성능을 향상시켰으며, LCP(Largest Contentful Paint) 및 INP(Interaction to Next Paint)와 같은 Core Web Vitals의 성능이 향상되었습니다.

이번 개편은 마이크로프론트엔드에 대한 Vercel의 지원을 바탕으로 개발자 경험(DX)을 개선하고 추가 최적화를 위한 영역을 강조했습니다. 대규모 앱 마이그레이션을 *도그푸딩함으로써 모든 사용자를 위해 플랫폼을 간소화할 수 있는 새로운 방법을 발견했습니다. 이 블로그에서는 그간의 여정을 공유함과 동시에 모든 사용자를 위해 원활한 프로세스를 제공할 수 있는 방안도 소개합니다. 계속해서 개선해 나가면서 단일 애플리케이션을 더 빠르게 빌드하여 최종 사용자의 성능 저하 없이 더 뛰어난 DX를 구현할 수 있도록 하고 있습니다.

(* 도그푸딩 : 자사의 제품이나 서비스를 내부 직원들이 먼저 사용해 보는 것)

어떻게 했는지 살펴보겠습니다.

Turbo 활용하기

첫 번째 단계는 로컬 컴파일, 빌드 시간 및 CI 워크플로우를 개선하는 데 집중하는 것이었습니다. Vercel의 모노레포는 turborepo에 의해 구동되며, 이를 통해 Vercel Remote Cache--affected 등의 기능을 사용하여 작업을 최적화할 수 있었습니다. Turbopack을 채택함으로써 로컬 개발 속도가 크게 향상되었습니다. 하지만 이러한 개선 작업을 진행하면서 Vercel.com에 single-app 모델도 더 이상 필요하지 않다는 것을 깨달았습니다. 애플리케이션 내에서 논리적 분할을 통해 모든 빌드 및 컴파일에서 불필요한 작업을 피할 수 있어 개발 속도를 더욱 크게 향상할 수 있었습니다.

수평 또는 수직 분할 고려

마이크로프론트엔드는 대규모 애플리케이션을 더 작고 독립적인 단위로 세분화하여 제품 영역과 엔지니어링 팀에서 병렬 개발할 수 있는 방법을 제공합니다. 단일 애플리케이션은 응집력이 있지만, 마이크로프론트엔드는 애플리케이션과 조직이 모두 성장함에 따라 확장 문제를 해결하는 데 도움이 됩니다.

두 가지 주요 전략이 있습니다.

  • 수직적 마이크로프론트엔드: 경로별 분할, 각 페이지가 단일 앱에서 처리되는 경우
  • 수평적 마이크로프론트엔드: 기능별 분할, 여러 애플리케이션이 동일한 페이지에서 실행되는 기능별 분할

*마이크로프론트엔드에 대한 두 가지 일반적인 접근 방식이 있습니다: 단일 페이지 내의 여러 마이크로프론트엔드(가로 분할) 또는 하나의 마이크로프론트엔드가 전체 페이지를 관리(세로 분할)하는 방식입니다.


정답이나 오답은 없으며 각 방법에는 장단점이 있습니다. 각 접근 방식은 사용 사례에 따라 상당한 이점을 제공할 수 있습니다. 마이크로프론트엔드에 대한 Luca Mezzalira의 책은 이 주제에 대한 좋은 자료입니다.

수직 분할은 일관성을 제공하지만 서로 다른 마이크로프론트엔드에서 지원하는 애플리케이션 간에 전환할 때 탐색이 어려울 수 있습니다. 프리페칭과 같은 기술이나 Chromium의 추측 규칙과 같은 API가 도움이 될 수 있지만 리소스 사용량 증가와 브라우저 지원 제한 등의 한계가 있습니다.

수평 분할을 사용하면 여러 마이크로프론트엔드가 동일한 페이지에서 작동하기 때문에 테스트, 릴리스, 모니터링 및 디버깅이 더 복잡해집니다.

우리는 통합된 모노레포를 유지하면서 빌드 시간을 단축하고 종속성을 단순화하기 위해 사용자가 거의 교차하지 않는 논리 섹션으로 앱을 분할하는 수직 마이크로프론트엔드를 채택했습니다.

초기 테스트 결과 이 접근 방식은 빌드 시간을 절반으로 줄이고 개발과 프로덕션 모두에서 소유권을 간소화하여 개발자가 하나의 애플리케이션에서 작업하는 듯한 느낌을 줄 수 있는 것으로 나타났습니다.

우리의 마이그레이션 과정

다음 단계는 개발이나 사용자 경험에 지장을 주지 않야서 모놀리식 프론트엔드 앱을 더 작은 수직 애플리케이션으로 마이그레이션하는 것이었습니다. 애플리케이션을 세 가지 핵심 영역으로 분류했습니다:

  • 마케팅 (marketing)
  • 문서 (documentation)
  • 로그인 된 대시보드 (logged-in dashboard)

이러한 영역은 자연스럽게 구분되었습니다. 사용자들이 두 영역 사이를 자주 넘나들지 않고, 서로 다른 사용자 인터페이스를 유지하므로 분리하기에 이상적입니다.


*사용자는 단일 마이크로프론트엔드 내에서는 소프트 내비게이션을, 마이크로프론트엔드 간에 이동할 때는 하드 내비게이션를 경험합니다.


Next.js를 사용하기 때문에 수직 마이크로프론트엔드를 지원하는 Next.js 멀티존 기능을 사용했습니다.

점진적인 마이그레이션을 우선순위로 삼았습니다. 원래 코드베이스를 포크하는 대신 완전히 새로운 애플리케이션을 만드는 방법을 선택했습니다. 포크는 겉으로 보기에는 쉬워 보였지만 위험이 따랐을 것입니다. 헤더, 푸터, 디자인 시스템과 같은 공유 구성 요소를 여러 레포지토리에서 복제하고 유지 관리해야 하므로 동기화 문제와 잠재적인 불일치가 발생할 수 있습니다.

모노레포를 계속 사용하고 모노레포 내의 패키지로 코드를 중앙 집중화함으로써 공유 구성 요소의 일관성을 보장하는 동시에 핵심 영역을 쉽고 점진적으로 분리할 수 있었습니다. TurborepoDependency Cruiser와 같은 도구가 이 프로세스를 간소화하는 데 도움이 되었습니다.


*Vercel의 모노레포는 apps 폴더에 독립적인 마이크로프론트엔드로 구성되어 있으며, 모든 앱에서 원활하게 액세스할 수 있도록 공유 패키지를 장려합니다.


feature flag를 사용하여 아직 라이브 상태인 모놀리식 프론트엔드 앱에서 새로운 마이크로 프론트엔드로 트래픽을 점진적으로 라우팅할 수 있었습니다. 이를 통해 위험을 최소화하고 이전 코드를 제거하기 전에 성능 개선 사항을 검증할 수 있었습니다. 새 페이지가 최소 일주일 동안 오류 없이 트래픽을 처리하고 나면 기존 애플리케이션에서 코드를 제거하여 종속성과 빌드 시간을 점진적으로 줄였습니다.


*점진적 마이그레이션 중에는 페이지가 원래 프론트엔드 모놀리스와 새로운 마이크로 프론트엔드 모두에 존재합니다. feature flag는 마이크로프론트엔드 버전이 완전히 라이브될 때까지 라우팅을 제어합니다.


이 모노레포 설정과 수직 분할 접근 방식을 통해 자신감과 통제력을 확보할 수 있었습니다. 일관성을 유지하고 빌드 시간을 단축하며 앱 개발을 단순하게 유지하면서 매우 빠르게 움직일 수 있었습니다.

교훈을 얻고 트레이드오프 관리하기

Vercel.com에 마이크로프론트엔드를 성공적으로 도입한 후, nextjs.org와 별도의 애플리케이션으로 실행되는 2024 Next.js Conf 페이지와 같은 다른 사이트에도 동일한 접근 방식을 확장했습니다. 이 인프라를 통해 개별 영역을 독립적인 애플리케이션으로 추출할 수 있었고, Next.js Conf 팀과 Next.js 개발 팀이 독립적으로 빠르게 반복할 수 있어 개발 주기를 단축할 수 있었습니다.

하지만 문제도 있었습니다. 몇 가지 문제가 발생했고, 특히 실제 사용량을 모니터링하는 Speed Insights와 레이아웃 시프트 및 인터랙션 타이밍 알림을 위한 Vercel Toolbar 같은 도구를 사용하여 성능 저하를 방지하는 데 주력했습니다.

저희는 초기에 마이크로프론트엔드를 로컬과 프리뷰에서 테스트하는 것이 어렵다는 것을 알고 있었습니다. Drafe Mode와 같은 기능이 제대로 작동하지 않았고, 하드 내비게이션과 같은 성능 병목 현상도 알려진 문제였습니다. 이러한 문제를 해결하기 위해 Chromium의 추측 규칙을 사용한 프리페칭 및 프리렌더링과 같은 전략을 채택했습니다.

트레이드오프 극복의 예시입니다:

하드 탐색의 영향을 줄이기 위해 링크가 표시되는 즉시 초기 페이지의 리소스(JavaScript 및 CSS)를 다운로드하여 브라우저 캐시를 프라이밍하는 것부터 시작합니다. 즉, 사용자가 탐색할 때 해당 자산이 캐시에서 로드됩니다. 그러나 페이지에는 여전히 HTML과 같은 나머지 자산을 렌더링하고 가져와야 합니다.

한 단계 더 나아가 사용자가 상호 작용할 때(예: 링크를 탭하는 등) 페이지를 미리 렌더링합니다. 이렇게 하면 모든 네트워크 요청 및 처리를 포함하여 백그라운드에서 페이지가 렌더링되므로 사용자가 페이지에 도착하면 즉각적으로 느껴집니다. 이 접근 방식은 리소스 사용량만 미리 가져오기 및 적절한 시점에 미리 렌더링하여 디바이스 과부하를 방지하면서 원하는 경험을 제공하는 동시에 성능의 균형을 맞춥니다.


*사용자 상호 작용 시 페이지를 미리 렌더링하거나 프리페치하여 성능과 리소스 사용을 최적화하면서 원활한 탐색을 제공합니다.


앞으로의 전망

반복 속도가 개선됨에 따라 플랫폼 전반의 마이크로 프론트엔드를 개선하는 데 두 배의 노력을 기울이고 있습니다. 라우팅 개선, 미리보기 워크플로우 간소화, 하드 내비게이션 성능 최적화에 중점을 두고 있습니다. 또한 대시보드 환경을 개선하고 워크플로 문제를 해결하여 마이크로프론트엔드 개발의 처음부터 끝까지를 개선하고 있습니다.

수직적 마이크로프론트엔드로의 전환으로 개발자 속도가 크게 향상되고 빌드 시간이 단축되었습니다. 이제 팀은 공유 패키지를 통해 조율하면서 더욱 독립적으로 작업하여 자율성과 통합 개발의 균형을 유지하는 시스템을 구축할 수 있습니다.

이 아키텍처를 계속 개선해 나가면서 그 잠재력에 대한 기대가 커지고 있습니다. 마이크로프론트엔드를 탐색하든 단일 애플리케이션을 고수하든 상관없이 Vercel은 최상의 개발자 경험을 보장하기 위해 최선을 다하고 있습니다.