[F-Lab 모각코 챌린지 66일차] 모노레포 Monorepo

Nami·2023년 8월 5일
1

66일 포스팅 챌린지

목록 보기
66/66

모노레포 Monorepo

소프트웨어 개발에서 여러 프로젝트나 모듈을 하나의 대규모 리포지토리(repository)에서 관리하는 개발 방법을 말한다.

저장소 모델

  • 소스 코드 구성을 위한 구조화 옵션의 대표적인 두가지
  • 소스 형상 관리 시스템상에서 소스 리포지토리를 관리하는 방법 두가지
  1. 모노레포
  2. 멀티레포(매니레포)

멀티레포는 추후에 알아보겠다.

초기 프로젝트 구조

프로젝트 초기에는 모노리딕 시스템으로 서비스를 구현하게 된다.
프로젝트의 크기가 크지 않고, 개발자의 수도 적기 때문에 모든 것을 한곳에서 처리하는 것이 효율적.
이 경우 시스템 자체가 쪼개어지지 않고 하나이기 때문에 리포지토리 역시 하나로 관리하게 된다.

모노리딕 시스템 Monolithic System
소프트웨어를 단일한 거대한 블록으로 구성된 하나의 단일 애플리케이션으로 개발하는 방식을 의미.
전통적인 방식이고, 모든 기능과 컴포넌트를 하나의 코드베이스에 포함하여 개발하고 배포한다.
모놀리스(Monolith)와 동일한 개념

모노리딕 시스템, 모놀리스

  • 모노리딕 시스템은 시스템이 커질수록 유지보수가 어려워지고, 확장성과 유연성이 제한된다.
  • 여러 개발자들이 동시에 작업하는 경우 코드 충돌이 발생할 가능성이 높다.
  • 높은 결합도와 낮은 응집력.

개발 조직은 시스템의 각 부분을 도메인별로 분리해서 마이크로 서비스로 구성하기 시작한다. 이때 개발 조직은 쪼개진 각 서비스를 하나의 리포지토리에서 관리할지, 각자 다른 리포지토리에서 관리할지 고민하게 된다.
방법은 시스템의 각 모듈을 개별 리포지토리에서 관리할 것인지, 하나의 리포지토리에서 관리할 것인지에 따라서 달라진다. 이때 나눠서 관리하는 것을 멀티레포, 하나로 관리하는 것을 모노레포라 정의한다.

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

모놀리스 레포가 아니라 모듈러 레포에 가깝다.
재사용 가능한 컴포넌트와 라이브러리는 분리되어 있다.

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

그래도 왜?

대부분 멀티레포를 사용하고 있는데 왜 모노레포?

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

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

하지만 마이크로 서비스 아키텍처더라도 프론트엔드는 모놀리스로 진행되는 경우가 많음.
프론트에 적용하면 어떨까?

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


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

가장 흔한 예로 구글 서비스!!!

대규모 엔터프라이즈 애플리케이션을 개발한다고 가정할 때,

  • 각 팀별 또는 업무단위에 대해 Backend + Frontend 개발 후 통합하는 이슈를 줄일 수 있다.
  • 작고, 응집력 있고 유지보수성을 가지는 코드베이스를 가질 수 있다. (Simple, decoupled codebase)
  • 분리배포가 용이하고, 자율적인 팀 조직운영이 수월해진다. (Independent deployment, Autonomous teams)
  • 프론트앤드 개발을 점진적 업그레이드 또는 재작성이 수월해진다. 유사한 기능을 추상화하고 공유 패키지화하여 중복 작업을 줄일 수 있다. (Incremental upgrades)
  • 하나의 수정으로 양쪽에 commit과 PR을 반여할 수 있다.
  • 모든 프로젝트를 쉽게 검색 및 수정할 수 있다.
  • 모든 사람이 모든 것을 보고 더 많이 저장소에 참여하면서 함께 한다는 “느낌”, 제품에 대한 “소유권”이 발생된다. 자발적으로 기술에 대한 집착과 지식을 공유하게 됨. (Code ownership)
  • 회사에서 표준화하려는 환경과 배포 관리가 쉽다.
    • 예를 들어 package.json 과 같은 종속성 관리나 공유된 패키지의 재사용(예를들어 /design-system 또는 /common-util, /schema)을 쉽게 할 수 있고 환경설정(ESlint, TSConfig 등)을 구성하거나
      테스트(unit, e2e)환경을 공통으로 구성하기 좋다.

🔽 물론 단점도 있을 수 있음

  • 배포 번들 사이즈가 커질 수 있다, 저장소가 커지면서 체크인/체크아웃 성능이 저하 (Payload size)

    • 소스로부터 생성되는 아티팩트나 바이너리를 되도록 저장소에 포함시키지 않도록 하고 빌드된 바이너리라 아티팩트는 지속적인 빌드 통합과 배포(CI/CD)에서만 존재하게 함.
  • 누구나 코드를 변경할 수 없도록 풀리퀘스트(PR)를 구현

    • Github을 활용해 해결 가능.
    • 미리 사전에 약속하여 페어프로그래밍을 통해 협업
  • 서로간의 개발 환경의 차이로 복잡도가 올라간다. (Environment differences)

  • 운영 및 거버넌스도 당연히 복잡해진다. (Operational governance complexity)

  • 복잡한 파이프라인은 추가적인 교육과 학습곡선(Learning curve)

    • 모노레포 도구를 이용할 수 있음.
    • 의존성을 알아서 정렬시키고 여러 패키지에 대해서 순서대로 빌드하지 않고 의존성에 따라 병렬로 실행해 빌드
    • 머신에서 같은 것을 두 번 빌드하거나 테스트하지 않음
  • 앱마다 다른 배포주기와 의존된 공유 패키지들은 복잡한 브랜치로 유지 관리를 힘들게 한다.

    • 추상화된 브랜치 패턴과 기능 플래그를 이용
    • 기능 플래그(Feature Flags).
      응용 프로그램이나 서비스의 특정 기능을 켜고 끄는 방법으로 특정 UI 요소를 표시/숨김을 전환 하거나, 특정 로직을 On/Off 하는 등의 기능 릴리즈 관리

결론

모노레포와 마이크로 아키텍처는 뗄 수 없는 개념이다. 마이크로 아키텍처 구현을 위해 기존의 멀티레포에서 모노레포로 이동하는 경우가 많다.
모노레포로 이동 시 하나의 소속감으로 소유권을 가지고 피드백과 토론이 이루어질 수 있고,
새로운 서비스나 앱에 별도의 개발 스택을 사용하면서 기술적으로 실험적인 개발과 경험을 개발자들에게 전달할 수 있다. 그리고 모노레포에 참여한 개발자들은 공통된 관심사의 경우 재사용성과 확장성을 유지하려고 노력하게 된다는 장점이 있다. 단점으로 언급되는 불편한 점은 여러 모노레포 도구와 개발 프로세스 및 패턴을 통해 극복이 가능할 수 있을듯 하다.

pnpm과 밀접한 관계가 있는 모노레포. 모노레포 환경에 많이 쓰여서 이번에 좀 깊게 알아봤다.
역시 고려할 것이 굉장히 많고 무엇이 정답이라 할 순 없는듯 하다.

66일 챌린지가 끝났다. 이젠 포스팅을 하지 않는 날을 상상할 수 없을 정도로 습관화된 듯하다.
너무나 즐거웠다! ☺️


0개의 댓글