모노레포 - 마이크로 아키텍처를 지향하며

Gravatar for sinnerr0@gmail.com
최경식자재플랫폼개발실 재배팀 프론트엔드 개발자
2023. 01. 16.

안녕하세요. 그린랩스의 자재플랫폼개발실 재배팀에 소속되어 있는 최경식 입니다.
혹시 모노레포에 대해서 들어보셨나요?
왜 모노레포를 사용할까요?
마이크로 서비스에 대해서 많이 들어보셨죠?!
프론트엔드에서 마이크로 아키텍처를 지향하려면 어떻게 해야할까요?
자재플랫폼 개발실의 프론트엔드 개발자는 모노레포에서 개발하고 있습니다. 그리고 매주 코드리뷰를 통해서 모노레포를 개선하며 마이크로 아키텍처를 지향하고 있는데요. 함께 그 이야기의 여정에 초대드리겠습니다.

저장소 모델

소스코드 구성을 위한 구조화 옵션의 대표적인 두가지가 있는데요.
모노레포와 멀티레포 입니다. 멀티레포는 매니레포라고도 불립니다. 그 외 다른 저장소 모델도 있지만 오늘은 모노레포와 멀티레포에 대해서만 후루룩 훑도록 할께요.

모노레포(Monorepo)

모노레포는 모든 프로젝트에 대한 모든 코드와 자산을 저장하는 단일 저장소를 말합니다. 서드 파티나 라이브러리 또는 여러 다른 프로젝트와 기술로 구성될 수 있어요. 모노레포는 하나의 저장소에 모든 것이 담겨 있답니다. 이 때문에 배포 주기와 저장소의 강력한 결합이 발생돼요.

모노레포는 모놀리스 레포가 아니라 모듈러 레포에 가까운데요. 재사용 가능한 컴포넌트와 라이브러리는 분리되어 있다고 생각하시면 돼요.

1expect(모노레포 === 모놀리스 레포).toBeFalsy()
2expect(모노레포 === 모듈러 레포).toBeTruthy()

멀티레포(Multirepo)

멀티레포는 여러 저장소를 사용합니다. 일반적으로 많이 선택되고 있는 모델이라고 생각하시면 돼요. 독립된 애플리케이션이나 다른 프로젝트와 직접적인 종속성이 없는 속성을 가지고 있습니다. 하지만, 종종 실무에선 다른 시스템에 영향을 줄 수도 있어요. 대부분 팀별 또는 프로젝트별로 나누어 멀티레포 방식으로 개발을 진행하고 있죠.

대부분의 앱들은 멀티레포이고 혼자 프로젝트를 진행하는 경우 대부분 모놀리스로 만들죠. 오픈소스들은 각각의 저장소를 가진 멀티레포로 되어 있지만 모듈러 형태로 누구나 사용할 수 있죠. 그리고 일부 회사들의 경우는 모노레포를 사용하기도 합니다.

우리는 저장소 모델에 대해서 알게 되었어요. 다시 한 번 말하지만 모노레포는 재사용 가능한 모듈로 이루어진 모듈러 레포랍니다.


왜 모노레포?

그럼 대부분 멀티레포를 사용하고 있는데 왜 모노레포로 자재플랫폼개발실의 프론트엔드 개발자들은 모노레포로 전환했을까요?

먼저 모노레포를 선택하기 전에 자재플랫폼개발실의 프론트엔드 챕터에서 추구하는 아키텍처를 고민해보기로 하죠. 금방이니 조금만 해당 여정에 참을성을 가지고 지켜봐 주세요.

모놀리식(Monolithic) 서비스 아키텍처

모놀리식 서비스 아키텍처는 구성요소의 긴밀한 결합(tight coupling)으로 인하여 아키텍처가 단단해지고 애플리케이션은 분리할 수 없는 하나의 단위로서 업데이트가 필요하거나 새로운 기능이 추가될 때마다 고통스럽습니다.

일반적으로 소규모 또는 POC, MVP 구현의 경우 간단하고 빠르기 때문에 모놀리식으로 시작하게 되죠.

마이크로(Micro) 서비스 아키텍처

마이크로 서비스 아키텍처 안들어 보신분 없으시겠죠?

