3-4. Git의 submodule: 프로젝트 종속성 관리

1. Submodule의 개념과 필요성

Git submodule은 프로젝트 내에서 다른 Git 저장소를 종속성으로 관리할 수 있게 해주는 기능입니다. 마치 C/C++에서 include 문을 사용하여 다른 헤더 파일을 가져오는 것과 유사하다고 볼 수 있습니다. 프로젝트가 복잡해지고, 다른 라이브러리나 모듈을 가져와 사용해야 할 때, 각 종속성을 개별적인 Git 저장소로 관리하고, 메인 프로젝트에서 해당 종속성을 특정 버전으로 고정하여 관리할 수 있도록 해줍니다.

1) 왜 Submodule을 사용할까?

프로젝트를 개발하다 보면, 다른 팀에서 개발한 라이브러리를 사용하거나, 오픈 소스 프로젝트의 코드를 가져와서 사용해야 하는 경우가 빈번하게 발생합니다. 이러한 경우, 다음과 같은 문제에 직면할 수 있습니다.

  • 종속성 관리의 어려움: 직접 코드를 복사해서 사용하는 경우, 종속성의 업데이트를 추적하고, 메인 프로젝트와 종속성의 호환성을 유지하기가 어렵습니다.
  • 코드 중복: 동일한 라이브러리를 여러 프로젝트에서 사용해야 할 경우, 각 프로젝트마다 라이브러리 코드를 복사해야 하므로 코드 중복이 발생합니다.
  • 업데이트의 번거로움: 종속성의 변경 사항을 반영하려면, 각 프로젝트에서 해당 코드를 일일이 업데이트해야 합니다.

submodule은 이러한 문제를 해결하기 위해 고안되었습니다. submodule을 사용하면, 종속성을 외부 Git 저장소로 관리하고, 메인 프로젝트에서는 특정 커밋을 가리키도록 설정할 수 있습니다. 이를 통해 종속성의 업데이트를 쉽게 관리하고, 코드 중복을 방지하며, 메인 프로젝트와 종속성 간의 호환성을 유지할 수 있습니다.

2) Submodule과 Subtree의 비교

Git에는 submodule 외에도 종속성을 관리하는 또 다른 방법인 subtree가 있습니다. 두 가지 방법 모두 외부 저장소를 프로젝트에 통합하는 기능을 제공하지만, 작동 방식과 사용 사례에 차이가 있습니다.

  • Submodule: 외부 저장소를 별도의 독립적인 Git 저장소로 유지합니다. 메인 프로젝트는 submodule의 위치와 특정 커밋을 기억합니다. submodule 내에서 변경 사항을 커밋하고, 메인 프로젝트에서 이를 업데이트할 수 있습니다.
  • Subtree: 외부 저장소의 코드를 메인 프로젝트의 일부로 병합합니다. 외부 저장소의 히스토리를 유지하면서, 메인 프로젝트의 히스토리와 통합됩니다.
기능 Submodule Subtree
저장소 분리 아니오 (메인 프로젝트에 통합)
사용 편의성 복잡 (별도 명령어 사용) 상대적으로 쉬움 (git merge 사용)
히스토리 관리 독립적인 히스토리 메인 프로젝트와 통합된 히스토리
업데이트 별도의 업데이트 명령어 ( git submodule update ) git merge 또는 git cherry-pick 사용
사용 사례 대규모 프로젝트, 독립적인 종속성 관리 소규모 프로젝트, 단순한 종속성 관리

일반적으로 submodule은 다음과 같은 경우에 사용합니다.

  • 종속성이 별도의 Git 저장소로 관리되고 있으며, 해당 저장소의 전체 히스토리를 유지해야 하는 경우
  • 종속성을 여러 프로젝트에서 공유하고, 각 프로젝트에서 특정 버전을 고정하여 사용해야 하는 경우
  • 종속성을 업데이트할 때, 메인 프로젝트에 영향을 미치지 않도록 격리하여 관리해야 하는 경우

