pile·
프론트엔드·토스 SLASH토스 SLASH·

모노리포 희망편, 절망의 리포가 희망의 리포로 부활하기까지 걸린 1년

토스 프론트엔드 팀이 100명 이상의 개발자가 사용하는 모노리포에서 겪은 의존성 버전 불일치, 개발 환경 편차, 느린 설치 속도 문제를 pnpm Catalog 도입으로 해결한 1년간의 여정을 다룬다. 카탈로그로 라이브러리 버전을 중앙화한 결과 의존성 설치 시간을 52% 단축하고 .pnp.cjs 파일 크기를 84% 줄이는 데 성공했다.

핵심 포인트
  • 100명+ 규모 모노리포에서 React·TypeScript 등 핵심 라이브러리 버전이 서비스마다 달라 플랫폼 라이브러리 업데이트가 사실상 불가능한 상태였다.
  • pnpm Catalog의 catalog: 프로토콜로 표준 버전을 단일 YAML에 선언하고 각 서비스가 참조하는 방식으로 버전 분산을 해소했다.
  • .pnp.cjs 파일이 96MB에서 15MB로 84% 줄어들고, 의존성 설치는 528초에서 250초로 52%, 개발 서버 실행은 26.7초에서 20.3초로 23% 단축됐다.
  • 파괴적 변경이 생길 때는 새 카탈로그 버전을 생성하고 자동 코드 변환 스크립트로 마이그레이션 비용을 최소화했다.
  • 월 1회 버전 발행 정책과 패키지 개발자 간 정기 미팅으로 카탈로그를 지속 운영 가능한 체계로 정착시켰다.
상세 정리
  • 문제 인식: 100명+ 개발자가 동일 모노리포에서 작업하는데 React·TypeScript 등 핵심 라이브러리 버전이 서비스마다 달라 의존성 충돌이 빈번했다.
  • 개발 경험 편차: 최신 환경 서비스는 빠른 반면 오래된 서비스는 개발 서버 속도가 느리고 빌드 설정이 달라 개발자마다 경험이 달랐다.
  • 플랫폼 라이브러리 전파 병목: 버전 호환성 문제로 사내 공통 라이브러리 업데이트 시 각 서비스에 일일이 대응해야 해 전파 비용이 급증했다.
  • 카탈로그 선택: 모노리포를 유지하면서 버전을 통합하기 위해 pnpm/Yarn의 Catalog 기능을 채택했다. 별도 인프라 없이 패키지 매니저 기능으로 해결하는 방식이었다.
  • 구현 방식: 루트 pnpm-workspace.yaml의 catalog: 블록에 표준 버전을 선언하고, 각 패키지의 package.json에서 catalog:react 형태로 참조했다.
  • 설치 성능 개선: .pnp.cjs(PnP 런타임 파일)가 96MB에서 15MB로 84% 줄어 설치 I/O가 대폭 감소했고, 전체 의존성 설치 시간은 528.4초에서 249.9초로 52% 단축됐다.
  • 개발 서버 개선: 중복 의존성 해소로 개발 서버 실행 시간이 26.7초에서 20.3초로 23% 빨라졌다.
  • 버전 관리 정책: 월 1회 카탈로그 버전을 발행하는 정책을 수립했고, 파괴적 변경이 포함될 때는 새 카탈로그 버전을 생성해 점진적 이전을 지원했다.
  • 자동 코드 변환 스크립트: 서비스가 새 카탈로그 버전으로 이전할 때 수작업 없이 마이그레이션할 수 있는 codemod 스크립트를 제공했다.
  • 추가 조치: 사내 패키지를 통합 관리하는 패키지 모노리포를 별도 구축하고, Yarn용 플러그인(yarn-plugin-catalogs)도 개발해 Yarn 환경에서도 동일 체계를 적용했다.
  • 운영 체계: 패키지 개발자 간 정기 미팅을 운영해 카탈로그 변경 사항을 사전 공유하고 충돌을 예방하는 거버넌스를 갖췄다.
  • 성과: React Server Components, TypeScript 7, Rspack 등 최신 기술을 전 서비스에 빠르게 도입하는 것이 가능해졌다.
왜 읽나대규모 프론트엔드 모노리포에서 의존성 버전 불일치와 느린 설치 속도를 겪고 있는 팀에게 pnpm Catalog의 구체적인 도입 과정과 수치 결과를 제공한다.
토스 SLASH
토스 SLASH 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2