애플리케이션이 명확한 경계와 책임이 있는 독립된 구성요소 집합으로 분할되는 접근 방식으로 가장 많이 채택된 소프트웨어 아키텍처 유형 이에요. 모듈성과 확장성 기능을 갖추고 있어 유지 관리 및 테스트가 더 쉽습니다.

그런데 프론트엔드 팀은 여전히 모놀리스 아키텍처로 되어 있네요. 왜 프론트엔드는 마이크로 아키텍처에 대해서 얘기하지 않을까요? ㅠㅠ

모놀리스(Monolith) 프론트엔드 아키텍처

대부분의 프론트엔드 애플리케이션은 모놀리스 입니다.

단일 레이어 구조의 아키텍처를 가지고 있죠. 최근에는 동형 아키텍처에 따라 비즈니스 로직이 백엔드가 아니라 프론트엔드에도 있습니다. 그 결과 애플리케이션이 복잡해지고 모놀리스 프론트엔드 애플리케이션이 되어 갑니다.

프론트엔드도 마이크로 아키텍처에 대해서 이야기 할 때가 온 것 같죠?

마이크로(Micro) 프론트엔드 아키텍처

아래 그림은 마이크로 프론트엔드 애플리케이션의 일반적인 참조 아키텍처 중 하나인데요.

마이크로 프론트엔드 아키텍처를 통해 복잡한 UI 애플리케이션을 일관된 사용자 경험을 유지하면서 더 작고 관리하기 쉬운 조각으로 나눌 수 있습니다. 그럼으로써 더 빠른 개발과 더 작은 청크(chunks)를 생성해 성능을 향상시킬 수도 있죠. 또한 팀이 독립적으로 작업할 수 있게함으로서 결합을 줄이고 종속성을 최소화할 수 있습니다.
이런 아키텍처를 사용하는 예가 있을까요?

많이 쓰고 있는 구글 서비스 입니다. 안쓰시는 분 없겠죠?

구글의 메일, 드라이브, 캘린더 등 서비스들은 디자인과 기능을 통합 시켰지만 여러 서브도메인에 걸쳐서 독립적인 앱으로서 실행되고 있어요. 사용하면서 앱간 전환되는데 불편하거나 디자인적으로 컨텍스트 스위칭 시 어색하신 분은 없으셨겠죠? 아니면 저희가 익숙해 진걸까요?

또 다른 예로 오늘의 집을 보죠. 오늘의 집엔 홈 커뮤니티, 베스트, 셀프 가이드 등 여러 앱 서비스 카테고리가 있습니다. 서로 다른 도메인이지만 같은 페이지간 이동하는 것으로 착각할 수 있어요.


마이크로 프론트엔드 아키텍처의 요구사항은 무엇일까요?

아래는 마이크로 프론트엔드 아키텍처의 요구사항으로서 4개의 레이어로 나누어 보았어요.

첫 번째 쉘 레이어는 앱의 진입점으로 일반적으로 경로(route)를 기반으로한 앱을 로드하는 컨테이너와 라우터 역할을 합니다.
두 번째 컴포지션 레이어는 도메인별 경로(route)와 페이지가 포함되어 있습니다.
세 번째 피쳐 레이어는 도메인별 비즈니스 로직, 스토리지 로직, 위젯을 포함하게 됩니다. 이러한 위젯은 코어 라이브러리와 추가적인 컴포넌트를 기반으로 개발됩니다.
마지막으로 코어 레이어는 도메인에 구애받지 않는 라이브러리가 포함되어 있고 이러한 라이브러리는 피쳐 레이어의 빌딩 블록을 제공합니다.

현재 저희 자재플랫폼개발실의 프론트엔드는 쉘과 컴포지션 레이어를 하나로 합쳤어요.

유지해야할 레이어 비용을 줄일 수 있고 각 앱별 진입점을 스스로 결정하여 독립된 서비스로 분리할 수 있도록 하였습니다. 독립된 서비스는 서브 도메인 앱 레이어로 만들고 그린랩스에서 조직을 구성하는 스쿼드 조직에 맞게끔 저장소 구조를 유지하고 관리하고 있답니다.

실제 저희 자재플랫폼개발실 프론트엔드 저장소를 보며 얘기해 볼까요?