subtree는 다음과 같은 경우에 사용합니다.

  • 종속성이 작고, 메인 프로젝트에 쉽게 통합될 수 있는 경우
  • 종속성의 코드를 수정하고, 메인 프로젝트와 함께 관리해야 하는 경우
  • 종속성의 히스토리를 메인 프로젝트와 함께 관리해야 하는 경우

2. Submodule 사용법

submodule을 사용하는 기본적인 단계는 다음과 같습니다.

1) Submodule 추가

git submodule add <repository> <path> 명령어를 사용하여, 외부 Git 저장소를 submodule로 추가합니다.

  • <repository>: 외부 Git 저장소의 URL
  • <path>: submodule을 메인 프로젝트 내에 위치시킬 경로 (예: lib/mylibrary)
git submodule add https://github.com/example/mylibrary.git lib/mylibrary

이 명령어를 실행하면, 다음과 같은 작업이 수행됩니다.

  1. 지정된 URL에서 submodule 저장소를 클론합니다.
  2. 메인 프로젝트의 .gitmodules 파일에 submodule 정보를 추가합니다.
  3. .gitmodules 파일에 대한 변경 사항을 스테이징하고 커밋합니다.
  4. 메인 프로젝트에서 submodule을 사용할 수 있도록 .git 디렉터리에 설정 파일들을 생성합니다.

.gitmodules 파일은 다음과 같은 정보를 포함합니다.

[submodule "lib/mylibrary"]
    path = lib/mylibrary
    url = https://github.com/example/mylibrary.git

git status 명령어를 실행하면, submodule이 추가된 디렉터리의 상태가 표시됩니다.

On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   .gitmodules
        new file:   lib/mylibrary

2) Submodule 초기화 및 업데이트

submodule을 추가한 후에는, git submodule initgit submodule update 명령어를 사용하여 submodule을 초기화하고, 최신 상태로 업데이트해야 합니다.

  • git submodule init: .gitmodules 파일을 기반으로, submodule을 초기화합니다.
  • git submodule update: submodule의 내용을 업데이트합니다. git clone 명령어를 사용하여, 외부 저장소에서 최신 코드를 가져오고, 메인 프로젝트의 작업 디렉터리에 적용합니다.
git submodule init
git submodule update

.gitmodules 파일을 수정하거나, submodule의 URL을 변경한 경우에는, git submodule sync 명령어를 사용하여 .gitmodules 파일의 변경 사항을 적용해야 합니다.

3) Submodule에서 변경 사항 관리

submodule 내에서 변경 사항을 수정하고, 커밋할 수 있습니다.

  1. submodule 디렉터리로 이동합니다.
  2. 변경 사항을 수정하고, 스테이징하고, 커밋합니다.
  3. 메인 프로젝트 디렉터리로 돌아와서, submodule 디렉터리의 변경 사항을 스테이징하고 커밋합니다.
cd lib/mylibrary
# 변경 사항 수정
git add .
git commit -m "feat: updated library feature"
cd ..
git add lib/mylibrary  # submodule 변경 사항 스테이징
git commit -m "feat: updated submodule mylibrary"

4) Submodule 삭제

submodule을 삭제하려면, 다음과 같은 단계를 수행합니다.

  1. .gitmodules 파일에서 해당 submodule에 대한 정보를 삭제합니다.
  2. git rm --cached <submodule path> 명령어를 사용하여, 메인 프로젝트에서 submodule을 제거합니다.
  3. submodule 디렉터리를 수동으로 삭제합니다.
  4. .git/config 파일에서 submodule 관련 설정을 삭제합니다.
  5. 삭제된 파일 및 .gitmodules 파일에 대한 변경 사항을 커밋합니다.
git rm --cached lib/mylibrary
rm -rf lib/mylibrary
# .gitmodules 파일에서 [submodule "lib/mylibrary"] 섹션 삭제
git commit -m "feat: remove submodule mylibrary"

5) Submodule clone

