Git submodules

JeongYong Park·2023년 9월 6일
1

개요

프로젝트를 진행하다보면 민감한 정보들을 git에 올리지 못하는 경우가 많습니다.
이번 프로젝트에서는 db의 정보, OAuth 인증키, JWT secret key, AWS access key등을 관리해야 했습니다.
이런 정보들을 github actions를 자동배포를 할 때, 이러한 데이터들은 github actions secret에 직접 등록하는 방법을 사용하여 세팅해줄 수 있습니다.
그런데 이 방법은 변경이 생길 때마다 직접 변경을 해줘야하는 번거로움이 생기는 경우가 많습니다.
이런 문제점을 해결하기 위해 git submodule을 사용하게 되었습니다.

git submodule

Git Submodule은 git 저장소 안에 다른 git 저장소를 디렉토리로 분리해 넣어줍니다. 즉, 부모 레포지토리 하위에 공통으로 사용하는 프로젝트 레포지토리를 하위에 두는 방법입니다.
이러한 특성 때문에 프로젝트에서 공통으로 관리해야하는 변수들을 공유할 수 있습니다.

주의 사항

서브모듈을 사용할 때 주의해야할 사항이 있습니다. 부모-자식 관계라고 생각해서 부모가 자식의 것들을 모두 관리한다고 생각할 수 있는데 전혀 그렇지 않습니다.
둘은 별개의 프로젝트로 관리가 되기 때문입니다. 그래서 부모에서 자식을 직접 변경할 수 없습니다. 또한 자식의 변경사항이 생겨도 부모에서 알아차릴 수 없습니다.

그렇다면 부모 프로젝트는 어떻게 자식 프로젝트를 연결하는 걸까요? 결론부터 말하자면 커밋로그를 기반으로 연결되어 있습니다.

예를 들어 아래와 같이 커밋로그가 있다고 해보겠습니다.

부모 레포지토리의 A 브랜치는 docs: db 관련 설정 yml파일 추가를 가리키고 있고 B브랜치는 docs: jwt, aws관련 yml 파일 추가을 가리킬 수 있습니다. 이렇듯 부모-자식간의 레포지토리의 연결은 커밋 로그를 기반으로 연결이 됩니다.

서브모듈의 적용

먼저 민감한 파일들을 관리하기 위해 private 레포지토리를 생성합니다.
이번 프로젝트에서는 Organization을 사용하기 때문에 Organization안에 secret이라는 이름으로 레포지토리를 생성했습니다.

이후 git 명령어를 통해 서브 모듈을 추가합니다.
저희 팀은 resources 폴더 아래에 추가하도록 해당 경로로 이동해 명령어를 입력했습니다.

git submodule add {private repository의 url}

위의 명령어를 입력하면 아래와 같이 디렉토리가 생성됩니다.


git은 위의 secret디렉토리를 서브모듈로 취급해서 디렉토리 내부의 파일 수정사항을 추적하지는 않습니다.

또한 .gitmodules 파일이 생성되는데, 이 파일은 서브디렉토리와 하위 프로젝트 URL의 매핑 정보를 담은 설정파일입니다.

[submodule "src/main/resources/secret"]
	path = src/main/resources/secret
	url = https://github.com/masters2023-project-03-second-hand/secret.git

서브모듈 개수만큼 이 항목이 생기게 되는데, 이 파일도 .gitignore 파일처럼 버전을 관리하기 때문에 ignore처리하지 않습니다. 그래서 서브모듈이 포함된 프로젝트를 clone 하는 사람은 .gitmodules파일을 보고 어떤 서브모듈 프로젝트가 있는지 알 수 있습니다.

서브모듈을 클론

처음 위 명령어를 입력하면 secret 폴더는 비어있습니다. 그렇기 때문에 아래 명령어를 입력해야 합니다.

git submodule init
git submodule update
  • git submodule init
    • 서브모듈 정보를 기반으로 로컬 환경설정 파일이 준비됩니다.
  • git submodule update
    • 서브모듈의 리모트 저장소에서 데이터를 가져오고 서브모듈을 포함한 프로젝트의 현재 스냅샷에서 checkout 해야 할 커밋 정보를 가져와 서브모듈 프로젝트에 대한 checkout을 수행합니다.

서브모듈이 변경되어 반영해야 하는 경우

서브모듈 프로젝트를 최신으로 변경해야 하는 경우 서브모듈 디렉토리로 이동해 직접 git 명령을 수행할 수 있습니다.

git fetch
git merge

혹은 git pull명령어를 입력해 가져올 수 있습니다. 아니면 git submodule update --remote명령어를 통해 git이 알아서 서브모듈을 fetch하고 업데이트할 수 있습니다.

빌드될 때 submodule에 있는 파일 복사

이제 서브모듈에 있는 파일들을 gradle로 빌드할 때 프로젝트의 resources 폴더로 복사하려고 합니다.

이를 위해 build.gradle에 아래와 같은 task 를 추가합니다.

processResources.dependsOn('copySecret')

tasks.register('copySecret', Copy) {
    description = 'Copy submodules to project'

    from('./src/main/resources/secret') {
        include('*.yml')
    }
    into('src/main/resources')
}

이제 gradle을 빌드하면 아래와 같은 task가 수행되며 파일이 복사가 되게 됩니다.

github actions에 적용

우리 팀은 github actions를 통해 CI/CD를 수행하고 있는데 github actions의 job이 수행될 때 서브모듈에 있는 파일들을 가져오고 싶었습니다.
간단하게 아래와 같이 작성하면 job이 수행될 때 서브모듈을 참조하게 됩니다.

      - name: Checkout-source code
        uses: actions/checkout@v3
        with:
          token: ${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}
          submodules: true

PRIVATE_REPO_ACCESS_TOKEN은 private 레포지토리에 접근할 수 있는 유저의 액세스 토큰을 사용하면 됩니다.

결론

이번에 우리 팀은 private한 정보 관리를 위해 서브모듈을 도입하게 되었습니다. 환경 변수를 사용하거나 직접 secret 파일을 등록해야할 때보다 편리하게 파일을 공유할 수 있었습니다.

하지만 서브모듈과 private 레포지토리를 관리해야한다는 단점도 있습니다. 그리고 서브모듈의 변경사항을 인지하지 못하면 안되는 이유를 찾기 힘들 것이며 잘못되면 commit기록 또한 꼬일 수 있게 됩니다. 결국 관리해야할 지점들이 늘어나기 때문에 팀원과 협의해 잘 적용하는 것이 좋다고 생각합니다.

https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88

profile
다음 단계를 고민하려고 노력하는 사람입니다

0개의 댓글