모노레포 vs 폴리레포: 웹·모바일·백엔드를 동기화하는 방법
웹, 모바일, 백엔드 앱을 배포하는 팀을 위해 모노레포와 폴리레포를 설명합니다. 의존성, 릴리스, CI 전술을 비교해 속도를 유지하는 방법을 알아보세요.

진짜 문제: 세 개의 코드베이스에 걸친 변경 배포\n\n팀들이 모노레포냐 폴리레포냐로 논쟁하는 이유는 Git 철학 때문이 아닙니다. 문제는 작은 제품 변경이 웹, 모바일, 백엔드에 각각 세 번의 변경으로 바뀌고, 그 과정에서 어딘가가 깨진다는 점입니다.\n\n처음 고장 나는 곳은 보통 UI가 아닙니다. 보이지 않는 접착제 같은 부분이 흔히 문제입니다: API 계약이 일치하지 않게 바뀌거나, 공유 라이브러리가 한 곳에서만 버전이 올라가거나, 빌드 파이프라인에 갑자기 새로운 단계가 필요해지는 식입니다. 한 부분이 다른 부분보다 먼저 배포되면 사용자는 ‘웹에는 버튼이 있는데 모바일은 지원 안 함’이나 ‘백엔드 응답이 바뀌어서 앱이 무한 로딩됨’ 같은 버그로 느낍니다.\n\n웹, 모바일, 백엔드는 배포 주기도 다릅니다. 웹은 하루에도 여러 번 배포할 수 있고, 백엔드는 자주 배포하지만 롤아웃이 신중해야 할 때가 많습니다. 모바일은 앱 스토어 심사와 사용자 업데이트 지연 때문에 가장 느립니다. 필드명을 바꾸는 같은 ‘간단한’ 변경도 한 화면에서만 필요하더라도 가장 느린 경로를 기준으로 계획을 세워야 할 수 있습니다.\n\n다음 같은 일이 자꾸 발생하면 레포 조율 비용을 지불하고 있는 것입니다:\n\n- 파괴적 API 변경이 머지 후에 발견된다.\n- 버전 정렬이 수작업 알림과 스프레드시트에 의존한다.\n- 한 기능에 대해 여러 개의 PR이 필요하고 서로 기다리며 멈춰 있다.\n- CI가 변경과 무관하게 너무 많은 것을 빌드하고 테스트해 느리다.\n- 롤백이 위험하게 느껴진다(어떤 커밋이 어떤 릴리스와 짝인지 불명확).\n\n팀 규모와 제품 성숙도에 따라 정답은 달라집니다. 초반에는 조율 비용을 싸고 가시성을 높이는 쪽이 유리한 경우가 많습니다. 팀이 성장하면 경계가 중요해지지만, 그 전제는 인터페이스가 안정적이고 소유권이 명확해야 한다는 점입니다.\n\n의미 있는 모든 변경이 세 군데에 반드시 반영되어야 한다면, 그 비용은 어떤 식으로든 지불하게 됩니다. 레포 전략은 그 비용을 어떻게 지불할지에 관한 문제입니다.\n\n## 전문 용어 없이 본질 정리: 모노레포와 폴리레포\n\n레포는 코드와 그 히스토리가 저장되는 장소일 뿐입니다. 웹, 모바일, 백엔드가 있을 때 선택은 명확합니다: 모두 한곳에 두느냐, 분리하느냐.\n\n모노레포는 여러 앱과 공유 코드를 하나의 저장소에 담는 방식입니다. 웹, iOS/Android, 백엔드 서비스, 공유 라이브러리가 나란히 존재합니다.\n\n폴리레포는 반대입니다: 각 앱(혹은 서비스)마다 별도의 저장소가 있습니다. 공유 코드는 보통 별도 패키지가 되거나 필요한 부분을 복사해 씁니다.\n\n일상적으로 보면 모노레포는 코드 공유가 쉽고, 크로스 앱 변경을 한 PR로 처리할 수 있으며 규칙이 일관된 느낌을 줍니다. 단점은 사회적 측면입니다: 소유권이 흐려질 수 있고, 레포 전체를 대상으로 한 검사들이 엄격하게 느껴질 수 있습니다.\n\n폴리레포는 각 팀이 독립적으로 움직이기 좋고 레포가 집중되는 경향이 있으며 접근 제어가 단순해질 수 있습니다. 단점은 조율입니다: 코드 공유에 계획이 필요하고 크로스 앱 변경은 여러 PR과 정교한 타이밍을 요구합니다.\n\n많은 팀은 하이브리드로 수렴합니다: 앱은 분리된 레포에 두고 공유 계약만 한 곳에 두거나, 하나의 모노레포지만 강한 경계를 두어 팀이 대부분 자기 영역에만 머무르게 하는 식입니다.\n\n하나의 소스 오브 트루스에서 백엔드, 웹, 모바일을 생성하는 플랫폼을 쓰면 계약과 로직이 함께 존재해 드리프트가 줄어듭니다. 예를 들어 AppMaster (appmaster.io)는 단일 모델에서 프로덕션 준비가 된 백엔드, 웹, 네이티브 모바일 앱을 생성합니다. 이것이 릴리스 현실(모바일은 여전히 느림)을 없애진 않지만, "세 군데 모두 업데이트했나?" 하는 오버헤드 상당수를 제거할 수 있습니다.\n\n## 의존성 관리: 공유 코드를 안전하게 유지하기\n\n공유 코드는 레포 배치와 관계없이 팀이 시간을 잃는 주된 지점입니다. 공유 라이브러리나 API 계약의 작은 변경이 웹 빌드, 모바일 릴리스, 백엔드 배포를 각각 다른 방식으로 망가뜨릴 수 있습니다.\n\n라이브러리(UI 컴포넌트, 검증 규칙, 인증 헬퍼)를 공유할 때는 모두가 같은 버전을 쓸지, 시간에 따라 여러 버전을 허용할지 선택해야 합니다.\n\n- 하나의 버전은 단순하고 "내 브랜치에서는 동작" 같은 서프라이즈를 줄입니다.\n- 여러 버전은 팀이 각자 속도로 움직이게 하지만 잡동사니가 늘고 보안 패치 배포가 어려워집니다.\n\nAPI 클라이언트와 스키마는 특별한 주의가 필요합니다. 수동 업데이트는 느리고 실수하기 쉽습니다. 더 나은 패턴은 API 스키마를 진실의 원본으로 두고 클라이언트를 자동 생성한 뒤 이를 체크인하거나 CI에서 생성하게 하는 것입니다. 목표는 빠르게 실패하게 하는 것: 백엔드가 필수 필드를 추가하면 모바일 클라이언트가 QA가 아니라 빌드 단계에서 깨지게 하세요.\n\n동작 변경이 안전한 이전 경로 없이 퍼질 때 파괴적 변경이 확산됩니다. 먼저 추가 방식(새 필드, 새 엔드포인트)을 선호하고 나중에 폐기하세요. 부득이 파괴적 변경을 해야 한다면 버전된 엔드포인트나 짧은 호환성 창을 사용하세요.\n\n구체적 예: 백엔드가 status를 state로 이름을 바꿨습니다. 웹이 오늘 업데이트했지만 모바일은 일주일 뒤에나 배포할 수 있다면, 백엔드는 그 일주일 동안 두 필드를 모두 허용하거나 옛 필드를 새 필드로 매핑하는 어댑터를 배포해야 합니다.\n\n의존성 업데이트를 지루하지만 안전하게 만드는 몇 가지 규칙:\n\n- 일정한 주기로 업데이트하세요. 작고 주간 단위 업데이트가 분기 단위의 큰 업데이트보다 낫습니다.\n- 파괴적 변경에는 명시적 승인을 요구하고 짧은 마이그레이션 노트를 포함하세요.\n- 자동화된 검사(의존성 업그레이드, 클라이언트 재생성, 기본 계약 테스트)를 도입하세요.\n- “완료”를 “내 레포 통과”가 아닌 “웹, 모바일, 백엔드 빌드가 모두 녹색”으로 정의하세요.\n\n생성된 코드는 드리프트를 줄이지만 규율을 대체하지는 않습니다. 하나의 계약, 명확한 폐기 정책, 예측 가능한 업데이트가 여전히 필요합니다.\n\n## 릴리스 조율: 웹, 모바일, 백엔드를 맞추기\n\n릴리스 조율은 레포 전략이 이론에서 실무로 나오는 지점입니다. 백엔드가 API 필드명을 바꾸면 웹은 보통 같은 날 업데이트하고 배포할 수 있습니다. 모바일은 앱 스토어 심사와 사용자 업데이트 타이밍 때문에 작은 불일치가 며칠에서 몇 주의 지원 티켓으로 이어질 수 있습니다.\n\n실용적 목표는 단순합니다: 사용자 동작이 어떤 부분이 먼저 업데이트되든 작동해야 합니다. 즉 완벽하게 동기화된 릴리스를 가정하지 말고 혼합 버전을 계획하세요.\n\n### 팀들이 실제로 쓰는 버전 관리 패턴\n\n대부분의 팀은 다음 접근 중 하나에 정착합니다:\n\n1) 하나의 공유 릴리스 트레인: 웹, 모바일, 백엔드를 하나의 버전 단위로 함께 배포.\n\n2) 서비스별 버전 + 호환성 규칙: 각 앱/서비스에 자체 버전이 있고 백엔드는 정의된 범위의 클라이언트 버전을 지원.\n\n공유 릴리스 트레인은 보기에는 깔끔하지만 모바일 지연 때문에 무너지는 경우가 많습니다. 서비스별 버전은 문서상으로는 복잡하지만 현실과 잘 맞습니다. 서비스별로 간다면 한 가지 규칙을 명확히 적고 강제하세요: 어떤 백엔드 버전이 어떤 모바일 버전을 얼마나 오래 지원해야 하는가.\n\n모바일 지연은 핫픽스 접근 방식도 바꿉니다. 백엔드 핫픽스는 빨리 나갈 수 있지만 모바일 핫픽스는 사용자에게 도달하는 데 며칠이 걸릴 수 있습니다. 서버 측 수정으로 구버전 모바일이 계속 동작하도록 하세요. 클라이언트 변경이 필요할 때는 기능 플래그를 사용하고, 대부분 사용자가 업데이트할 때까지는 오래된 필드를 제거하지 마세요.\n\n예: 주문 흐름에 “배달 지침”을 추가한다고 합시다. 백엔드가 새 선택적 필드를 추가하고 웹은 즉시 표시하며 모바일은 다음 스프린트에 표시합니다. 백엔드가 구형 요청도 받아주고 필드를 선택적(optional)으로 남겨두면 모바일이 따라올 때까지 모든 것이 문제없이 작동합니다.\n\n### 누가 릴리스 캘린더를 책임져야 하나\n\n“모두가 책임진다”고 되면 실제론 아무도 책임지지 않아 조율이 실패합니다. 소유자는 기술 리드, 릴리스 매니저, 또는 엔지니어링 지원이 있는 제품 매니저가 될 수 있습니다. 그들의 일은 놀라움을 방지하고 릴리스 기대치를 가시화하는 것입니다.\n\n복잡한 절차가 필요한 건 아닙니다. 반복 가능한 습관 몇 가지가 필요합니다: 컷오프와 프리즈 윈도우가 포함된 간단한 릴리스 캘린더, API 변경 전의 빠른 교차팀 점검, 모바일 지연 시의 결정(백엔드 보류 vs 호환성 유지)을 위한 명확한 계획 등입니다.\n\n만약 워크플로가 하나의 모델에서 웹, 모바일, 백엔드를 생성한다 해도 릴리스 소유자는 여전히 필요합니다. ‘세 곳 모두 업데이트했나?’ 하는 순간은 줄겠지만 모바일 타이밍 문제로부터 완전히 자유로워지진 않습니다.\n\n## CI 시간을 관리하는 법\n\nCI가 느려지는 이유는 모노레포든 폴리레포든 비슷합니다: 불필요하게 너무 많은 것을 다시 빌드하고, 종속성을 반복해서 설치하고, 모든 변경에 모든 테스트를 돌립니다.\n\n흔한 시간 소모 요인은 작은 변경에 전체 빌드를 돌리는 것, 캐시 누락, 전체를 돌리는 테스트 스위트, 병렬로 돌릴 수 있는 작업을 직렬로 실행하는 것 등입니다.\n\n모든 환경에서 도움이 되는 개선부터 시작하세요:\n\n- 종속성 다운로드와 빌드 결과물을 캐시하세요.\n- 린트, 유닛 테스트, 빌드를 가능한 병렬로 실행하세요.\n- 빠른 검사(커밋마다)와 느린 검사(메인 브랜치, 야간, 프리릴리스)를 분리하세요.\n\n### 모노레포에서 유용한 전술\n\n모노레포는 모든 커밋마다 "세상 전체를 빌드"하면 고통스러워집니다. 해결책은 변경에 영향을 받는 부분만 빌드하고 테스트하는 것입니다.\n\n경로 필터와 영향도 기반 접근을 사용하세요: 모바일 UI 코드를 건드렸다면 백엔드 이미지를 굳이 다시 빌드할 필요가 없습니다. 공유 라이브러리를 건드렸다면 그 라이브러리에 의존하는 앱만 빌드·테스트하세요. 많은 팀이 간단한 의존성 그래프를 만들어 CI가 추정 대신 결정을 내리게 합니다.\n\n### 폴리레포에서 드리프트를 막는 전술\n\n폴리레포는 각 레포가 작아 상대적으로 빠를 수 있지만 중복과 도구 불일치로 시간을 낭비하기 쉽습니다.\n\n공유 CI 템플릿(동일한 단계, 동일한 캐시, 동일한 규약)을 유지해 모든 레포가 파이프라인을 재발명하지 않게 하세요. 런타임 버전, 빌드 도구, 린터 등 툴체인을 고정해 한 레포에서 동작하지만 다른 레포에서는 동작하지 않는 문제를 피하세요. 종속성 다운로드가 병목이라면 공유 캐시나 내부 미러를 설정해 각 레포가 처음부터 모든 것을 내려받지 않도록 하세요.\n\n구체적 예: 기능이 status라는 새 필드를 추가한다고 합시다. 백엔드 변경, 웹 반영, 모바일 반영 순이라면 모노레포에서는 백엔드 테스트와 API 클라이언트에 의존하는 웹·모바일 부분만 CI에서 실행하면 됩니다. 폴리레포에서는 각 레포가 자체 빠른 검사를 실행하고, 세 릴리스가 여전히 일치하는지 검증하는 별도의 통합 파이프라인을 두면 됩니다.\n\n소스 코드를 내보내어 자체 CI를 실행한다면 같은 규칙을 따르세요: 변경된 부분만 빌드하고 캐시를 적극적으로 재사용하며 느린 검사는 실제 가치를 더할 때만 예약하세요.\n\n## 단계별: 팀에 맞는 레포 전략 선택하기\n\n이 결정을 이념에서 시작하지 말고 일상 업무에서 시작하면 쉬워집니다.\n\n### 1) 함께 변경되어야 하는 것들을 적어보세요\n\n최근 510개 기능을 골라 어떤 부분이 락스텝(lockstep)으로 움직였는지 적어보세요. 각 기능이 UI 화면, API 엔드포인트, 데이터 테이블, 인증 규칙, 공유 검증을 건드렸는지 표시하세요. 대부분의 기능이 세 영역 모두를 건드린다면, 엄격히 분리된 구성은 릴리스 프로세스가 아주 규율 있어야만 고통을 줄여줍니다.\n\n### 2) 공유 코드와 의사결정 흐름을 추적하세요\n\n공유 코드는 라이브러리뿐 아니라 계약(API 스키마), UI 패턴, 비즈니스 규칙도 포함합니다. 현재 어디에 있고 누가 편집하며 변경을 어떻게 승인하는지 적어보세요. 공유 조각이 레포 간에 복사되어 있다면 모노레포나 엄격한 버전 규칙으로 제어를 강화해야 할 신호입니다.\n\n### 3) 경계와 소유자를 정의하세요\n\n단위를(앱, 서비스, 라이브러리) 결정한 뒤 각 단위에 소유자를 할당하세요. 경계는 레포 배치보다 더 중요합니다. 소유권 없이는 모노레포가 시끄러워지고, 소유권 없이는 폴리레포가 연결이 끊긴 상태가 됩니다.\n\n간단한 체크리스트을 원하면 목표는 다음과 같습니다: 배포 가능한 서비스/앱마다 하나의 레포 또는 폴더, 공유 계약은 한 곳, 진정으로 공유되는 UI 컴포넌트는 한 곳, 비즈니스 로직이 어디에 있는지에 대한 명확한 규칙, 각 항목의 문서화된 소유자.\n\n### 4) 따를 수 있는 릴리스 모델을 선택하세요\n\n모바일 릴리스가 백엔드 변경보다 느리다면 호환성 계획(버전 엔드포인트, 역호환 필드, 정의된 지원 창)이 필요합니다. 모든 것을 함께 배포해야 한다면 릴리스 트레인이 가능하지만 조율 비용이 증가합니다.\n\n브랜칭 규칙을 단순하게 유지하세요: 단명 브랜치, 작은 머지, 명확한 핫픽스 경로.\n\n### 5) 일상적 변경 중심으로 CI를 설계하세요\n\n처음부터 최악의 경우에 맞춰 CI를 설계하지 마세요. 매일 사람들이 하는 일에 맞춰 설계하세요.\n\n대부분의 커밋이 웹 UI만 건드린다면 기본적으로 웹 린트와 유닛 테스트를 실행하고 전체 E2E 테스트는 일정에 따라 또는 릴리스 전 실행하세요. 대부분의 사고가 API 드리프트에서 발생한다면 우선 계약 테스트와 클라이언트 자동 생성을 투자하시요.\n\n## 예: 웹, 모바일, 백엔드를 건드는 하나의 기능\n\n작은 팀이 고객 포털(웹), 현장 앱(모바일), API(백엔드)를 동시에 개발한다고 가정합시다. 요청이 들어왔습니다: 작업에 새 ‘서비스 상태(Service status)’ 필드를 추가하고 모든 곳에 표시하세요.\n\n변경은 작아 보이지만 조율 시험이 됩니다. 백엔드는 필드를 추가하고 검증과 응답을 업데이트합니다. 웹은 이를 표시하고 필터를 업데이트합니다. 모바일은 오프라인 표시, 동기화, 엣지 케이스를 처리해야 합니다.\n\n실제 문제는 API 변경이 파괴적이라는 점입니다. 필드 이름이 status에서 service_status로 바뀌고, 이전 클라이언트가 이를 처리하지 못하면 크래시가 납니다.\n\n### 모노레포에서 달라지는 점\n\n모노레포는 대체로 차분하게 느껴질 수 있습니다. 백엔드, 웹, 모바일 업데이트를 하나의 PR(또는 조정된 커밋 묶음)으로 올릴 수 있습니다. CI는 영향받은 테스트만 실행하고 세 업데이트를 포함한 단일 릴리스를 태그할 수 있습니다.\n\n주된 위험은 기술적이라기보다 사회적입니다: 한 레포에 있으면 파괴적 변경을 빠르게 병합하기 쉬우므로 리뷰 규칙을 엄격히 해야 합니다.\n\n### 폴리레포에서 달라지는 점\n\n별도 레포라면 각 앱이 자체 일정대로 움직입니다. 백엔드가 먼저 배포하면 웹과 모바일이 따라잡느라 애를 먹을 수 있습니다. 모바일 릴리스가 앱 스토어 심사를 필요로 한다면 코드 변경 자체는 작아도 수정이 배포될 때까지 며칠이 걸릴 수 있습니다.\n\n팀들은 보통 버전된 엔드포인트, 역호환 응답, 긴 폐기 기간, 명확한 롤아웃 단계 같은 구조를 도입해 이 문제를 해결합니다. 효과는 있지만 지속적인 관리가 필요합니다.\n\n증거 기반으로 결정하려면 지난 몇 달을 보세요:\n\n- 사고가 버전 불일치에서 자주 발생하면 더 타이트한 조율을 선택하세요.\n- 릴리스가 빈번하고 시간 민감하다면(특히 모바일) 파괴적 변경을 피하거나 중앙화하세요.\n- 팀이 독립적이고 같은 기능을 거의 건드리지 않는다면 폴리레포의 오버헤드가 감수할 가치가 있습니다.\n\n## 피해야 할 흔한 실수와 덫\n\n대부분의 팀이 실패하는 이유는 ‘잘못된’ 레포 구조를 골라서가 아닙니다. 일상적 습관이 서서히 마찰을 더해 결국 모든 변경이 위험해지기 때문입니다.\n\n### 공유 코드가 쓰레기장 되는 경우\n\n공유 라이브러리는 유혹적입니다: 헬퍼, 타입, UI 조각, ‘임시’ 우회 방법이 쌓입니다. 곧 오래된 코드가 숨는 장소가 되고 누구도 변경이 안전한지 모르게 됩니다.\n\n공유 코드는 작고 엄격하게 유지하세요. “공유”는 많은 팀이 사용하고 신중히 리뷰되며 의도적으로 변경되는 것을 의미해야 합니다.\n\n### 숨겨진 가정으로 인한 강한 결합\n\n별도 레포라도 시스템은 여전히 강하게 결합될 수 있습니다. 결합은 날짜 형식, 열거형 값, 권한 규칙, “이 필드는 항상 존재한다” 같은 가정으로 옮겨갑니다.\n\n예: 모바일은 status = 2를 "승인"으로 처리하고 웹은 "확인"으로 처리한다면 백엔드가 enum 순서를 바꿨을 때 무작위로 보이는 큰 장애가 발생할 수 있습니다.\n\n이럴 때는 계약을 문서화하고 필드 의미와 허용 값 등을 제품 규칙처럼 취급하세요.\n\n### 불분명한 소유권\n\n모두가 아무거나 바꿀 수 있으면 리뷰가 얕아지고 실수가 섞입니다. 아무도 소유하지 않으면 버그가 몇 주째 방치됩니다.\n\n웹, 모바일, 백엔드, 공유 모듈에 대한 소유자를 정의하세요. 소유권은 기여를 막지 않고 올바른 사람이 변경을 보게 합니다.\n\n### 가지치기 없는 CI 성장\n\nCI는 작게 시작해 사건이 생길 때마다 “안전하자”며 새 작업을 추가하다가 나중에 느리고 비싸지기 쉽습니다.\n\n간단한 규칙: 모든 CI 작업에는 명확한 목적과 소유자가 있어야 하고, 더 이상 실제 문제를 잡지 못하면 제거하세요.\n\n정리해야 할 신호로는 작업 간 중복 테스트, 며칠간 빨간 상태인 작업, ‘빠른 변경’ 검증에 빌드 시간이 더 오래 걸리는 상황, 백엔드 전용 변경에 모바일 빌드를 트리거하는 파이프라인 등이 있습니다.\n\n### 부족한 문서화에 의존하는 릴리스 조율\n\n릴리스가 한 사람이 기억해온 순서와 비결에 의존하면 속도가 느려지고 자주 깨집니다.\n\n릴리스 단계를 문서화하고 반복 가능하게 만들며 지루한 검사들을 자동화하세요. 툴이 백엔드와 클라이언트를 일관되게 생성하더라도 명확한 릴리스 규칙은 여전히 필요합니다.\n\n## 레포를 재조직하기 전에 해볼 빠른 점검\n\n레포 재구성 전에 팀이 지금 어떻게 배포하는지 현실 점검을 하세요. 목표는 완벽한 구조가 아니라 한 변경이 웹, 모바일, 백엔드를 건드릴 때 놀라움이 줄어드는 것입니다.\n\n다섯 가지 질문을 해보세요:\n\n- 독립적 배포: 백엔드 수정을 같은 날 모바일 업데이트 없이 배포할 수 있나?\n- API 변경 규칙: 폐기 정책과 오래된 동작을 얼마나 오래 지원할지 문서화돼 있나?\n- 공유 코드 규율: 공유 라이브러리가 일관되게 리뷰되고 버전 관리되나?\n- 중요한 것만 실행하는 CI: CI가 무엇이 변경됐는지 판별해 영향 범위만 빌드/테스트하나?\n- 하나의 릴리스 뷰: 웹, 모바일, 백엔드에서 무엇이 나가는지 소유자와 날짜를 포함해 한곳에서 볼 수 있나?\n\n간단한 예: 체크아웃에 새 ‘주소’ 필드를 추가할 때 백엔드가 먼저 배포되어도 기존 모바일 앱이 계속 동작하려면 API가 구/신 payload를 당분간 모두 허용해야 합니다. 이는 클라이언트 업데이트가 옵션이지 필수가 아니게 합니다.\n\n## 다음 단계: 조율 비용 줄이고 자신 있게 배포하기\n\n목표는 ‘옳은’ 레포 구조가 아니라 핸드오프와 놀라움을 줄이고 ‘지금 어떤 버전이 라이브인가?’라는 물음이 사라지게 하는 것입니다.\n\n간단한 결정 기록을 작성하세요: 현재 접근을 선택한 이유, 개선 기대치, 감수하는 트레이드오프를 적고 612개월마다(혹은 팀 규모나 배포 주기가 바뀌면 더 자주) 재검토하세요.\n\n파일을 옮기기 전에 실제 통증을 줄이는 가장 작은 변경부터 시작하세요:\n\n- 공유 패키지에 대한 버전 규칙을 추가하고 따르기.\n- API 계약을 정의하고 CI에서 계약 테스트로 강제하기.\n- 웹, 모바일, 백엔드 전반에 통일된 릴리스 체크리스트 합의하기.\n- 여러 부분에 걸친 변경은 프리뷰 환경으로 검증하기.\n- PR 검사 시간을 제한(예: PR 체크 15분 이하)하는 CI 예산 설정하기.\n\n교차 코드베이스 결합이 병목이면 변경해야 할 장소 수를 줄이는 것이 레포 구조보다 더 큰 효과를 낼 수 있습니다. 일부 팀은 더 많은 로직과 데이터 모델링을 단일 진실 원본으로 옮겨 이 문제를 해결합니다.\n\n그 접근을 시험해보고 싶다면 AppMaster (appmaster.io)는 공유 데이터 모델과 비즈니스 로직으로 백엔드 서비스, 웹 앱, 네이티브 모바일 앱을 생성하도록 설계되어 있습니다. 위험이 적은 평가 방법은 작은 내부 툴 하나를 먼저 만들어 보고 얼마나 많은 조율 작업이 사라지는지 기반으로 결정하는 것입니다.\n\n자신감 있는 길은 일부러 지루합니다: 결정을 문서화하고 결합을 줄이며 검사를 자동화하고, 숫자가 도움이 된다고 말할 때만 레포 구조를 바꾸세요.
status에서 service_status로 바뀌고, 이전 클라이언트가 이를 처리하지 못하면 크래시가 납니다.\n\n### 모노레포에서 달라지는 점\n\n모노레포는 대체로 차분하게 느껴질 수 있습니다. 백엔드, 웹, 모바일 업데이트를 하나의 PR(또는 조정된 커밋 묶음)으로 올릴 수 있습니다. CI는 영향받은 테스트만 실행하고 세 업데이트를 포함한 단일 릴리스를 태그할 수 있습니다.\n\n주된 위험은 기술적이라기보다 사회적입니다: 한 레포에 있으면 파괴적 변경을 빠르게 병합하기 쉬우므로 리뷰 규칙을 엄격히 해야 합니다.\n\n### 폴리레포에서 달라지는 점\n\n별도 레포라면 각 앱이 자체 일정대로 움직입니다. 백엔드가 먼저 배포하면 웹과 모바일이 따라잡느라 애를 먹을 수 있습니다. 모바일 릴리스가 앱 스토어 심사를 필요로 한다면 코드 변경 자체는 작아도 수정이 배포될 때까지 며칠이 걸릴 수 있습니다.\n\n팀들은 보통 버전된 엔드포인트, 역호환 응답, 긴 폐기 기간, 명확한 롤아웃 단계 같은 구조를 도입해 이 문제를 해결합니다. 효과는 있지만 지속적인 관리가 필요합니다.\n\n증거 기반으로 결정하려면 지난 몇 달을 보세요:\n\n- 사고가 버전 불일치에서 자주 발생하면 더 타이트한 조율을 선택하세요.\n- 릴리스가 빈번하고 시간 민감하다면(특히 모바일) 파괴적 변경을 피하거나 중앙화하세요.\n- 팀이 독립적이고 같은 기능을 거의 건드리지 않는다면 폴리레포의 오버헤드가 감수할 가치가 있습니다.\n\n## 피해야 할 흔한 실수와 덫\n\n대부분의 팀이 실패하는 이유는 ‘잘못된’ 레포 구조를 골라서가 아닙니다. 일상적 습관이 서서히 마찰을 더해 결국 모든 변경이 위험해지기 때문입니다.\n\n### 공유 코드가 쓰레기장 되는 경우\n\n공유 라이브러리는 유혹적입니다: 헬퍼, 타입, UI 조각, ‘임시’ 우회 방법이 쌓입니다. 곧 오래된 코드가 숨는 장소가 되고 누구도 변경이 안전한지 모르게 됩니다.\n\n공유 코드는 작고 엄격하게 유지하세요. “공유”는 많은 팀이 사용하고 신중히 리뷰되며 의도적으로 변경되는 것을 의미해야 합니다.\n\n### 숨겨진 가정으로 인한 강한 결합\n\n별도 레포라도 시스템은 여전히 강하게 결합될 수 있습니다. 결합은 날짜 형식, 열거형 값, 권한 규칙, “이 필드는 항상 존재한다” 같은 가정으로 옮겨갑니다.\n\n예: 모바일은 status = 2를 "승인"으로 처리하고 웹은 "확인"으로 처리한다면 백엔드가 enum 순서를 바꿨을 때 무작위로 보이는 큰 장애가 발생할 수 있습니다.\n\n이럴 때는 계약을 문서화하고 필드 의미와 허용 값 등을 제품 규칙처럼 취급하세요.\n\n### 불분명한 소유권\n\n모두가 아무거나 바꿀 수 있으면 리뷰가 얕아지고 실수가 섞입니다. 아무도 소유하지 않으면 버그가 몇 주째 방치됩니다.\n\n웹, 모바일, 백엔드, 공유 모듈에 대한 소유자를 정의하세요. 소유권은 기여를 막지 않고 올바른 사람이 변경을 보게 합니다.\n\n### 가지치기 없는 CI 성장\n\nCI는 작게 시작해 사건이 생길 때마다 “안전하자”며 새 작업을 추가하다가 나중에 느리고 비싸지기 쉽습니다.\n\n간단한 규칙: 모든 CI 작업에는 명확한 목적과 소유자가 있어야 하고, 더 이상 실제 문제를 잡지 못하면 제거하세요.\n\n정리해야 할 신호로는 작업 간 중복 테스트, 며칠간 빨간 상태인 작업, ‘빠른 변경’ 검증에 빌드 시간이 더 오래 걸리는 상황, 백엔드 전용 변경에 모바일 빌드를 트리거하는 파이프라인 등이 있습니다.\n\n### 부족한 문서화에 의존하는 릴리스 조율\n\n릴리스가 한 사람이 기억해온 순서와 비결에 의존하면 속도가 느려지고 자주 깨집니다.\n\n릴리스 단계를 문서화하고 반복 가능하게 만들며 지루한 검사들을 자동화하세요. 툴이 백엔드와 클라이언트를 일관되게 생성하더라도 명확한 릴리스 규칙은 여전히 필요합니다.\n\n## 레포를 재조직하기 전에 해볼 빠른 점검\n\n레포 재구성 전에 팀이 지금 어떻게 배포하는지 현실 점검을 하세요. 목표는 완벽한 구조가 아니라 한 변경이 웹, 모바일, 백엔드를 건드릴 때 놀라움이 줄어드는 것입니다.\n\n다섯 가지 질문을 해보세요:\n\n- 독립적 배포: 백엔드 수정을 같은 날 모바일 업데이트 없이 배포할 수 있나?\n- API 변경 규칙: 폐기 정책과 오래된 동작을 얼마나 오래 지원할지 문서화돼 있나?\n- 공유 코드 규율: 공유 라이브러리가 일관되게 리뷰되고 버전 관리되나?\n- 중요한 것만 실행하는 CI: CI가 무엇이 변경됐는지 판별해 영향 범위만 빌드/테스트하나?\n- 하나의 릴리스 뷰: 웹, 모바일, 백엔드에서 무엇이 나가는지 소유자와 날짜를 포함해 한곳에서 볼 수 있나?\n\n간단한 예: 체크아웃에 새 ‘주소’ 필드를 추가할 때 백엔드가 먼저 배포되어도 기존 모바일 앱이 계속 동작하려면 API가 구/신 payload를 당분간 모두 허용해야 합니다. 이는 클라이언트 업데이트가 옵션이지 필수가 아니게 합니다.\n\n## 다음 단계: 조율 비용 줄이고 자신 있게 배포하기\n\n목표는 ‘옳은’ 레포 구조가 아니라 핸드오프와 놀라움을 줄이고 ‘지금 어떤 버전이 라이브인가?’라는 물음이 사라지게 하는 것입니다.\n\n간단한 결정 기록을 작성하세요: 현재 접근을 선택한 이유, 개선 기대치, 감수하는 트레이드오프를 적고 6자주 묻는 질문
웹, 모바일, 백엔드에서 한 기능이 얼마나 자주 함께 바뀌는지부터 시작하세요. 대부분의 작업이 교차 영역이고 조율이 주요 문제라면 모노레포나 ‘단일 계약’ 접근법이 파손을 줄이는 경향이 있습니다. 반대로 팀들이 거의 같은 영역을 건드리지 않고 독립적 배포가 중요하다면 폴리레포가 엄격한 호환성 규칙과 함께 잘 작동할 수 있습니다.
API 드리프트, 공유 라이브러리 버전 불일치, 그리고 특히 모바일 앱 스토어 심사로 인한 릴리스 타이밍 차이가 일반적인 원인입니다. 해결책은 완벽한 동기화된 릴리스를 가정하지 말고 혼합 버전을 계획하며, 파괴적 변경은 드물고 의도적으로 만들도록 하는 것입니다.
API 스키마를 진실의 원본으로 취급하고 거기서 클라이언트를 생성해 빌드 단계에서 불일치가 드러나게 하세요. 먼저 추가 방식의 변경(새 필드, 새 엔드포인트)을 선호하고, 이후에 점진적으로 폐기하세요. 이름을 바꾸거나 제거해야 할 때는 짧은 호환성 창을 두세요.
작고 규칙적인 업데이트(주간)가 분기 업데이트보다 낫고, 파괴적 변경에는 명시적 승인을 요구하세요. 각 변경에 짧은 마이그레이션 노트를 남기고 ‘완료’ 기준을 단일 레포 통과가 아닌 “웹, 모바일, 백엔드 빌드가 모두 정상”으로 정의하세요.
기본 권장 모델은 서비스별 버전으로, 어떤 백엔드 버전이 어떤 클라이언트 버전을 지원하는지 그리고 얼마나 오래 지원할지에 대한 명확한 호환성 규칙을 두는 것입니다. 초기에 하나의 릴리스 트레인은 가능하지만 모바일 지연 때문에 오래 지속되기 힘든 경우가 많습니다.
백엔드가 먼저 배포되어도 구버전 모바일 사용자가 깨지지 않게 백엔드를 호환성 있게 유지하세요. 필드는 추가 방식으로 도입하고 오래된 동작을 너무 빨리 제거하지 마세요. 클라이언트에 변경이 필요할 때는 기능 플래그를 사용해 점진적으로 롤아웃하세요.
릴리스 조율 담당을 명확히 하세요. 보통 기술 리드, 릴리스 매니저, 혹은 엔지니어링 지원이 있는 제품 담당자가 맡습니다. 목표는 복잡한 프로세스가 아니라 반복 가능한 캘린더와 지연 시 결정 규칙(변경 보류 vs 호환성 유지)입니다.
변화된 부분만 빌드·테스트하고 가능한 모든 것을 캐시하세요. 빠른 체크(커밋마다)와 느린 체크(주요 브랜치, 야간, 프리릴리스)를 분리해 개발자가 빠른 피드백을 받게 하세요.
경로 필터와 ‘영향 범위만’ 빌드하는 방식을 사용하면 작은 변경에 전체를 빌드하지 않아도 됩니다. 공유 모듈이 바뀌면 해당 모듈에 의존하는 앱만 체크하도록 하고, 소유권과 리뷰 규칙을 명확히 해 레포가 잡동사니 창고가 되지 않게 하세요.
레포별로 도구와 CI 템플릿을 표준화해 각 레포가 파이프라인을 다시 만들지 않게 하세요. 핵심 계약을 검증하는 통합 체크를 추가하고, 툴체인 버전을 고정해 한 레포에선 동작하지만 다른 레포에선 동작하지 않는 문제를 피하세요.


