팀이 커져도 배포를 늦추지 않는 코드베이스 운영법: 토스 모노리포
프론트엔드 인력이 100명을 넘고 하루 배포가 수백 번이면, 공통 라이브러리 하나의 업데이트도 곧 운영 문제가 된다. 토스는 모바일 제품 코드를 하나의 모노리포로 유지하면서 React 19, Next.js 15, TypeScript 7처럼 핵심 개발환경을 가깝게 맞추는 방식을 택했다.
핵심은 리포지터리의 개수가 아니라 의존성 변경을 어느 범위까지 예측하고 전파할 수 있는가에 있다. 토스 프론트엔드 플랫폼 팀은 서비스마다 달랐던 핵심 라이브러리 버전을 카탈로그로 묶고, 새 버전을 별도로 발행해 검증과 이전의 순서를 만들었다.
모노리포가 커질수록 왜 업데이트가 비싸지는가
한 리포지터리에 코드가 모여 있어도 서비스가 제각각의 React, 상태 관리 도구, 빌드 도구 버전을 고르면 공통 코드는 사실상 여러 환경을 동시에 지원해야 한다. 설치할 패키지 종류가 늘고, 어떤 서비스에서 통과한 변경이 다른 서비스에서도 통과하는지 장담하기 어렵다. 이 상태에서 플랫폼 팀은 테스트 범위가 너무 넓어지고, 서비스 팀은 업데이트를 미루게 된다.

토스가 찾은 원인은 모노리포 자체가 아니라 버전 정책의 부재였다. 리포를 여러 개로 쪼개면 개별 설치 범위는 작아질 수 있지만, 개발환경이 갈라지고 공통 패키지를 바꾸는 비용은 남는다. 그래서 팀은 핵심 의존성의 버전과 조합을 플랫폼이 관리하는 표준으로 만들었다.
카탈로그는 버전을 고정하는 대신 변경 경로를 만든다
카탈로그는 pnpm-workspace.yml 또는 .yarnrc.yml에 정의한 의존성 세트를 서비스가 catalog: 프로토콜로 참조하는 방식이다. 새 서비스는 처음부터 최신 카탈로그를 쓰고, 직접 설치할 때도 현재 서비스의 카탈로그를 참조하게 하며, CI는 카탈로그에 든 패키지를 제각각 버전으로 쓰는 실수를 잡는다.

이 구조에서 이미 발행한 카탈로그는 파괴적 변경을 몰래 담지 않는다. 토스는 메이저 변경이 필요하면 새 카탈로그를 만들고 일부 서비스에서 먼저 동작을 확인한 뒤 이전한다. 이전에는 코드 변환 스크립트와 AI Skill을 제공하고, 서비스 팀은 자신이 쓰는 카탈로그 이름을 바꾸는 방식으로 변경 범위를 알아차린다.
새 버전은 한 번에 밀어 넣지 않고 통과 경로를 남긴다
토스의 카탈로그 이름에는 발행 연월이 들어간다. 새 카탈로그는 한 달에 최대 한 번 발행하며, 월초에 패키지 메인테이너가 예정 변경을 함께 논의한다. 발행 전 검증된 서비스, 자동 변환 도구, CI 규칙을 차례로 두면 플랫폼 팀은 변경을 전파하고 서비스 팀은 필요한 시점에 이전할 수 있다.

이전이 끝난 뒤에도 정책은 코드로 남는다. 토스는 Yarn 플러그인과 CLI로 카탈로그 적용, 특정 워크스페이스의 사용 강제 또는 제한을 관리한다. 실험용 버전은 기존 안정 카탈로그의 이름 아래 별도 경로로 두어 일부 서비스에서 먼저 시험할 수 있게 했다. 플랫폼 팀의 판단을 문서 공지에만 두지 않고, 새 프로젝트 생성과 의존성 설치, CI 검사에 녹인 셈이다.
측정값이 보여 주는 것은 설치 시간만이 아니다
토스가 공개한 적용 전후 수치에서 Yarn PnP의 .pnp.cjs 파일은 96MB에서 15MB로 줄었다. 개발 서버 실행은 26.7초에서 20.3초로, 모노리포 전체 의존성 설치는 528.4초에서 249.9초로 감소했다. 각각 약 84%, 23%, 52%의 변화다. 이 숫자는 토스가 같은 모노리포에서 카탈로그 적용 효과로 제시한 측정이며, 중요한 변화는 패키지 수 감소와 함께 어떤 서비스가 어떤 버전을 쓰는지 추적할 수 있게 된 점이다.

가시성이 생기면 패키지 개발자는 구조적 변경의 파급 범위를 찾고, 서비스 개발자는 검증된 세트를 바탕으로 업데이트할 수 있다. 토스는 이 기반 위에서 RSC, TypeScript 7, Rspack, E2E 테스트 같은 변화를 빠른 기간에 시도했다고 설명한다. 보안 패치도 카탈로그 버전 갱신을 통해 전파 경로를 확보한다.
다른 팀이 먼저 정할 것은 리포 구조가 아니라 세 가지다
첫째, 모든 서비스가 반드시 함께 쓸 핵심 의존성을 좁혀야 한다. 모든 패키지를 중앙화할 필요는 없지만, 런타임·프레임워크·빌드와 검사 도구처럼 공통 코드의 호환성을 좌우하는 층은 표준이 필요하다. 둘째, 이미 발행한 표준에 어떤 변경을 허용할지 정해야 한다. 호환성이 깨지는 변경은 새 버전으로 분리해야 서비스 팀의 예상이 맞는다. 셋째, 새 버전으로 가는 수동 작업을 코드 변환과 CI 규칙으로 줄여야 한다.
모노리포는 코드를 한곳에 둔다는 사실만으로 배포 속도를 보장하지 않는다. 표준 버전, 사전 검증, 되돌릴 수 있는 이전 경로를 함께 운영할 때 공통 플랫폼의 변경이 여러 팀의 대기열이 아니라 다음 배포로 이어진다.
출처: 토스테크, 「모노리포 희망편, 절망의 리포가 희망의 리포로 부활하기까지 걸린 1년」(2026-08-10)