submodule이 포함된 프로젝트를 다른 곳에서 클론할 때, git clone 명령어를 사용하면, submodule은 초기화되지 않은 상태로 클론됩니다. 따라서, git submodule initgit submodule update 명령어를 실행하여, submodule을 초기화하고 업데이트해야 합니다.

git clone <repository>
git submodule init
git submodule update

혹은, git clone --recurse-submodules <repository> 명령어를 사용하여, submodule을 자동으로 초기화하고 업데이트할 수 있습니다.

git clone --recurse-submodules <repository>

6) Submodule 사용 시 주의사항

  • submodule은 특정 커밋을 가리키므로, submodule의 변경 사항을 메인 프로젝트에 적용하려면, 메인 프로젝트에서 submodule을 업데이트하고, 커밋해야 합니다.
  • submodule의 변경 사항을 병합할 때, 충돌이 발생할 수 있습니다. 충돌을 해결하려면, submodule 디렉터리에서 변경 사항을 병합하고, 메인 프로젝트에서 다시 submodule을 업데이트해야 합니다.
  • submodule의 URL이 변경된 경우, git submodule sync 명령어를 사용하여, .gitmodules 파일의 변경 사항을 적용해야 합니다.
  • submodule을 삭제한 후, .gitmodules 파일 및 .git/config 파일에서 관련 설정을 제거해야 합니다.

Submodule 사용법 설명 뒤

3. Submodule 활용 사례

submodule은 다양한 프로젝트에서 종속성을 관리하는 데 사용될 수 있습니다. 다음은 몇 가지 활용 사례입니다.

1) 오픈 소스 라이브러리 연동

프로젝트에서 외부 오픈 소스 라이브러리를 사용해야 할 때, 해당 라이브러리를 submodule로 추가하여 관리할 수 있습니다. 이렇게 하면, 라이브러리의 특정 버전을 고정하여 사용할 수 있으며, 라이브러리의 업데이트를 쉽게 관리할 수 있습니다.

예를 들어, 웹 프론트엔드 프로젝트에서 React 라이브러리를 사용한다고 가정해 봅시다. React 라이브러리를 submodule로 추가하면 다음과 같은 장점이 있습니다.

  • 프로젝트는 특정 버전의 React를 사용하도록 고정됩니다.
  • React의 업데이트를 쉽게 관리할 수 있습니다.
  • React의 코드를 프로젝트의 일부로 관리할 수 있습니다.

2) 공통 코드 모듈 공유

여러 프로젝트에서 재사용되는 공통 코드 모듈을 submodule로 관리할 수 있습니다. 이렇게 하면, 각 프로젝트에서 해당 모듈의 특정 버전을 공유하고, 모듈의 변경 사항을 쉽게 반영할 수 있습니다.

예를 들어, 여러 백엔드 프로젝트에서 사용되는 API 클라이언트 라이브러리를 submodule로 추가한다고 가정해 봅시다. API 클라이언트 라이브러리를 submodule로 관리하면 다음과 같은 장점이 있습니다.

  • 각 프로젝트는 동일한 버전의 API 클라이언트 라이브러리를 사용합니다.
  • API 클라이언트 라이브러리의 변경 사항을 쉽게 반영할 수 있습니다.
  • API 클라이언트 라이브러리의 코드를 여러 프로젝트에서 공유할 수 있습니다.

3) 3rd party SDK 통합

3rd party SDK를 프로젝트에 통합할 때, 해당 SDK를 submodule로 추가하여 관리할 수 있습니다. 이렇게 하면, SDK의 특정 버전을 고정하고, SDK의 업데이트를 쉽게 관리할 수 있습니다.

예를 들어, 모바일 앱 프로젝트에서 3rd party SDK를 사용한다고 가정해 봅시다. 3rd party SDK를 submodule로 추가하면 다음과 같은 장점이 있습니다.

  • 앱은 특정 버전의 SDK를 사용하도록 고정됩니다.
  • SDK의 업데이트를 쉽게 관리할 수 있습니다.
  • SDK의 코드를 앱 프로젝트의 일부로 관리할 수 있습니다.

