Monorepo

Elena·2026년 1월 8일
post-thumbnail

Monorepo란?

여러 프로젝트/패키지/서비스의 코드를 하나의 Git 저장소에 모아 관리하는 방식

  • 장점
    - 공통 라이브러리(shared code) 관리가 쉬움
    - 코드 탐색/리팩토링이 쉬움(서비스 간 변경을 한 PR(pull request)로)
    - 버전 맞추기(동기화)가 쉬움
  • 단점
    - 레포가 커지면 빌드/테스트가 무거워질 수 있음(그래서 캐시/부분 빌드 전략 필요)
    - 권한/소유권/릴리즈 정책이 복잡해질 수 있음
    - 도구(빌드 캐시, CI 최적화) 없으면 생산성이 떨어질 수 있음

Monolithic vs MSA vs Monorepo

  • 모놀리식(Monolithic), MSA(Microservices Architecture) = 주로 서비스 아키텍처/배포 단위
  • 모노레포(Monorepo) = 주로 코드 저장소(레포) 운영 방식

1) 모놀리식 (Monolith)

  • 정의
    - 하나의 애플리케이션(또는 하나의 배포 단위) 안에 기능들이 함께 들어있는 구조.
    - 보통 하나의 코드베이스 + 하나의 빌드/배포 산출물(예: 단일 jar/war) + 단일 실행 환경.

  • 특징
    -모듈(패키지)로 내부를 나누더라도 배포는 같이 된다.
    -서비스 간 호출이 대부분 프로세스 내부 호출(메서드 호출) 이라 단순하고 빠름.
    -텍스트초기 개발/운영이 비교적 쉽다.

  • 장점
    - 개발/테스트/배포 파이프라인 단순
    - 트랜잭션 처리 쉬움(단일 DB, 단일 트랜잭션)
    - 로컬 디버깅 쉬움

  • 단점
    - 커지면 빌드/배포가 느려지고 변경 영향 범위가 큼
    - 부분만 확장(scale)하기 어려움(전체를 같이 늘리는 경우 많음)
    - 팀이 커지면 충돌/의존이 커짐

2) MSA(Microservices Architecture)

  • 정의
    - 기능(도메인)을 여러 독립 서비스로 나누고, 각 서비스가 독립적으로 배포/확장되는 구조.
    - 서비스 간 통신은 보통 HTTP/gRPC/메시지 큐 등 “네트워크 호출”이다.

  • 특징
    - 서비스별로 DB를 분리하는 경우가 많고(“Database per service” 패턴), 데이터 일관성은 분산 트랜잭션 대신 이벤트/사가(Saga) 등으로 푼다.
    - 운영 요소가 늘어난다: 서비스 디스커버리, 관측성(로그/트레이싱), 장애 격리, 배포 자동화 등.

  • 장점
    - 서비스 단위로 독립 배포/롤백 가능
    - 특정 서비스만 수평 확장 가능
    - 팀이 서비스 단위로 오너십을 갖기 쉬움(조직 확장에 유리)

  • 단점
    - 분산 시스템 복잡도 상승(네트워크, 장애, 지연, 버전 호환)
    - 관측/운영 비용 증가(모니터링, 트레이싱, 배포, 보안)
    - 데이터 일관성/트랜잭션이 어려워짐

“무엇을 나누는가” 관점

모놀리식: 기능은 나눠도 배포 단위는 하나
MSA: 기능을 서비스로 나누고 배포 단위도 여러 개
모노레포: 배포 단위가 뭐든 상관없이 코드를 한 레포에 모아 관리

만약 회사에 스토리지/ 메신저/ 명함 서비스가 있다면?

1) 하나의 모놀리식으로 묶는 경우
한 서버(한 앱) 안에 3개 기능이 모듈로 존재

  • StorageModule, MessengerModule, BusinessCardModule
  • 배포는 한 번에 같이
  • DB도 하나 또는 스키마만 나눔

