CMS 모노레포 개선기: 빌드 시간 단축부터 번들 최적화까지
10여 개 Next.js 앱을 병렬 빌드로 바꿔 배포 시간을 14분에서 8분으로 줄였다.
여기어때 통합CMS는 10여 개 Next.js 앱을 하나의 모노레포에서 운영하며, Spring Boot가 인증·라우팅을 맡고 정적 파일은 Static Export로 만든 뒤 Thymeleaf 템플릿으로 서빙했다. 앱이 늘어나면서 배포마다 약 14분이 걸렸고, 프론트엔드 한 줄만 바뀌어도 전체 앱을 다시 빌드해야 했다.
병목은 Next.js 빌드였다. .dockerignore를 정리해 불필요한 파일 전송을 줄이고, 이전 빌드 이미지를 캐시처럼 재활용하도록 바꿨다. 이어 TurboRepo 빌드를 순차에서 병렬로 전환해 --concurrency=3으로 돌리고, 실패하면 --concurrency=1로 자동 재시도하게 했으며, --continue로 일부 앱이 실패해도 나머지 빌드는 계속 진행하게 했다.
그 결과 배포 시간은 14분 → 8분으로 줄어 약 43% 단축됐고, 배포 한 번당 약 6분을 절약했다. 디스크와 메모리를 사전 점검해 Docker 이미지 누적과 리소스 부족으로 인한 실패도 함께 줄였다.
번들 최적화 단계에서는 AI 코딩 도구로 모노레포 전체 구조와 의존성을 분석해, 20여 개 파일에 흩어진 lodash import 패턴과 사이드이펙트를 먼저 확인했다. 실제 사용 함수는 isEmpty, debounce, isEqual, orderBy 등 10종뿐이었고, 체이닝이나 mixin처럼 개별 import 전환을 막는 패턴은 없었다.
- Lottie는 약 1.6MB짜리 전체 렌더러 번들 대신
lottie_light로 바꿔 해당 청크를 약 75% 줄였다. - lodash는 전체 import와 named import를 개별 import로 정리하고,
Array.flat(),.filter(Boolean),!= null같은 네이티브 대체도 함께 적용했다. - 공유 패키지의 Context 파일처럼 영향 범위가 큰 지점을 먼저 손봐 3개 대표 앱의 lodash 청크를 299KB → 164KB로 낮췄고, 전체로는 약 1.6MB를 절감했다.
다만 Git diff 기반 빌드 스킵, Turbo 로컬 캐시, 앱별 부분 빌드는 JAR 통합 구조와 Jenkins 권한 문제 때문에 효과가 제한적이었다. 앞으로는 TanStack Query 버전 통일, date-fns 통일, Recoil → Jotai 마이그레이션을 순차적으로 이어가고, 장기적으로는 프론트엔드 독립 배포 구조로 더 짧은 배포 시간을 노린다.
이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.
요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.