4. Submodule의 단점과 대안

submodule은 종속성 관리에 유용한 기능을 제공하지만, 몇 가지 단점도 존재합니다. 이러한 단점을 고려하여, 다른 대안을 선택할 수도 있습니다.

1) Submodule의 단점

  • 사용의 복잡성: submodule을 사용하기 위해서는, 여러 가지 명령어를 기억하고, submodule의 작동 방식을 이해해야 합니다. 특히, 초보자에게는 진입 장벽이 높을 수 있습니다.
  • 유지보수의 어려움: submodule은 별도의 Git 저장소로 관리되기 때문에, 메인 프로젝트와 submodule 간의 변경 사항을 동기화하는 데 어려움이 있을 수 있습니다. 예를 들어, submodule의 변경 사항을 메인 프로젝트에 반영하려면, submodule을 업데이트하고, 메인 프로젝트에서 커밋해야 합니다.
  • 개발 환경 설정의 번거로움: submodule을 사용하는 프로젝트를 처음 클론하는 경우, submodule을 초기화하고 업데이트해야 합니다. 이는 개발 환경 설정 과정을 복잡하게 만들 수 있습니다.
  • 파일 경로 문제: submodule의 경로는 상대적이기 때문에, 프로젝트의 파일 구조가 변경될 경우, submodule의 경로도 변경해야 합니다.
  • 대용량 저장소: submodule은 각 submodule의 전체 히스토리를 포함하기 때문에, 메인 프로젝트의 저장소 크기를 증가시킬 수 있습니다.

2) Submodule의 대안

submodule의 단점을 보완하기 위해, 다음과 같은 대안을 고려할 수 있습니다.

  • 패키지 관리자: npm, yarn, pip, maven과 같은 패키지 관리자를 사용하여, 종속성을 관리할 수 있습니다. 패키지 관리자는 종속성을 자동으로 다운로드하고, 관리하며, 업데이트를 쉽게 할 수 있습니다. 대부분의 현대적인 개발 환경에서는 패키지 관리자를 사용하는 것이 일반적입니다.

    패키지 관리자를 사용하면, 종속성 관리의 복잡성을 줄이고, 개발 생산성을 향상시킬 수 있습니다.

  • Subtree: subtreesubmodule보다 사용하기 쉽고, 메인 프로젝트와 종속성 간의 변경 사항을 동기화하는 데 용이합니다. 그러나, 종속성의 히스토리를 메인 프로젝트와 함께 관리해야 하므로, 종속성의 규모가 큰 경우에는 적합하지 않을 수 있습니다.
  • Git Hooks: Git hooks을 사용하여, submodule 관련 작업을 자동화할 수 있습니다. 예를 들어, post-checkout hook을 사용하여, submodule을 자동으로 초기화하고 업데이트할 수 있습니다.

    Git hooks를 사용하면, submodule 사용의 복잡성을 줄이고, 개발 생산성을 향상시킬 수 있습니다.

Submodule의 대안 설명 뒤

5. Submodule 사용 시 주의사항과 팁

submodule을 사용할 때, 몇 가지 주의사항과 팁을 숙지하면, 효율적으로 프로젝트를 관리할 수 있습니다.

1) Submodule 업데이트 전략

submodule의 업데이트 전략을 신중하게 선택해야 합니다. 무작정 submodule을 최신 버전으로 업데이트하면, 메인 프로젝트와의 호환성 문제가 발생할 수 있습니다.

  • 특정 버전 고정: submodule을 특정 버전으로 고정하여 사용하는 것이 좋습니다. 이렇게 하면, 메인 프로젝트와 submodule 간의 호환성을 유지할 수 있으며, 예상치 못한 오류를 방지할 수 있습니다.
  • 업데이트 테스트: submodule을 업데이트하기 전에, 메인 프로젝트에서 테스트를 수행하여, 호환성 문제를 확인해야 합니다.
  • 변경 사항 관리: submodule의 변경 사항을 메인 프로젝트에 반영할 때, 커밋 메시지에 변경 사항에 대한 자세한 설명을 포함해야 합니다.

