Submodule을 이용하여 Config 파일 관리하기

변현섭·2023년 12월 25일
2

Github 사용법

목록 보기
17/17

1. 개요

프로젝트에는 데이터베이스 관련 설정, AWS 관련 설정, API Key와 같은 민감 데이터가 포함될 수 있다. 당연히 이와 같은 정보는 하드 코딩해선 안 되고, 별도의 설정 파일로 관리해야 한다. 그래서 SpringBoot에서는 application.properties 파일이나, application.yml 파일을 이용해 설정을 관리하는 것이 일반적이다.

설정 파일을 별도로 관리함으로써 얻을 수 있는 또 하나의 이점은, 각 환경에 따라 다른 설정을 적용할 수 있다는 것이다. 즉, 로컬 환경(local-env), 개발 환경(dev-env), 운영 환경(prod-env), 테스트 환경(test-env)별로 다른 설정을 사용할 수 있게 된다.

문제는 설정 파일을 팀원들과 어떻게 공유할 것인가이다. 설정 파일은 다른 사람에겐 공개되지 않으면서, 팀원들 간에는 원활히 공유되어야 한다. 지금까지는 설정 파일을 단순히 gitignore 하는 방법에 대해서만 소개했었는데, 이러한 방식은 팀 프로젝트에서 적합하지 않을 수 있다. 그래서 이번 포스팅에서는 설정 파일을 Github Organization에 업로드하면서, 다른 사람에게는 공개되지 않도록(private) 설정하는 방법에 대해 알아보도록 하겠다.

2. 설정 파일을 Github Organization에 업로드 하기

설정 파일을 비공개로 설정하는 방법은 아래와 같다.

  • 별도의 Private Repository를 두어 설정 파일을 관리한다.
  • Main Repository에서 Private Repository를 Submodule로 참조한다.

즉, 설정 파일을 별도의 Private Repository에 업로드하되, 프로젝트의 메인 레포지토리(Public Repository)와 연동하기 위해 Submodule을 이용한다는 것이다. 자세한 방법은 직접 실습해보면서 알아보기로 하자.

※ Submodule
Git 저장소 안에 다른 Git 저장소를 디렉토리로 분리해 넣는 것을 서브 모듈이라 한다. 서브 모듈을 이용하면 독립된 Git 저장소를 Clone 하여 다른 Git 저장소 안에 포함할 수 있으며, 각 저장소의 커밋은 독립적으로 관리된다.

1) 사전 설정 진행하기

깃허브와 연동된 스프링부트 프로젝트 및 깃허브 Organization이 이미 존재한다면, 이 단계는 생략해도 된다.

① 아래의 포스팅을 참조하여 실습에 사용할스프링부트 프로젝트를 생성 및 실행한다.
>> 스프링 개발환경 구축하기

② 아래의 포스팅을 참조하여 스프링부트 프로젝트를 깃허브와 연동한다.
>> IntelliJ와 Github 연동하기

③ 아래의 포스팅을 참조하여 Github Organization을 생성한다.
>> Github Organization 생성하기

④ application.properties 파일을 삭제한다.

  • 설정 파일은 추후에 다시 작성할 것이다.
  • 삭제하고 싶지 않다면, gitignore를 적용해도 된다.

⑤ Github Organization에 프로젝트를 업로드한다.

  • 프로젝트의 메인 레포지토리로 사용할 것이므로, public으로 업로드한다.
  • Github Organization에 코드를 업로드하는 방법을 알고 있다면, 바로 업로드하면 된다.
  • 업로드 방법을 잘 모르겠다면, 아래의 포스팅을 참조하여 먼저 프로젝트를 개인 Repository에 업로드 한 후, 해당 Repository를 Organization으로 옮긴다.
    >> Github에 프로젝트 업로드하기
    >> Github Organization으로 코드 옮기기

2) Private Repository를 Submodule로 연결하기

① 방금 생성한 Main Repository를 Fork한다.

② 아래의 포스팅을 참조하여 Fork 된 개인 레포지토리를 Clone 하여 IntelliJ로 불러온다.
>> Git Clone 하여 IntelliJ로 불러오기

  • File > Project Structure > Projects에 SDK를 17로, Language level도 17로 설정한다.
  • File > Settings > Build.Excecution.Deployment > Build Tools > Gradle에 Build and run using과 Run tests using을 IntelliJ IDEA로 변경하고 Gradle JVM도 17로 변경한다.

③ 설정 파일을 관리할 Private Repository를 생성한다.

  • 본인의 Organization에 새로운 Private Repository를 생성한다.
  • 초기 커밋이 존재해야 작업하기 편하기 때문에, Add a README file에 체크한다.
  • Private Repository의 이름이 곧 서브 모듈 디렉토리의 이름이 되므로, 반드시 config라는 이름으로 생성해야 한다. (config로 설정해야 Spring에서 설정 파일로 인식할 수 있다.)

④ Private Repository의 HTTPS 주소를 복사한다.

⑤ IntelliJ 터미널에 아래의 명령을 입력하여 Submodule을 추가한다.

  • 이 때, 프로젝트가 이미 메인 레포지토리와 연동되어 있어야 한다.
git submodule add {방금 복사한 repository의 주소}

⑥ 추가된 Submodule을 확인한다.

  • config 디렉토리가 잘 생성된 것을 확인할 수 있다.

⑦ gitmodules 파일도 생성되는 것을 확인할 수 있다.

  • 방금 생성된 서브모듈 디렉토리의 이름과 Private Repository의 주소가 담긴 설정파일이다.

⑧ Fork된 개인 레포지토리로 Commit 및 Push 한다.

3) Organization에 Submodule 반영하기

