chasing_pavement

8개월만에 MFA로 마이그레이션 성공한 flex의 이야기 본문

아키텍처

8개월만에 MFA로 마이그레이션 성공한 flex의 이야기

FE Developer, Jin 2024. 10. 11. 12:11

 

flex에서는 하나의 앱을 쓰는 경험을 제공하기 위해 프로젝트의 기능 개발을 하는 동시에 8개월 만에 MFA로 마이그레이션에 성공했다고 한다.

여기서 MFA가 무엇인지, 어떤 계기로 전환했는지 한번 알아보겠다. 

 

 

flex 와 MFA 도입 과정

flex는 올인원 HR 플랫폼을 개발하는 대형 웹 서비스이다. 

전자계약, 휴가/근무 관리, 급여 정산 등 여러 기능을 통합 관리하고 있어 17개의 Next.js 앱과 모노레포 앱의 개수보다 더 많은 공용 패키지를 사용하고 있었다. 

 

 

Flex의 문제점이 크게 두가지가 있었는데 

 

1. 앱의 규모가 커짐에 따라 빌드 배포 시간이 오래 걸리는 문제가 발생

→ 앱을 나눠서 개발할 필요성을 느껴 각 스쿼드에서 페이지 별로 나눠서 개발

2. 다른 앱으로 접속하면 모든 리소스를 다시 가져와야 하는 문제 발생, 의도치 않은 로딩 서클을 다시 보게 됨

 

 

이런 문제들을 어떻게 해결할 수 있을까? ≫ MFA를 도입해보자 !

 

 

 

Module Federation

 

MFA 구현 방식 중 하나로, 하나의 앱을 독립적인 배포가 가능한 모듈 단위로 나누어 브라우저의 런타임 시점에 통합하는 방식

각각의 마이크로 앱들은 호스트라고 불리는 앱에서 번들 형태로 로드되어 각각 렌더링이 된다.

Module Federation WorkFlow

 

 

 

이를 활용하면 화면에 보이는 모든 UI들을 컴포넌트 단위로 배포할 수 있고 앱 전환할 때 모든 자원을 처음부터 다시 불러올 필요가 없어진다. 

컴포넌트 단위로 배포할 수 있는 MFA의 장점

 

MFA를 도입하면서 생긴 문제점

 

1. Next.js에서 공식적으로 모듈 페더레이션 방식을 지원할 계획이 없어보임

 

Next.js 플러그인 존재했지만 다른 레포지토리에서 이슈가 발생

→ next로 구현되어 있던 것들을 SPA 방식으로 전환 (해결!)

 

 

2. 모듈 페더레이션이 가진 전방향적인 특성 때문에 생기는 리스크

 

remote는 해당 카이크로 앱에서 불러올 다른 마이크로 앱의 진입점 URL

exposes는 다른 앱에서 해당 마이크로 앱을 부를 때 사용할 수 있는 모듈의 경로

 

하나의 마이크로 앱은 다른 앱을 호출할 수 있고, 다른 앱에서 호출될 수 있다.

이건 전방향적인 특성을 가지고 있다고 하는데 이런 방법으로 운영하면 런타임 간 의존성이 복잡해지고 앱의 구조를 쉽게 파악하지 못할 가능성 O

호스트이면서 동시에 리모트가 되는 전방향의 마이크로 앱

 

flex의 해결방법

전역의 호스트를 하나만 두고, 호스트가 여러 리모트를 불러올 수 있는 2 depth 구조를 만들었다.

기존 Micro App과 기존 App의 리스크를 완화한 버전

 

 

 

3. 런타임 에러 리스크

 

런타임 리스크란?

런타임에 앱들이 동적으로 합쳐지는 과정에서 식별되지 않은 에러가 발견되어 유저가 앱을 원활히 사용하지 못하는 것

Remote App 로드를 실패해도 앱의 다른 기능을 사용할 수 있어야 했다.

각 리모트에서 발행한 에러 때문에 전체 장애로 이어질 수 있는 상황

 

 

 

flex의 해결방법

 

로컬 환경에 두 가지 개발 환경을 제공해서 런타임 에러가 발생할 위험성을 잘 인지할 수 있게 했다. 

 

multiple과 standalone 환경을 같이 제공해 생산성을 올렸다.

 

dev:multiple 환경을 제공하여 여러 앱을 각각 다른 로컬 포트에 실행시킴

dev:standalone 환경도 같이 제공하여 개발시 필요하지 않은 앱은 실행시키지 않고 하나의 앱만 실행시킬 수 있음

 

 

 

flex는 왜 기능 개발을 아키텍처 마이그레이션과 함께 진행했을까?

플렉스는 마이그레이션과 기능 개발을 동시에 진행했다고 한다. 

 

 

기존의 next.js 앱에서 마이그레이션된 앱으로 이동할 때 html을 한번 렌더링해야 했기 때문에 한번에 모든 앱을 MFA로 마이그레이션해야 하는 상황이였음. 

 

프레임워크에 의존하지 않는 리액트 컴포넌트에 해당하는 코드들을 모노레포 내부 패키지로 분리하고 기존 웹 패키지와 함께 새로운 웹 패키지를 동시에 의존하도록 구성하여 빌드하는 방식을 사용했음

이를 위해서 마이그레이션 초반에 프레임워크에 의존하지 않는 리액트 컴포넌트들을 코드에서 분리하는 작업을 진행하였음

 

두 가지 환경에서 빌드 성공시키기

 

홈페이지에 해당하는 리액트 컴포넌트 코드를 분리해서 Next.js 앱에서는 디렉토리 라우팅 방식으로 넣어주고, 

마이크로 프론트엔드 앱에서는 SPA 라우팅 방식으로 넣어주면 페이지가 두 앱 모두에서 제대로 작동하여 빌드에 성공하였음

Next.js 앱에서는 분리된 페이지에서 계속 기능 개발하고,

Micro Frontend App 에서는 분리된 패키지에서 개발된 기능을 그대로 반영 + 마이그레이션에 필요한 작업 진행

 

마이그레이션 완료된 기능에 대해서는 기존 앱을 중단시키고 새로운 앱을 프로덕션으로 전환하였음

마이그레이션 완료된 후 기존 코드 삭제

 

import { useFlexRouter } from '@flexteam/next-router';

export default function Component() {
  const { push } = useFlexRouter();

  return (
    <div>
      <h1>Component</h1>
      <button
        onClick={() => {
          push('/some/path');
        }}
      >
        next/router을 이용한 라우팅
      </button>
    </div>
  );
}

이렇게 물리적으로 떼어낼 수 없는 코드는 빌드 시점에 바꿔주었음

 

SPA 라우터인 react-router-dom을 래핑하는 패키지를 만들어 기존 패키지와 동일한 기능을 하도록 구현

마이크로 앱이 빌드 될 때 webpack config 설정을 통해 코드를 직접 수정하지 않고 빌드 타임에 마이크로 앱 안에 선언된

넥스트 라우터를 새로운 패키지로 대체하여 빌드가 성공하게 함

 

결론은 전체를 바꾸는 방식으로 구현하였음 !

 

 

MFA를 도입하며 미친 영향(도입 전과 후)

1. next.js -> SPA 방식으로 변경

2. 배포 단위 세분화 - 전체 장애/롤백 상황 최소화

3. 개발 생산성 개선 - 빌드 시간 평균 70% 개선(20분-> 5분)