서브 도메인으로 구분된 앱들로 구성되어 있네요. 그리고 서로 다른 앱과 서로 다른 기술 스택으로 구현될 수 있습니다. 그리고 공통된 코어 라이브러리들을 참조하여 독립된 단위로 재사용성과 확장성을 가지게끔 아키텍처를 유지하고 있습니다.

코어 라이브러리 레이어는 Node.js의 모듈 종속성 검색에 따라 모든 앱에서 이용할 수 있도록 패키지 공유가 되도록 구성되어 있답니다.

그렇다면 이렇게 나뉘어진 마이크로 프론트엔드 아키텍처의 장점은 무엇일까요?

  • 공유가능한 위젯 서비스와 페이지를 가지고 원활한 업그레이드가 가능해요.
  • 그리고 변경에 의한 사이드이펙트를 방지하고 리팩터링이 간단해 집니다.

뭔가 어떤 저장소 모델의 장점이 생각나시나요?!

물론, 극복해야할 단점도 있습니다.

  • 유지해야할 또 다른 레이어가 발생되고
  • 교육 및 학습 곡선이 있어요.
  • 그리고 변경사항에 대한 통합 테스트도 필요합니다.

그렇다면 이 복잡한 아키텍처를 어떻게 유지시키는지 궁금하실 것 같아요.

공유되는 패키지와 종속성 관리는 또 어떻게 해야 할까요?

마이크로 아키텍처를 지향하면서 여러 프로젝트와 공유 패키지를 만들고 종속성 관리를 합니다.
동일한 기능, 동일한 UI와 UX… 멀티레포라면 어떻게 유지하고 구성할 수 있을까요?
버전 제어 시스템 중 git을 사용하시는 분들은 submodules를 이용하여 구현하실거라 생각하고 JS 생태계에 익숙하신 분들은 npm 패키지를 생각하시는 분도 계실 것 같아요.
별도 디자인 시스템을 저장소로 구성할 수도 있을 것 같네요.
만약 분리되어 있는 조직이라면 어떨까요? 애자일과 함께 스타트업에서 참 좋아하는 조직이죠 ㅎㅎ.

조직이 목적조직으로 변하고 각 제품별 멀티레포로 되어 있다고 가정해 보죠. 제품간 의존성이 있으면 해결하는데 많은 시간이 걸립니다. 이러한 목적 조직에서 멀티레포로 마이크로 프론트엔드 아키텍처가 유지될 수 있을까요?

다시 “왜 모노레포일까?”를 고민해 보죠.

저희 자재플랫폼개발실은 마이크로 프론트엔드 아키텍처를 지향하고 이를 통해 목적 조직으로 구성되어 있는 조직 구조까지 고려하여 모노레포로 전환하기로 결정했습니다. 그리고 이전의 멀티레포를 유지하지 않고 과감하게 모노레포로 전환하기로 선택했습니다.


기억해야할 사항

사실 저장소 모델의 선택 공식은 없습니다. 저장소 모델은 조직의 현재와 미래에 따라 결정되고 개발 프로세스에 통합된 구조로 외부 요인에 따라 달라질 수 있습니다.

만약, 팀이 자율적이며 독립되어 있고 굳이 공통 패키지를 만들 필요가 없다면 멀티레포가 현명한 선택입니다. 잘못된 모노레포의 선택은 오히려 해결하기 위한 이슈를 많이 생산할 수 있습니다. 이는 개발의 병목현상을 일으키고 프로젝트의 실패를 가져다 줄 수 있습니다.

멀티레포로 이미 잘 동작되고 불편함이 없으신 분들은 굳이 모노레포로 이동하시지 않으셔도 돼요.

모노레포의 좋은점

모노레포로 제품을 관리하는 경우

  • 하나의 수정으로 양쪽에 commit과 PR을 반여할 수 있어요.
  • 모든 프로젝트를 쉽게 검색 및 수정할 수 있어요.
  • 유사한 기능을 추상화하고 공유 패키지화하여 중복 작업을 줄일 수 있어요.
  • 모든 사람이 모든 것을 보고 더 많이 저장소에 참여하면서 함께 한다는 “느낌”, 제품에 대한 “소유권”이 발생됩니다. 이는 자발적으로 기술에 대한 집착과 지식을 공유하게 돼요.
  • 그리고 회사에서 표준화하려는 환경과 배포 관리가 쉬워요.
    • 예를 들어 package.json 과 같은 종속성 관리나
    • 공유된 패키지의 재사용(예를들어 /design-system 또는 /common-util, /schema)을 쉽게 할 수 있고
    • 환경설정(ESlint, TSConfig 등)을 구성하거나
    • 테스트(unit, e2e)환경을 공통으로 구성하기 좋아요.

