여러 모노레포를 연결하는 Git 서브모듈 활용법 https://www.jannikbuschke.de/blog/git-submodules/
https://www.jannikbuschke.de/blog/git-submodules/
아래는 Jannik Buschke 블로그 글의 내용을 요약한 한국어 정리입니다.
여러 모노레포를 연결하는 Git 서브모듈 활용법
요약: Git 서브모듈은 여러 모노레포 간에 공유 모듈을 함께 개발할 수 있도록 해주는 강력하고 실용적인 방법입니다. "레포 안의 레포", 그것도 여러 겹으로 구성할 수 있어 매우 유용합니다!
1. 소개: 모노레포의 장점과 한계
모노레포(Monorepo)는 복잡한 앱 개발을 단순화해줍니다. 예를 들어, 다음과 같은 구조로 구성할 수 있습니다:
/app-repository
/app1
/app2
/shared-module
app1
과app2
는 비슷한 도메인을 다루며,shared-module
은 공통 유틸리티를 담고 있습니다.- 이 구조에서는
shared-module
을 소스 코드 수준에서 바로 연결할 수 있어, 개발 중인 기능을 즉시 사용하고 API 설계에 대한 빠른 피드백을 받을 수 있습니다.
한계점
shared-module
이app1
,app2
외에도 다른 앱(예:app3
)에서도 유용할 수 있습니다.- 하지만
app3
가 다른 저장소(repository)에 있고, 다른 조직이나 커뮤니티에서 관리한다면,shared-module
을 공유하기 어렵습니다. shared-module
의 빌드 결과물(예: npm 패키지)을 배포하면app3
에서 사용할 수는 있지만, 함께 개발하거나 실시간으로 기여하기는 어렵습니다.
2. 해결책: Git 서브모듈(Submodules)
Git 서브모듈을 사용하면, 하나의 모듈이 여러 모노레포에 동시에 포함되어 개발될 수 있습니다.
구조 예시
먼저
shared-module
을 독립된 저장소로 분리합니다:/module-repository /shared-module
이 저장소를 다른 모노레포에 서브모듈로 추가합니다:
/mono-repository1 /app1 /app2 /generic-module-as-a-git-submodule ← 서브모듈 /mono-repository2 /app3 /generic-module-as-a-git-submodule ← 동일한 서브모듈
- 서브모듈은 특정 커밋(commit)을 가리키는 링크일 뿐, 소스 코드 자체를 포함하지 않습니다.
- 하지만 로컬에서 클론할 때, 서브모듈의 소스도 함께 체크아웃되므로, 마치 하나의 큰 저장소처럼 작업할 수 있습니다.
3. 서브모듈 작업 방법
- 서브모듈 내부에서 명령어 실행: 서브모듈 저장소에 영향을 줍니다.
- 부모 저장소에서 명령어 실행: 부모 저장소에 영향을 줍니다.
- 두 저장소는 저장소 차원에서는 분리되어 있지만, 로컬 파일 시스템에서는 소스 코드가 함께 위치하므로 통합된 개발이 가능합니다.
서브모듈 추가하기
git submodule add <저장소-URL>
.gitmodules
파일이 생성되며, 서브모듈의 경로와 URL을 기록합니다.예:
[submodule "my-module"] path = my-module url = https://github.com/jannikbuschke/my-module.git
서브모듈이 포함된 저장소 클론하기
git clone <저장소-URL> --recursive
--recursive
플래그를 꼭 사용해야 서브모듈도 함께 체크아웃됩니다.- 생략하면 서브모듈 폴더는 비어 있게 되며, 나중에 초기화하는 과정이 번거롭습니다.
서브모듈의 새로운 커밋 반영하기
- 서브모듈에서 커밋을 하면, 부모 저장소는 자동으로 변경되지 않습니다.
부모 저장소에서 다음과 같이 명시적으로 업데이트해야 합니다:
git add <서브모듈-경로> git commit -m "Update submodule to latest commit"
git status
나git diff
를 통해 어떤 커밋을 가리켜야 할지 확인할 수 있습니다.
4. 주의사항 및 팁
- 서브모듈 커밋은 반드시 푸시해야 함:
서브모듈에서 커밋했지만 푸시하지 않으면, 그 커밋은 로컬에만 존재합니다.
이 상태에서 부모 저장소를 푸시하면, 다른 개발자나 CI/CD가 존재하지 않는 커밋을 체크아웃하려 해서 실패할 수 있습니다. - --recursive 플래그 필수:
클론 시--recursive
를 빼먹지 마세요. 이후 수동 초기화는 다소 번거롭습니다. - 서브모듈 진입 시 브랜치 체크아웃:
서브모듈은 기본적으로 detached HEAD 상태(커밋 해시 참조)로 시작합니다.
작업하려면git checkout main
또는git switch -
등으로 브랜치를 명시적으로 체크아웃해야 합니다. - 서브모듈 경로 변경/삭제는 까다로움:
이름 변경이나 삭제는.gitmodules
파일을 직접 수정하거나, 새 위치에 클론하는 것이 가장 안전합니다.
5. 결론
- Git 서브모듈은 종종 "사용하기 어려움", "문서 부족", "이상한 동작" 등으로 평가절하되지만, 실제로는 학습 곡선을 넘기면 매우 강력한 도구입니다.
- 약간의 주의사항이 있지만, 그로 인한 이점이 훨씬 큽니다.
- 여러 앱을 개발하면서 코드를 공유하거나, 오픈소스 프로젝트를 사용하면서 동시에 기여하고 싶다면, Git 서브모듈을 꼭 한번 시도해보세요!
✅ 핵심 메시지: 서브모듈은 "여러 모노레포에서 하나의 모듈을 함께 개발"하는 이상적인 솔루션입니다.