1인 개발자 SaaS 모노레포 vs 멀티레포 — Graxel 운영 1년 후 다시 보는 결정
pnpm과 Turborepo로 구축한 모노레포 아키텍처가 1인 개발자에게 정말 정답이었을까요? 1년간의 뼈저린 운영 회고와 실패담.
1년 전의 원대한 가설: "Vercel처럼 쿨하게 개발하자"
정확히 1년 전, 저는 새로 시작할 GRAXEL 프로젝트의 뼈대를 잡으며 흥분에 빠져 있었습니다. Next.js, UI 컴포넌트, 공통 유틸리티 함수들을 하나의 저장소(Repository)에 쓸어 담는 모노레포(Monorepo) 구조를 채택했기 때문입니다. pnpm workspaces와 Turborepo를 조합하면, 나홀로 개발자라도 마치 실리콘밸리의 거대 테크 기업처럼 우아하게 코드를 재사용할 수 있을 거라 굳게 믿었습니다.
당시의 제 가설은 이랬습니다. "인증 로직(`packages/auth`)과 디자인 시스템(`packages/ui`)을 한 번만 만들어두면, portal이든 myhyetaek이든 블록 조립하듯 순식간에 새로운 SaaS를 찍어낼 수 있을 거야!"
그리고 1년이 지난 지금, 이 가설은 절반의 성공과 절반의 끔찍한 악몽으로 결론 났습니다.
실제로 좋았던 점 3가지: 압도적인 일관성
먼저 모노레포가 제게 가져다준 달콤한 열매들을 이야기해 보겠습니다.
- '진실의 원천'이 된 공유 패키지: 가장 강력한 장점이었습니다. 버튼 색상을 파란색에서 보라색으로 바꾸고 싶을 때,
packages/ui폴더의 CSS 변수 하나만 수정하면 5개의 서비스에 동시에 반영되었습니다. 일일이 레포지토리를 돌아다니며 복사-붙여넣기를 하지 않아도 되는 경험은 황홀했습니다. - TS/ESLint 환경의 중앙 통제: 1인 개발자는 자칫하면 코드 스타일이 파편화되기 쉽습니다. 모노레포 루트에
tsconfig.json과eslint.config.mjs를 하나만 두고 모든 앱이 이를 상속받게 하니, 코드 품질이 강제로(!) 일정하게 유지되었습니다. - Atomic Commit의 위력: 공통 API 유틸리티를 수정하면서, 그 변경사항에 영향을 받는 프론트엔드 코드 3곳을 하나의 Git 커밋으로 묶어서 올릴 수 있었습니다. "API 먼저 배포하고, 프론트 배포해야지" 하는 순서의 스트레스가 완전히 사라졌습니다.
실제로 아팠던 점 3가지: 꼬리가 몸통을 흔들다
하지만 서비스가 3개를 넘어가면서부터 아키텍처가 제 목을 조르기 시작했습니다. 특히 1인 개발자의 한정된 리소스에서 병목은 치명적이었습니다.
"어느 날, `legal-kr` 앱의 작은 오타 하나를 고쳤을 뿐인데, 전혀 상관없는 `portal` 앱의 CI 빌드가 실패하면서 전체 프로덕션 배포가 3시간 동안 마비되었습니다."
- CI 시간의 폭발적 증가: Turborepo의 캐싱이 제대로 동작하지 않으면 지옥이 펼쳐집니다. 처음엔 2분이면 끝나던 Github Actions 빌드 시간이 15분, 20분으로 늘어났습니다. 모노레포 툴 가이드에 나온 대로 캐시 설정을 최적화하려 했지만 의존성 그래프가 꼬이면서 번번이 캐시 미스(Miss)가 발생했습니다.
- 의존성 충돌의 도미노: 특정 앱 하나만 React 19로 올리고 싶었는데, 공통
ui패키지가 React 18에 묶여 있어 발목을 잡았습니다. 하나의 서비스를 실험적으로 업그레이드하려면 전체 생태계를 갈아엎어야 하는 '강결합'의 역설에 빠진 것입니다. - 터미널 창의 혼돈: `pnpm dev` 명령어를 루트에서 치면 5개의 프론트엔드 서버와 2개의 백엔드 스크립트가 동시에 터미널을 채웁니다. 에러 로그가 어디서 발생했는지 스크롤을 한참 위로 올려야 찾는 일이 다반사였습니다.
멀티레포로의 탈출: saas-factory-trader 사례
결국 지난달, 저는 뼈아픈 결단을 내렸습니다. 새로 기획한 주식 트레이딩 데시보드인 saas-factory-trader는 모노레포에서 완전히 분리하여 독립된 멀티레포(Multi-repo)로 파냈습니다.
이유는 명확했습니다. 기존 서비스들은 Next.js 중심의 정적 콘텐츠가 많았지만, 트레이더 앱은 Python 백엔드에 무거운 WebSocket 통신을 사용해야 했기 때문입니다. 이기종 스택을 억지로 모노레포에 쑤셔 넣으려다 보니 CI 파이프라인이 누더기가 되었습니다. 분리하고 나니 빌드 속도는 1분대로 줄었고, 저는 다시 평화로운 개발 리듬을 되찾았습니다. (제 삽질의 구체적인 코드가 궁금하시다면 제 개발자 프로필의 깃허브 링크를 확인해주세요.)
다시 시작한다면? 1인 개발자의 임계값
만약 타임머신을 타고 1년 전으로 돌아간다면, 저는 여전히 모노레포를 선택할 것입니다. 0에서 1을 만들고, 비슷한 도메인의 서비스를 10개까지 늘려가는 과정에서는 모노레포의 생산성이 압도적입니다.
하지만 서비스의 성격(도메인, 기술 스택)이 완전히 달라지는 순간, 혹은 CI 빌드 시간이 10분을 초과하는 순간이 바로 멀티레포로 분리해야 할 '임계값'이라는 교훈을 얻었습니다. 데브옵스 엔지니어 없이 혼자 모든 것을 감당해야 하는 1인 개발자에게 너무 비대한 시스템은 사치입니다. 아키텍처에 대해 저와 논의하고 싶으신 분들은 언제든 Contact 페이지를 통해 메시지를 남겨주시기 바랍니다.
공유하기
이어 읽으면 좋은 글
같은 주제와 태그를 기준으로 GRAXEL 운영 맥락을 더 깊게 볼 수 있는 글입니다.
SaaS Factory 모노레포 운영기 — pnpm + Turbo로 12개 서비스 묶기
pnpm workspaces와 Turborepo로 공용 패키지와 12개 서비스를 동시에 관리하며 얻은 실전 패턴을 공유합니다.
Cloudflare Pages 무료 티어로 SaaS 시작하기 — 진짜 1년 비용 후기
1인 개발자가 Cloudflare Pages 무료 티어로 1년간 portal, myhyetaek 등 5개 서비스를 운영하며 지출한 실제 비용과 뼈아픈 실패담을 공개합니다.
Next.js 15 App Router + next-intl v4로 ko/en/ja 3개 언어 운영기
graxel.ai 자체를 한국어/영어/일본어 3개 언어로 운영하면서 배운 로케일 라우팅, SEO, hreflang 실전 패턴을 정리합니다.