자재플랫폼 개발실 프론트엔드 저장소의 환경 표준화 구성을 볼까요?

프로젝트의 ESLint 환경 구성은 코어 라이브러리의 환경을 가져다 쓰고 있습니다. 모든 프로젝트는 ESLint 환경구성을 표준화해 코드가 일관성을 가지게끔 되어 있습니다.

마찬가지로 프로젝트의 StyleLint 환경 구성도 코어 라이브러리의 환경 구성을 가져다 씁니다. 모든 프로젝트들은 표준화되어 스타일시트의 일관성을 유지합니다.

또 코어 UI 라이브러리는 스토리북 제공과 함께 피쳐 레이어에서 사용하기 위한 UI 컴포넌트들을 제공하여 모든 앱에서 재사용되고 있습니다.

지금까지 보여드린 것처럼 코어 라이브러리는 공유되고 피쳐 레이어의 빌딩 블록 역할을 하고 있습니다.

새로운 프로젝트를 만들어도 이렇게 일관된 코어 라이브러리의 내용은 테스트 환경과 배포 설정을 위해 복사 붙여넣기로 간단하게 새로운 서브 도메인 레이어에 적용할 수 있답니다.

모노레포의 불편한 점

지금까지 좋은 점만 말씀드렸는데 단연 모노레포를 사용하면 불편한 점도 있습니다.

  • 저장소가 커지면서 체크인/체크아웃 성능이 저하되고
  • 누구나 코드를 변경할 수 없도록 풀리퀘스트(PR)를 구현해야 합니다.
  • 그리고 복잡한 디렉토리 구조와
  • 복잡한 파이프라인은 추가적인 교육과 학습곡선을 만듭니다.
  • 모노레포는 하나의 저장소에 모든게 담겨 있습니다. 앱마다 다른 배포주기와 의존된 공유 패키지들은 복잡한 브랜치로 유지 관리를 힘들게 합니다.

모노레포의 불편한점 보완

모노레포를 운영하면서 불편한 점들을 해결하기 위해 프론트엔드 개발자들과 고민과 논의를 매주 하는데요. 이러한 고민결과 현재는 도구와 프로세스, 패턴들을 적용해 개발과 운영하느데 있어서 보완해 나가고 있습니다.

낮은 체크인/체크아웃 성능

낮은 체크인/체크아웃 성능의 불편한 점을 해결하기 위해서 소스로부터 생성되는 아티팩트나 바이너리를 되도록 저장소에 포함시키지 않도록 했고 빌드된 바이너리라 아티팩트는 지속적인 빌드 통합과 배포(CI/CD)에서만 존재합니다.

풀리퀘스트(PR) 구현

풀리퀘스트 구현은 대부분의 버전 제어 시스템에서 제공하고 있죠. 저희는 Github을 활용해 해결하고 있답니다.

Github의 풀리퀘스트(PR)와 테스트는 코드 변경을 막고 지식공유를 위한 장점을 제공합니다. 재택 근무를 하면서 비동기 커뮤니케이션과 고립된 스쿼드 조직에서 모든 구성원이 자유롭게 코드리뷰와 공통된 이슈를 해결하기 위해서 노력한답니다. 그리고 미리 사전에 약속하여 페어프로그래밍을 통해 협업을 하기도 합니다. 이는 자연스럽게 조직에 소속감을 느끼게 됩니다. 비대면 근무가 익숙한 저희에겐 소속감이 얕아지는 것을 막기 위해서 모노레포를 하는 것도 있어요.

복잡한 디렉토리 구조와 파이프라인

복잡한 디렉토리 구조와 파이프라인을 해결하기 위해서 모노레포 도구를 이용합니다.

모노레포 도구들

