본문 바로가기

회고/세미나

토스 SLASH 21 - Micro-frontend React, 점진적으로 도입하기 후기

 

 

면접에서도 MSA라는 이야기를 많이 들었는데 MSA란 마이크로 서비스 아키텍처의 준말이다.
MSA가 출현하게 된 배경으로는 모놀리틱 아키텍처 형태가 있는데 이는 모듈별로 개발을 하고 개발이 완료된 웹 어플리케이션을 하나의 결과물로 패키징하여 배포되는 형태를 말한다. 모놀리틱 아키텍처의 경우 소규모 프로젝트에서는 충분히 사용해도 괜찮지만 일정 규모 이상의 서비스, 혹은 수백명 이상의 개발자가 투입되는 프로젝트에서는 한계를 나타낸다. 부분 장애가 전체 서비스 장애로 확대될 수 있고, 한 프레임워크와 언어에 종속적이다. 또 서비스 변경이 어렵고 수정하면 장애의 영향도 파악이 어렵다. 이런 문제점들을 보완하기 위해 MSA가 출현하게 되었다.
이처럼 대규모 프로젝트를 진행하는 곳에서는 Micro하게 프로젝트를 관리한다. 그런데 이번 세미나 역시 Micro-frontend로, 나는 이 Micro-frontend가 궁금해졌다. 어떻게 하면 Micro하게 프론트엔드를 개발할 수 있다는 걸까?
이 강연의 핵심내용은 토스팀에서 Django MVC 프로젝트가 Micro-frontend React 프로젝트로 탈바꿈하는 이야기이다. 나는 아직 대규모 프로젝트를 진행해본 경험은 없어서 Micro-frontend가 있는지도 필요한지도 몰랐는데 대규모 프로젝트에서는 충분히 고민해볼만한 내용이라고 생각해서 다같이 보면 좋을 것 같아 블로그에 작성해본다.

 

  1. Django MVC 프로젝트에 점진적으로 React를 도입한 방법
    1. UX 인터랙션이 필요한 페이지에 부분적으로 React를 적용해보기로 함
    2. CRA로 하려고 하다보니까 Django와 충돌하는 부분이 많았고 결국 from scratch로 빌드 툴링을 직접 설정하는 편이 낫다고 생각
    3. webpack-bundle-tracker : 번들의 경로와 public path 추출
      1. webpack 빌드 결과물의 chunk 정보를 JSON 파일에 추출해줌
    4. react-app-rewired : CRA를 eject하지 않고도 각종 설정을 수정
    5. django-webpack-loader : 번들을 Jinja 템플릿에 쉽게 삽입하기 위해 사용
      1. 3-1의 JSON 파일의 정보를 바탕으로 적절한 <script> 태그나 <link> 태그를 생성해주는 원리
    6. 1년 후에는 토스 인터널의 25여개의 서비스가 React로 만들어짐
      1. 자연스럽게 새로운 서비스들이 기존의 실험적 코드베이스에 "탑승"하는 방식
      2. 각 서비스는 webpack entrypoint로 구분되지만 하나의 패키지에서 하나의 webpack 설정으로 한번에 빌드되는 구조를 갖게 됨
        ➡️ 의존성 지옥! (의존성 패키지의 변경이 갖는 영향의 범위가 크다 보니 최근 빠르게 변하는 웹 프론트엔드 생태계에 발맞추기 어려워지는 문제도 있음)
        ➡️ 긴 빌드 시간 (Git Push -> Docker Build(Frontend Build - Backend Build) -> Docker Push  -> K8S Deploy) 평균적으로 20분이 걸리는데 최대 45분이 걸림
  2. 마이크로 프론트엔드 아키텍처를 도입한 이유와 후기
    1. 마이크로 프론트엔드 아키텍처
      1. 기존의 거대한 소스 코드를 독립적인 패키지들로 분리 (유지보수가 이루어지는 단위 기준으로 패키지를 분리)
        1. 인프라 패키지 : 동일한 빌드 툴링 공유
        2. 라이브러리 패키지 : 공통 소스코드 관리
        3. 서비스 패키지 : 페이지에서 독립적으로 작동
      2. 어떻게 구현했나요?
        1. 최초 구현 : Yarn Workspace + Lerna
        2. 현재 구현 : Yarn 2 Workspace Plugin
      3. 이렇게 하면 뭐가 좋나요?
        1. 소스 코드부터 빌드 설정까지 완벽한 격리
        2. 의존성 지옥 탈출
        3. 빌드 속도 최적화
        4. 제품 전략 면에서 독립된 제품들이 기술적으로도 독립된 것
  3. 프론트엔드 빌드 시간을 효과적으로 단축한 비법
    1. 빌드 시간을 줄이는 가장 좋은 방법 : 빌드를 하지 않는 것
    2. 빌드를 하지 않을 수 있는 방법 : 소스 코드가 바뀐 패키지만 빌드하고 나머지는 기존 빌드 결과물을 재사용 (incremental build)
    3. Zero Build
      1. 소스 코드가 바뀌었는지는 어떻게 알 수 있나요?
        1. Git의 커밋 아이디는 사실 그 커밋에 포함된 모든 파일의 해시를 누적시킨 결과와 같다
          1. 각각의 파일은 Git 내부에서 blob으로 처리되고, 각각의 blob에 대해 해시를 계산한다
          2. 각각의 폴더는 tree로 처리되는데, tree의 해시는 그 tree에 속한 blob의 모든 해시 값의 해시
          3. 이런 식으로 반복하면 커밋의 해시가 결정된다
        2. 특정 tree가 변경되었는지 알고 싶다면 이전 커밋의 해시와 현재 커밋의 해시를 비교하면 된다
        3. 이 원리를 이용해서 각각의 패키지가 변경되었는지 여부를 아주 적은 추가 연산으로 알아낼 수 있다
      2. 기존 빌드 결과물은 어디에 저장하나요?
        1. Git 저장소에 압축해서 함께 저장 ➡️ Git을 pull 받기만 하면 최신 빌드 결과물을 다운로드 받을 수 있다
        2. Yarn 2의 zero-install이 작동하는 방식과 유사
      3. 이 방식을 적용하고 나서는 빌드 시간이 평균 3분으로 최대 15배까지 빨라짐
  4. 요약
    1. Django에 React를 얹기 위해 사용할 수 있는 도구들이 있다
    2. 마이크로 프론트엔드를 추천한다 (수평적 애자일 조직)
    3. 긴 빌드 시간은 Zero-build로 해결했다
  5. 여기서 다루지 않은 것들이지만 React, Micro-frontend 도입 전에 고려해야 할 것들
    1. React를 도입해야 하는 이유 (혹은 안 되는 이유)
    2. React 도입에 따른 백엔드의 변화
    3. 모놀리식 코드베이스에서 프론트엔드 빌드 성능을 개선하는 방법
반응형