2) Submodule 공유

submodule을 사용하는 프로젝트를 다른 사람과 공유할 때, 다음과 같은 사항을 고려해야 합니다.

  • .gitmodules 파일 공유: .gitmodules 파일을 공유하여, submodule 정보를 다른 사람에게 알려야 합니다.
  • git submodule initgit submodule update 실행: 프로젝트를 클론한 후, git submodule initgit submodule update 명령어를 실행하여, submodule을 초기화하고 업데이트해야 합니다.
  • .git 디렉터리 숨김: .git 디렉터리는 프로젝트의 중요한 정보를 담고 있으므로, .gitignore 파일에 추가하여, 불필요하게 공유되지 않도록 해야 합니다.

3) Submodule 관련 명령어 숙지

submodule 관련 명령어를 숙지하고, 필요에 따라 활용해야 합니다.

  • git submodule add <repository> <path>: submodule 추가
  • git submodule init: submodule 초기화
  • git submodule update: submodule 업데이트
  • git submodule status: submodule 상태 확인
  • git submodule foreach <command>: 각 submodule에 대해 특정 명령어 실행
  • git submodule sync: .gitmodules 파일 변경 사항 동기화
  • git clone --recurse-submodules <repository>: submodule을 포함하여 클론

4) Submodule 디렉터리 관리

submodule 디렉터리를 관리할 때, 다음과 같은 사항을 고려해야 합니다.

  • submodule 디렉터리 접근: submodule 디렉터리에 접근하여, submodule의 내용을 수정할 수 있습니다.
  • submodule 디렉터리 변경 사항 관리: submodule 디렉터리에서 변경 사항을 수정하고, 스테이징하고, 커밋해야 합니다.
  • 메인 프로젝트와의 동기화: submodule 디렉터리의 변경 사항을 메인 프로젝트에 반영하려면, 메인 프로젝트에서 git add 명령어를 사용하여 submodule 디렉터리를 스테이징하고, 커밋해야 합니다.

5) 트러블슈팅

submodule 사용 시 발생할 수 있는 문제와 해결 방법을 알아두면, 문제 발생 시 빠르게 대처할 수 있습니다.

  • submodule이 초기화되지 않음: git submodule init 명령어를 실행하여, submodule을 초기화해야 합니다.
  • submodule이 업데이트되지 않음: git submodule update 명령어를 실행하여, submodule을 업데이트해야 합니다.
  • submodule 관련 오류 발생: git submodule status 명령어를 사용하여, submodule의 상태를 확인하고, 오류 메시지를 참고하여 문제를 해결해야 합니다.
  • 충돌 발생: submodule의 변경 사항을 병합할 때, 충돌이 발생할 수 있습니다. 충돌을 해결하려면, submodule 디렉터리에서 변경 사항을 병합하고, 메인 프로젝트에서 다시 submodule을 업데이트해야 합니다.

6. 결론

submodule은 프로젝트의 종속성을 관리하는 강력한 기능입니다. submodule을 사용하면, 종속성을 외부 Git 저장소로 관리하고, 메인 프로젝트에서는 특정 버전을 고정하여 관리할 수 있습니다. 이를 통해 종속성의 업데이트를 쉽게 관리하고, 코드 중복을 방지하며, 메인 프로젝트와 종속성 간의 호환성을 유지할 수 있습니다.

submodule은 복잡한 개념이지만, 몇 가지 기본적인 사용법과 주의사항을 숙지하면, 효율적으로 프로젝트를 관리할 수 있습니다. 또한, submodule의 대안을 고려하여, 프로젝트의 특성에 맞는 종속성 관리 방법을 선택할 수 있습니다. 프로젝트의 규모, 종속성의 종류, 팀의 개발 환경 등을 고려하여, 가장 적합한 방법을 선택하는 것이 중요합니다.

비슷한 글 추천

Comments (0)

No comments yet. Be the first to comment!