이미 다양한 철학을 가진 훌륭한 팀이 구축한 모노레포 도구들이 있어요. 이러한 도구들은 모노레포 저장소를 효율적으로 최적화하여 운영이 가능합니다.

자재플랫폼개발실의 프론트엔드 챕터는 Turborepo 모노레포 도구를 이용하고 있습니다. Vercel 배포 플랫폼을 이용하는데 있어서 시너지가 있어 선택하게 되었는데요. 각각의 모노레포 도구마다 지원되는 기능과 특징이 있으니까 팀 또는 조직에 맞춰서 선택을 하면 될 것 같습니다.

저희가 주로 사용되는 모노레포 도구의 기능을 간단히 소개드릴까 합니다.

의존성에 따른 병렬 실행

저장소의 모든 앱과 패키지를 빌드하는데 패키지에 대한 의존성을 알아서 정렬시키고 여러 패키지에 대해서 순서대로 빌드하지 않고 의존성에 따라 병렬로 실행해 빌드해 줍니다. 전체 패키지를 빌드하는데 2분 정도 걸렸네요.

수정시 영향 받는 프로젝트만 빌드 & 테스트

예를 들어 util의 특정 모듈을 수정해보도록 하죠. 예시는 예시일 뿐 자세한 변경사항은 무시해 주세요 ㅎㅎ.

그러면 전체 앱을 빌드하지 않고 영향받는 패키지와 패키지에 영향받는 앱만 다시 빌드하게 됩니다. 2분정도 걸리는 빌드가 20초로 줄어들었네요!!. 만약에 모노레포로 재사용가능한 패키지들을 계속 재생산하고 유지할 수록 빌드 시간은 줄어들겠죠?

머신에서 같은 것을 두 번 빌드하거나 테스트하지 않음

만약 수정 없이 빌드를 다시 수행한다면 어떨까요? 빌드를 다시 하는데 1초도 걸리지 않습니다. 만약에 빌드된 아티팩트가 리모트로 캐시되어 다른 머신이나 환경에서 공유된다면 어떨지 상상해 보세요!!


모노레포 도구들 마다 특징과 기능이 있어 자신에게 필요한 기능과 환경에 적합한 모노레포 도구가 있을 거에요. 모노레포로 결정하셨다면 모노레포 도구를 적극 활용해 저장소를 효율화 할 수 있어요.

한 번 여러분의 저장소에 맞는 모노레포 도구를 찾아보시길 바랍니다.

복잡한 브랜치 병합(Merge)와 통합(Integration)

마지막으로 복잡한 브랜치 병합과 통합이 남아 있네요. 모노레포의 불편한 점을 보완하기 위해서 어떻게 해결해야 할까요? 모노레포는 단일 저장소 입니다. 다른 팀, 다른 프로젝트, 다른 패키지, 라이브러리들이 다 함께 존재하고 있어요.

대규모 팀은 일반적으로 목표와 출시 일정이 다르기 때문에 배포 시점과 주기가 다릅니다. 일반적으로 저희가 앱을 배포하는 시나리오를 함께 보죠.

모노레포에서 협업하는 모든 팀들이 릴리즈를 했다고 하죠. 이제 쉬려고 생각하시겠지만 회사는 쉴시간을 주지 않습니다 ^^; 바로 다음 프로젝트가 있어요. 그리고 제품 백로그는 계속 재생산 됩니다.

A팀은 릴리즈 준비가 되어 배포하고 싶지만 B팀에 이슈가 있어 해당 이슈를 우선적으로 처리한 후 개발할 예정입니다. A팀은 B팀에 종속성을 가지고 있어 배포할 수 없습니다. 빨리 배포하고 싶지만 그럴 수 없죠. B팀은 이슈를 해결하고 있어 뒤늦게 개발을 시작합니다. 그리고 v2.0이 배포가 됩니다.

그 동안 A팀은 B팀이 개발이 완료될 때까지 놀지 않고 있었을 것 입니다. v3.0개발을 준비하고 개발을 하고 있었습니다. 여기서 A팀은 v2.0에서 어떤 버그가 있을지 모르는 상태에서 v3.0개발 준비를 해야합니다. 그 와중에 의존성이 없는 C팀은 v2.0을 배포하였습니다.

