Flex 팀은 모든 제품을 일주일에 한 번 배포하는 정기 배포 시스템을 운영했습니다. 이 시스템은 초기에는 편리했지만, 시간이 지나면서 몇 가지 심각한 문제점을 야기했습니다.
불안정한 배포: 공유 패키지의 복잡한 의존성으로 인해 코드 변경이 예상치 못한 곳에서 오류를 발생시켰고, 결국 모든 앱을 동시에 배포해야만 하는 상황에 이르렀습니다. 이는 배포의 안정성을 떨어뜨리고 빠른 서비스 제공을 방해했습니다.
개발 생산성 저하: 거대한 모노레포는 의존성 그래프를 파악하기 어렵게 만들었고, 개발자들은 코드 수정이 미칠 영향 범위를 예측하기 힘들어했습니다. 이로 인해 소규모 변경에도 큰 책임감을 느끼게 되어 개발 속도가 현저히 느려졌습니다.

인지 부하 증가: 패키지 수가 375개에 달할 정도로 기하급수적으로 늘어났고, 개발자는 자신이 담당하는 앱 외에도 수많은 패키지의 의존 관계와 히스토리를 이해해야 했습니다. 이는 새로운 팀원의 온보딩을 어렵게 만들고, 팀 전체의 개발 문화를 저해했습니다.
정기 배포 시스템을 폐기하려고 하다보니 기존의 모노레포 시스템이 더 이상 팀과 제품의 성장에 적합하지 않다고 판단, 정기 배포 시스템을 폐기하고 폴리레포로 전환하는 대규모 리팩터링 프로젝트를 시작했습니다. 이 과정에서 우리는 다음 세 가지 핵심 원칙을 세웠습니다.
모노레포냐 폴리레포냐는 중요하지 않습니다. 가장 중요한 것은 코드베이스 내에 명확한 경계를 설정하는 것입니다. 기존 모노레포에서는 workspace:*를 통해 패키지를 자유롭게 공유하면서 의도치 않은 파급 효과(side effect)가 발생했습니다. A팀이 App1과 App2에 사용되는 패키지를 수정했는데, B팀이 App3에 사용하기 위해 해당 패키지를 수정하면서 App1과 App2에 갑작스러운 변경사항이 생기는 문제가 빈번했습니다.
이러한 문제를 해결하기 위해, 우리는 폴리레포를 채택하여 레포지토리 자체를 경계로 삼았습니다. 이는 업무 공유의 어려움, 코드 파편화, 원자적 커밋 불가능과 같은 단점이 있지만, 배포의 안정성과 속도를 크게 확보할 수 있는 장점이 훨씬 크다고 판단했습니다.
개발자가 인지할 수 있는 의존성의 범위는 한정적입니다. 패키지 수가 375개까지 늘어나자 개발 생산성은 물론이고 팀의 개발 문화까지 악영향을 받기 시작했습니다. 이를 해결하기 위해 우리는 다음 두 가지 방법을 실행했습니다.
flex-packages, flex-design-system과 같이 모든 패키지를 하나의 버전으로 관리하는 Monolithic 버전 관리 시스템을 도입했습니다. 이로써 개발자는 자신이 사용하는 패키지들의 복잡한 의존 관계를 일일이 파악할 필요 없이, pkg → service → app의 단순한 레이어로 의존성을 구성할 수 있게 되었습니다. 이는 프론트엔드 개발자의 인지 부하를 획기적으로 줄여 생산성을 높였습니다.무분별한 공유 모듈은 오히려 코드베이스의 취약성을 높이고 개발 생산성을 떨어뜨립니다. 우리는 공유 모듈의 기준을 명확히 정의했습니다.
@flex-pkgs), 또는 UI 컴포넌트(@flex-design-system)이 외의 모든 코드는 과감하게 각 사용처에 내재화하고 중복을 허용했습니다. 이는 코드가 고립되도록 만들어 추후 개별 레포지토리로 분리하기 용이하게 했습니다. flex-apps와 같이 비즈니스 로직을 담는 앱은 의존성을 끊어 완벽하게 독립적으로 운영될 수 있도록 작업했습니다.