① 아래의 포스팅을 참조하여 Organization Repository로 PR을 보낸다.
>> Organization Repository에 Pull Request 보내기

② Merge가 완료되면, Organization의 Main Repository에서 Submodule로 연결된 Private Repository를 확인할 수 있게 된다.

③ Microsoft Edge를 이용해 Organization Repository의 HTTPS 주소로 접근해보자.

④ 공개되어 있는 일반 디렉토리에는 접근할 수 있지만, config 디렉토리에는 접근하지 못하는 것을 확인할 수 있다.

3. Submodule을 이용하여 민감 데이터 관리하기

1) Main Repository와 Private Repository 동기화하기

메인 레포지토리에서 서브 모듈을 확인할 수는 있지만, 서브 모듈 내의 파일을 변경하는 것은 불가능하다. 이는 서브 모듈의 디렉토리가 메인 레포지토리의 관리 대상이 아니기 때문이다. 즉, 민감 데이터를 포함하는 파일은 Private Repository에 의해서만 관리될 수 있다.

이 때, Main Repository와 Private Repository가 서로 동기화되지 않는 문제가 발생한다. 그 이유는 Main Repository에서 Private Repository의 Commit Hash 값을 참조하는 구조이기 때문이다. 즉, Private Repository가 업데이트 되어 새로운 Commit Hash 값을 갖게 되더라도, Main Repository에서는 여전히 예전 Commit Hash 값을 참조하게 된다는 것이다. 따라서, Main Repository가 참조하는 Commit Hash 값을 최신화하는 동기화 작업이 필요하다. 동기화는 아래와 같은 방법으로 진행된다.

① Submodule 디렉토리 하위로, yml 파일을 추가한다.

  • 여기서는 application.yml(공통 설정), application-dev.yml, application-local.yml, application-prod.yml, application-test.yml을 추가하였다.
  • 각 yml 파일에 필요한 내용을 입력한다.

② Commit 후 본인의 Private Repository로 Push 한다.

  • 서브 모듈의 Commit과 Push는 CLI 방식을 사용하는 것이 더 편하다.
  • GUI 방식을 사용하고 싶다면, git add . 명령까지만 입력하고 기존 GUI 방식으로 Commit 및 Push 하면 된다.
cd config
git status
git add .
git commit -m 'add config file'
git push

③ config 레포지토리(Private Repository)에 설정 파일이 잘 업로드 되었는지 확인한다.

④ 이제 메인 레포지토리에서 참조하는 서브 모듈 디렉토리를 클릭해보자.

  • 서브 모듈의 변경 사항이 메인 레포지토리에 반영되지 않았다.
  • 변경 사항을 반영하기 위해서는 수동으로 업데이트를 진행해야 한다.

⑤ 서브 모듈이 최신화 되어 있는지 확인하는 방법은 Commit Hash 값이 동일한지 확인하는 것이다.

  • 서브 모듈 디렉토리의 @ 뒤에 오는 값이 Main Repository에 적용된 Commit Hash 값이다. 즉, f1285b7이 Main Repository에 적용된 Commit Hash 값이다.
  • Private Repository에 적용된 Commit Hash 값은 커밋 내역에서 확인할 수 있다. 즉, 7239a96이 Private Repository에 적용된 Commit Hash 값이다.
  • 두 Commit Hash 값이 다르므로, 현재는 최신화가 되어있지 않은 상태이다.

⑥ 서브 모듈을 최신화하기 위해 IntelliJ 터미널에 아래의 명령을 입력한다.

  • 이번에도 git add . 명령까지 입력한 후, CLI 또는 GUI 방식으로 Commit 및 Push 하면 된다.
cd .. // 서브 모듈에서 빠져나온다. 
git submodule update --remote
git status
git add .
git commit -m 'add config file'
git push

⑦ 개인 레포지토리에서 PR을 생성한 후 Organization에서 Merge 한다.

⑧ Main Repository에 적용된 Commit Hash 값이, Private Repository에 적용된 Commit Hash 값(7239a96)과 동일한지 확인한다.

⑨ 설정 파일을 수정할 때마다 반드시, Private Repository에 먼저 Push 한 후 Main Repository에서 최신화해야 한다.

  • 순서가 바뀌면 안 된다.

⑩ 팀원이 업데이트 한 설정 파일을 로컬로 받아오고 싶다면, 아래의 명령을 입력하면 된다.

cd config
git pull --recurse-submodules {private repository의 HTTPS 주소}

2) Main Repository에서 Submodule 디렉토리 내의 설정 파일 사용하기

설정 파일은 원칙적으로 src/main/resources에 위치해야 하지만, 현재는 임의로 생성한 Submodule 디렉토리 내부에 위치하고 있다. 따라서, Submodule 디렉토리에 있는 설정 파일을 src/main/resources로 가져오기 위한 설정을 진행해야 한다. 그 방법은 아래와 같다.

① Main Repository에 있는 설정 파일은 모두 삭제한다.

② build.gradle 파일에 아래의 코드를 추가한다.

processResources.dependsOn('copySecret')

tasks.register('copySecret', Copy) {
	from './config' // 서브 모듈 디렉토리 경로
	include "*.yml"  // 설정 파일 복사
	into 'src/main/resources'  // 붙여넣을 위치
}

③ Company 테이블을 생성하는 코드가 잘 실행되는지 확인해보자.

  • yml 파일이 Submodule 디렉토리 내부에 위치하고 있음에도, 데이터베이스와 잘 연동되는 것을 확인할 수 있다.

profile
Java Spring, Android Kotlin, Node.js 개발을 공부하는 인하대학교 정보통신공학과 학생입니다.

0개의 댓글