이처럼 팀간 의존성이 있는 배포와 그렇지 않은 배포가 있고 버전은 각 팀별로 다르게 관리가 됩니다.

또한 팀에서 애플리케이션은 여러개의 작은 부분으로 나뉘고 각 부분을 별도의 배포와 테스트, 버전 업그레이드 일정이 있습니다. 각 팀마다 버전은 다르고 여러 종속성과 이를 위한 배포 관리를 누군가 조율하지 않으면 서비스에 장애가 발생될 수 있습니다.

멀티레포에선 팀간 저장소가 달라 브랜치 머지시 충돌될 일이 없습니다. 배포순서나 일정을 조율하면 해결할 수 있습니다. 하지만 모노레포를 사용하면 코어 라이브러리를 수정하거나 공유 패키지가 수정될 수도 있습니다. 이러한 수정은 잘못하면 모든 시스템에 영향을 미칠 수 있습니다.

하… 모노레포에서 이 복잡한 코어 라이브러리와 패키지에 대한 개발은 어떻게 해결해야 할까요? 그림에선 구분하기 쉽게 분할하였지만 위의 모든 상황은 하나의 저장소에서 일어나는 일입니다.

추상화된 브랜치 패턴과 기능 플래그를 이용하여 해결

위와 같은 모노레포의 브랜치 문제를 해결하기 위해서 저희는 추상화된 브랜치 패턴과 기능 플래그를 이용하기로 결정하였습니다.

추상화된 브랜치(Branch by Abstraction)

애플리케이션의 큰 변화를 만들때 주 흐름을 점진적으로 반영하는 패턴으로 추상화된 브랜치는 대체될 컴포넌트와 의존하고 있는 코드들 사이에 추상화 레이어를 추가하고, 새로 도입할 컴포넌트는 의존 하지 않도록 하여 커밋합니다. 순차적으로 코드들이 새로운 컴포넌트에 의존하도록 변경하고, 이러한 작업이 완료 되면 기존 컴포넌트는 제거 하는 패턴입니다.

자동차 바퀴를 바꾸는 그림으로 다시 설명드리면 핑크색의 추상화 레이어를 만들고 바퀴를 하나씩 만듭니다. 나중에 한꺼번에 모든 바퀴를 토글형식으로 갈아치웁니다. 이러한 패턴은 올드 컴포넌트와 뉴 컴포넌트가 동시에 존재할 수 있고 개발하면서 발생되는 의존성 이슈를 미리 발견하고 빠른 배포가 가능합니다.

아래는 자재플랫폼개발실 프론트엔드에서 구현한 코드의 일부인데요. 쉘 컴포지션 레이어에서 추상화된 앱의 컴포넌트는 버전이나 개발 환경이라는 토글에 따라 버전2 컴포넌트를 사용할지 기존 default 컴포넌트를 사용할지 코드 내에서 동적으로 결정합니다.

또 다른 구현 일부인데요. 컴포지션 레이어 뿐 아니라 피쳐 레이어에서도 추상화 레이어를 만들어 점진적으로 반영 할 수 있습니다.

이렇게 전체 애플리케이션 내에서 특정 팀이나 버전에 종속되지 않고 미리 개발해 배포가 가능합니다. 현재도 저희 서비스에는 개발 진행중인 코드들이 배포되고 있습니다.

기능 플래그(Feature Flags)

기능 플래그를 사용할 경우 응용 프로그램이나 서비스의 특정 기능을 켜고 끄는 방법으로 특정 UI 요소를 표시/숨김을 전환 하거나, 특정 로직을 On/Off 하는 등의 기능 릴리즈 관리가 가능합니다.

  • 개발 환경에서는 기능을 활성화 하고 스테이징이나 프로덕션 에서는 기능을 비활성화 처리가 가능합니다.
  • 서비스 마다 플래그를 도입하여 끄고 배포 한뒤, 켜짐 상태로 전환하여 배포 없이 동적으로 모니터링이 가능 합니다.
  • 기능에 문제가 생길경우 바로 해당 기능을 비활성화 처리 할 수 있습니다.

아래는 기능 플래그에 대한 구현 코드 예시 입니다. 패키지별 버전이나 배포환경도 기능 플래그가 될 수 있습니다.