※ 단점:
- 하나의 서비스에 트래픽 폭증 시 전체를 같이 스케일 해야할 수 있음
- 배포 리스크 공유

2) MSA로 서비스를 3개로 분리하는 경우
스토리지 서비스 / 메신저 서비스 / 명함 서비스를 각각 별도 서비스로 둠 (배포 단위 3개)
서비스 간 연결 예시

  • 메신저에서 파일 첨부:
    messenger-service가 storage-service에 “파일 업로드용 presigned URL 발급” 요청
    업로드 후 messenger-service는 메시지에 fileId만 저장

  • 명함에서 프로필 사진 저장:
    card-service가 storage-service를 파일 저장소로 사용

DB는 보통 서비스별로 분리

  • 실제 파일은 오브젝트 스토리지 에 두는 식

※단점:
- 운영 난이도 상승(모니터링, 배포, 장애 대응 API 버전관리)
- 서비스 간 호출 실패/지연 고려해야함

모노레포 혹은 멀티레포와의 조합

1) 모노레포 + MSA (많이 쓰는 현실 조합)

한 레포에 여러 서비스 코드가 있고, 배포는 서비스별로 따로

레포 구조 예시

company-platform (one repo)
├─ services/
│ ├─ storage-service/
│ ├─ messenger-service/
│ └─ card-service/
├─ packages/
│ └─ common-lib/ (공통 DTO, 유틸, 인증 클라이언트 등)
└─ infra/
└─ k8s/ (배포 매니페스트, 헬름 등)

운영/배포
서버(배포 단위): 3개 (storage / messenger / card)
스케일: 각 서비스만 따로 확장 가능
장애 격리: 메신저 터져도 스토리지/명함이 덜 영향
데이터/통신

DB: 보통 서비스별 분리 (또는 최소한 스키마/계정 분리)

통신: messenger → storage를 HTTP/gRPC로 호출

언제 좋냐?
팀이 커지고, 공통 코드 재사용도 많고, 서비스별 독립 배포가 필요할 때

2) 멀티레포 + MSA

서비스마다 레포가 따로 있고, 배포도 서비스별로 따로

레포 구조 예시

storage-service-repo
messenger-service-repo
card-service-repo
common-lib-repo (있다면)

운영/배포
서버(배포 단위): 3개
각 팀이 레포/릴리즈를 완전히 독립적으로 가져감
데이터/통신

DB: 서비스별 분리가 자연스러움

통신: 네트워크 호출(HTTP/gRPC), 이벤트(큐) 등

언제 좋냐?
조직이 “서비스별로 완전 독립”이고, 접근 권한/규제가 강하게 나뉠 때

3) 모노레포 + 모놀리식

한 레포 + 한 앱(한 배포)
(프론트/백/공통까지 한 레포로 묶는 경우도 흔함)

레포 구조 예시

company-app (one repo)
├─ backend/
│ ├─ storage-module/
│ ├─ messenger-module/
│ └─ card-module/
├─ frontend/
└─ packages/

운영/배포
서버(배포 단위): 1개
배포: 스토리지 기능만 고쳐도 전체를 같이 배포
데이터/통신

DB: 보통 하나(테이블만 도메인별로 나눔)

통신: 내부 메서드 호출 (가장 단순)

언제 좋냐?
초기/작은 팀, 빠른 개발이 중요하고 운영 복잡도를 최소화할 때

핵심

  • MSA냐 아니냐는 “배포 단위가 여러 개인가?”
  • 모노레포냐 아니냐는 “코드가 한 Git 레포에 모여 있나?”
  • 모노레포 + MSA = “코드는 같이, 배포는 따로”
  • 멀티레포 + MSA = “코드도 따로, 배포도 따로”
  • 모노레포 + 모놀리식 = “코드도 같이, 배포도 같이”
profile
一切唯心造

0개의 댓글