최근 모노레포로 코드베이스를 관리하는 프랙티스가 각광받는다는 느낌을 많이 받습니다.
모노레포를 구성함으로써 얻을 수 있는 장점들은 널리 알려져 있습니다. 하지만 상대적으로 부각되지 않는 것이라면 모노레포의 장점을 십분 활용하기 위해서는 모노레포 구조가 가져오는 단점이 최소화되어야 한다는 사실입니다. 이러한 단점이 제대로 관리되지 못한다면 모노레포는 기존 레포지토리 관리 방식에 거대한 복잡도를 더하게 되고, 모노레포 도입으로 달성하고자 하는 것들에도 좋지 않은 영향을 줄 확률이 높습니다.
모노레포의 단점을 최소화하려면 떨어져있는 멀티레포들을 한 곳으로 모으는 일 이상의 무언가가 필요합니다. 그것이 바로 코드베이스 위에서 일어나는 여러 일들을 관리할 수 있게 하는, 모노레포에 알맞는 툴링입니다. 이 포스팅에서는 모노레포의 장점을 최대한 달성할 수 있게 코드베이스 툴링이 필요한 몇 개 지점들을 소개해보려고 합니다. 이를 위해 모노레포의 정의와 장점들을 먼저 간단히 소개해보려고도 하고요.
굳이 이야기하자면 이 포스팅에서 말하는 모노레포의 기준은 nodejs 패키지 기준입니다. 소개할 문제들이 특정 개발 생태계에서는 100% 들어맞지 않는 이야기일 수도 있을 것 같고, 빌드 툴 등이 자연스럽게 해결하는 문제도 있을 것 같아요.
어떤 것이 모노레포인가?
A monorepo is a single repository containing multiple distinct projects, with well-defined relationships. - Nrwl
모노레포 빌드 툴 중 하나인 Nx를 만드는 Nrwl 팀에서 정의한 모노레포의 의미가 간결하고 정확한 설명이라고 생각합니다.
모노레포를 이루는 개별 프로젝트(애플리케이션, 패키지)들은 독립적(distinct)이어야 합니다. 즉, 정상적인 구조의 모노레포라면 당장 모노레포를 폴리레포로 바꾸어도 개별 프로젝트들이 의존성 문제 없이 도로 다 분리될 수 있어야 합니다.
모노레포 위에서 각 패키지-애플리케이션, 혹은 패키지-패키지 관계에서의 의존성이 복잡하고 관리될 수 없는 형태라서 각 프로젝트들이 독립적인 배포가 힘들다면, 이는 단순히 프로젝트 여러개가 한 레포지토리에 모여있는 모놀리식과 다를게 없습니다. 이런 경우는 폴리레포로 관리하는 경우보다 못하게 특정 지점의 코드 변경이 독립적으로 배포돼야 하는 애플리케이션에 영향을 줄 위험이 큽니다. 또한 뒤에 설명할 모노레포 관리 도구를 실질적으로 적용하는데도 어려움이 생깁니다.
모노레포는 단순히 code-colocation이 아니기 때문에 각 프로젝트의 관계가 엄밀히, 잘 정의되어야 합니다(well-defined relationships). 모노레포의 프로젝트들이 패키지-패키지, 패키지-애플리케이션 관계를 이루고 있다면 의존 관계가 필연적으로 발생합니다. 이런 경우에도 각 프로젝트들은 의존 관계가 쉽게 추적될 수 있도록 패키지에는 버저닝이 필요하며, 특정 패키지 의존을 강제하거나 혹은 의존할 수 없도록 통제할 수 있는 도구가 필요합니다.
모노레포의 장점은 무엇인가?
모노레포 적용으로 얻으려고 하는 주된 장점은 크게 3가지 정도로 나눠볼 수 있습니다.
1. 거대한 프로젝트의 코드 관리 비용을 줄인다.
모노레포는 여러 프로젝트간 일관된 개발자 경험(DX)을 제공할 수 있는 기반이 됩니다. 폴리레포였다면 다 따로따로 세팅해줘야할 린트, 테스트, 빌드 도구들을 모노레포에서 관리하면 단일한 config로 단순하게 적용하고 관리할 수 있습니다.
원자적 커밋으로 여러 프로젝트의 핵심적인 변경을 쉽게 커밋할 수 있습니다. 코어 라이브러리에 대한 버전업이 필요할때 폴리레포였다면 각 레포지토리들을 순회하며 일일히 버전업 작업을 진행해야 했겠지만, 모노레포에서는 하나의 커밋으로 여러 프로젝트의 버전을 올릴 수 있습니다.