AB테스트나 특정 사용자를 위해 기능을 켤 수도 있습니다.

서비스 운영에 따른 기능 플래그를 두어 배포를 하지 않고 서비스를 적용시킬 수도 있습니다.


지금까지 모노레포의 불편한 점을 자재플랫폼개발실 프론트엔드 챕터에선 이렇게 극복하고 있어요.

다시 정리하자면 아래와 같이 모노레포의 불편한 점을 자재플랫폼개발실 프론트엔드 챕터는 극복중입니다. 그리고 모노레포로 전환하면서 발견되는 이슈나 문제는 계속 발생될 것입니다. 저장소에 관여하는 모든 개발자들은 공통으로 이슈를 해결하면서 발전된 저장소로 만들어 갈 것입니다.

  • 저장소가 커지면서 낮은 체크인/체크아웃 성능
    • → 아티팩트나 바이너리(CI/CD에서 출력)는 되도록 저장소에 포함시키지 않는다.
  • PR(pull requests) 구현. 그렇지 않으면 누구나 코드 변경 가능
    • → Github Branch rules와 PR & Test 통해 해결
  • 복잡한 디렉토리 구조 & 파이프라인
    • 모노레포 도구를 이용
  • 복잡한 브랜치 병합(Merge)과 통합(Integration)
    • → 추상화된 브랜치 패턴과 기능 플래그 활용

마무리

지금까지 자재플랫폼 개발실에서 경험한 내용을 요약해 볼께요.

마이크로 아키텍처를 지향하며
복잡한 아키텍처와 목적 조직을 위해 모노레포로 이동하였습니다.
모노레포 도구와 개발 프로세스 및 패턴을 통해 불편한 점을 극복 중이고
모노레포를 통해 고립된 스쿼드 조직에서 탈출하려고 합니다.
만약 기존 멀티레포를 모노레포로 만들고 싶으신 분이 계실 것 같아요.

그럴경우엔

  1. 일단 앱 폴더에 모든 프로젝트들을 넣어보세요.
  2. 그 후에 공통화/패키지화 시킬 수 있는 것들을 리팩토링 진행하세요.
  3. 그 후엔 자연스럽게 코드리뷰를 통해 저장소가 점점 효율화되어질 거에요.

목적 조직의 사일로를 구성하고 있는 조직의 경우 고립된 당사자를 구출하고 프로젝트가 원활하게 이뤄질 수 있도록 해야 합니다.
모노레포로 이동 시 사일로로써 고립되어 있지만 하나의 소속감으로 소유권을 가지고 피드백과 토론이 이루어질 수 있습니다.
새로운 서비스나 앱에 별도의 개발 스택을 사용하면서 기술적으로 실험적인 개발과 경험을 개발자들에게 전달할 수 있습니다.
모노레포에 참여한 개발자들은 공통된 관심사의 경우 재사용성과 확장성을 유지하려고 노력하게 됩니다.

기억해야 할 사항! 저장소 모델 선택의 공식은 없다.

마지막으로 다시 한 번 말씀드리지만 팀이 자율적이며 독립되어 있다. 고립을 느끼지 않는다. 공통 패키지를 만들 필요가 없다. 그러면 멀티레포가 “현명”한 선택입니다.

이상으로 자재플랫폼개발실 베짱이가 되고 싶은 생계형 일개미 “최경식” 이었습니다. 감사합니다.

참조

Deploying micro frontends with module federation and Next.js - Cogent
The Micro-Frontends Chaos (and how to solve it) | ITNEXT
The Hands-on Mainstream Repo Models You Need To Know - QE Unit
Monorepo.tools
Why TurboRepo Will Be The First Big Trend of 2022
Nx and Turborepo
Trunk Based Development
https://sinnerr0.medium.com/microfrontend-architecture-85a3f1ebf810
https://sinnerr0.medium.com/왜-요즘-monorepo-얘기가-많이-나오는-것일까-16e4a2131d11
https://sinnerr0.medium.com/monorepo-tools-29cf9b94e42f
https://sinnerr0.medium.com/당신이-알아야할-저장소-모델-repository-model-659882dca4f5

Dev Dive 2022, 영상 풀버전


추천 콘텐츠