이 글을 읽는 분들중 개발을 하시는 분들은 Facebook, Twitter(e.g. X), Google, Microsoft 등 대부분의 기업이 전체 코드베이스, 모든 서비스, 애플리케이션 및 도구를 단일 거대 저장소인 모노레포에 보관하는 것을 들어본 적이 있을 것이다.
대부분 팀이 코드베이스를 관리하는 일반적인 방식(저장소당 하나의 애플리케이션, 서비스)에 익숙 하다면 이는 매우 이상하게 들릴 수 있다. 우리가 구글이나 페이스북도 아닌데, 굳이 이걸 써야해? 라고 생각할 수 있다.
모노레포를 사용하면 소프트웨어 개발 라이프사이클에서 여러가지 장벽이 줄어들 수 있다. 코드를 찾는데 소요되는 시간이 줄고, 버그를 찾아내고 수정할때까지 시간이 줄어들 수 있다. 그리고 방대한 코드를 찾고 분석하는 것이 훨씬 쉬워진다.
모노레포(Monorepo)는 여러 프로젝트를 하나의 저장소에 저장하는 버전 관리 구성이다.
모노레포를 사용하면 다음과 같은 이점을 얻을 수 있다.
단일 저장소를 제공한다.
코드 공유가 쉽다.
코드 리팩토링이 쉽다.
모놀리스(Monolith)와 다른게 없는거 아닌가?라고 생각할 수 있다.
모노레포는 독립적인 프로젝트를 포함하는 거대한 코드베이스인 반면, 모놀리스는 단일 프로젝트에 집중한다. 물론, 모놀리스도 모노리포에서 관리 할 수 있다. 그러나 모놀리스는 여러 저장소로 분할 될 수도 있다.
어쨌든, 본 글은 모노레포에 초점을 맞출 것이다.
“단 하나의 저장소”는 무슨 의미일까?
이는 단일 루트가 있는 Linux 파일 트리와 유사하다.
이 개념에 익숙하지 않은 사람들은 일반적으로 이 아이디어에 대해 상당히 강한 반응을 보인다.
“너무 거대한거 아냐?”
“확장이 가능해?”
다양한 반대 의견이 나온다. 그럴 수 있다. 비교적 생소한 개념이며, 표면적으로는 거대하기에 거대하게 개발하지 말라고 배웠던 것에 어긋난다.
그러나 모노레포는 종속성 관리를 보다 쉽게 하고 여러 개의 저장소를 사용하는 것보다 안정적인 테스트를 가능하게 한다.
모노레포는 좋은 아이디어일까?
모노레포를 사용하는 것은 대부분 회사에 좋은 생각이다. 모든 팀의 모든 소스 코드를 하나의 저장소에 보관할 수 있다. 이렇게 하면 모든 사람과 공유하기 더 쉬워진다.
커밋 후에는 모든 개발자가 새 코드를 보고 사용할 수 있다. 이렇게 하면 많은 개발자가 단일 코드에서 작업하기에 흔히 발생하는 고통스러운 병합을 일부 회피할 수 있다.
모노레포는 모든 데이터에 대한 제한이 거의 없는 협업적 작업이라는 아이디어에 기반을 두고 있다. 하지만 모노레포가 커질수록 느려지게된다. 모든 데이터를 한 곳에 보관하는 것은 매력적이지만, 접근하는데 속도가 느리다면 단일 저장소가 무슨 소용이 있을까?
그럼에도, 구글을 모노레포를 잘 사용한다. 구글을 꽤 오래전부터 모노레포를 사용하기로 결정했고, 회사가 성장함에 따라 규모를 확대했다. 2015년 기준 구글 모노레포 현황이다. (https://cacm.acm.org/research/why-google-stores-billions-of-lines-of-code-in-a-single-repository/)
86테라바이트의 데이터
20억줄의 코드
900만개의 소스 파일
왜 구글이 모노레포를 선택했는지 그리고 계속 고수하고 있는지 이유는 무엇일까? 모노레포를 사용하는 것이 개방적이고 협력적인 문화의 핵심이기 때문이다.
구글외에도 Salesforce, Meta, Uber, Airbnb, X도 모노레포를 사용하는 것으로 유명하다.
모노레포는 종속성의 불일치를 제거한다. 종속 모듈간의 불일치는 정말 어려운 상황이다. 코드를 한곳에 저장하는 것으로서 버전 관리와 종속성 관리에 대한 것이 끝난다. 모노레포는 본질적으로 이 문제를 사라지게 한다. 이것은 내가 가장 좋아하는 문제 해결 종류이다.
그러나, 100% 사실은 아니다. 종속 모듈에 속한 부분이 변경이 되면 모든 것을 배포하고 테스트해야 한다.
<출처: ByteByteGo>
위 표는 모노레포와 마이크로레포(혹은 멀티레포)를 사용하는 회사들을 보여준다. 어느것이 더 나을까? 왜 회사마다 다르게 사용할까? 라는 의문이 생긴다.
모노레포에서는 서비스는 폴더이고, 모든 폴더에는 BUILD 구성과 OWNER 권한 제어가 존재한다. 모든 서비스의 멤버는 자체 폴더를 담당한다.
마이크로레포에서는 각 서비스는 자체 저장소를 가지며, 빌드 구성과 권한은 일반적으로 전체 저장소에 대해서 설정한다.
다시 모노레포로 돌어와서 구글은 모노레포 접근 방식으로 어떤 혜택을 얻고 있을까?
구글이 이런 결정을 한 이유에는 엄청난 규모에서 일관성과 조정을 유지해야 할 필요성에서 비롯되었다. 수천명의 엔지니어가 수많은 프로젝트에서 작업하기에 모노레포를 사용하면 팀이 코드를 공유하고 쉽게 협업할 수 있도록 보장하기 때문이다.
대규모로 작업을 해야 하기에 도구의 혁신이 필요하다. 그래서 Piper(버전 제어 시스템), Bazel(빌드 도구)에 크게 의존한다. 이런 도구를 사용해야 대규모 모노레포를 효과적으로 관리하고 테스트, 종속성 관리 및 배포를 자동화할 수 있다.
처음에 언급했듯이 모노레포 방식을 채택하면 개발 라이프사이클에서 장벽이 줄어든다. 코드를 찾고 어떻게 사용할지 알아내는 데 시간을 덜 쓰게 된다. 저장소를 설정하거나 허가를 요청할 필요도 없다. 이런 문제 대신 고객을 돕기 위한 문제에 더 많은 시간을 할애할 수 있다.
고려 사항
이제까지 언급한 이점에도 모노레포는 다음과 같은 과제를 안고 있다.
성능 문제: 모노레포가 커짐에 따라 버전 제어 성능이 느려질 수 있다.
손상된 빌드: 메인 브랜치의 실패는 모든 프로젝트에 영향을 미친다.
학습 곡선: 익숙하지 못한 개발자는 대규모 통합 저장소의 복잡성에 어려움을 겪을 수 있다.
코드 검토: 엄청난 양의 코드 검토와 알림은 압도적이다.
모노레포와 멀티레포 중에서 선택하는 것은 기술적 고려 사항 만큼이나 조직 문화에 관한 것이다. 모노레포는 Silo를 무너뜨리고 더 나은 협업을 촉진하는데 도움이 될 수 있으며, 모든 구성원의 중심 허브 역할을 한다.
결국, 도구를 잘 사용하여 워크플로우를 조정하는 것이 관건이다.
요약
모노레포는 코드 공유를 간소화하고 자산에 대한 가시성을 개선한다. 물론 깨끗한 히스토리, 병합 충돌 위험, 도구 지원 등의 대가를 치뤄야 한다.
모노레포가 가진 투명성이라는 이점은 모든 상황에 적합하지는 않다. 모노레포를 사용할지 여부는 자신의 프로젝트, 프로젝트 간 종속성, 구성원들의 의견에 따라 결정해야 한다.
좋은 코드 문화에는 사용하는 저장소 유형보다 더 많은 요소가 있기에 자발적인 참여가 필요하다.
모노레포는 잘 사용하면 정말 강력한 솔루션이다. 아래는 모노레포에 가장 일반적으로 사용되는 도구 목록이다. 시간이 되면 하나씩 다뤄보겠다.