Server

우당탕탕 서브모듈 도입기

wing1008 2024. 8. 7. 02:35

 

안녕하세요. 한끼족보 서버 개발자 김가연입니다.

저희 한끼족보 서버 팀은 서버를 구축하기 위해 Spring Framework를 사용하고 있는대요, Spring에서는 애플리케이션의 설정 정보를 관리하는 파일이 있습니다. 바로 resoures폴더의 application.yml 파일입니다. DB와 연동하기 위한 비밀번호, 키 값과 외부 API를 이용하기 위한 API Secret 키 등 외부에 그대로 노출되어서는 안되는 기밀 정보들이 application.yml에 포함됩니다. 이러한 중요한 기밀 정보가 만약 Public Git 저장소에 노출되어 악용된다면 어마어마한 서비스 비용이 부과되는 등 매우 위험한 상황으로 이어질 수 있습니다.

어마어마한 서버비에 오열 중인 김한끼

때문에 만약 Git을 사용하여 협업을 한다면 application.yml 파일은 반드시!! .gitignore 파일을 통해 git이 해당 파일을 추적할 수 없도록 설정해두어야 합니다. 그렇다면, 팀원들끼리는 각자의 기능 개발 중 application.yml 파일에 변경이 생겼을 때, 어떻게 서로 공유할 수 있을까요?

 

이번 포스트에서는 저희 서버 팀원들이 이러한 기밀 정보들이 담겨있는 파일들을 관리하는 방법에 대해 이야기해보려고 합니다.

 

개발 초반 🛫

개발 초반에는 파일에 변경이 생길 때마다 파일 내용을 모두 긁어 카톡에 공유하였습니다. 하지만 이러한 방식은 너무나도 번거로운 방식이었습니다. 특히 장기적으로 보았을 때, 설정 정보들이 계속해서 추가되어 각자 동시적으로 파일을 수정하게 된다면 수동으로 병합하는 과정에서 중요 정보가 누락될 위험도 존재했습니다.

 

레전드 비효율 발생

 

저희는 이러한 상황을 해결하고 또 방지하고자 서브모듈을 도입하기로 결심하였습니다.

 

서브모듈 도입 ✈️

서브모듈이란?

Git Submodule이란, 프로젝트에서 다른 프로젝트를 포함시키는 모듈을 사용하거나, 라이브러리를 이용하는 것과 같이 Git에서도 독립된 다른 저장소를 내 저장소 안에 포함하여 관리하는 기능을 말합니다.

초반의 hankki-serverserver-yml 라는 2개의 레포지터리는 서로 완전 독립된 레포지터리로 서로 그 어떠한 연관성이 없는 상태였습니다. 이제 의존성을 추가해볼까요?

git submodule add <submodule remote 주소> [dir 주소]

메인 레포지터리로 이동해서 위와 같이 서브모듈로 설정할 레포지토리의 remote 주소를 submodule에 add 하면 메인 저장소 안에 다른 Git 저장소(서브 저장소) 를 디렉토리로 분리해 넣을 수 있습니다. 이렇게 설정해줌으로써 Git을 이용하여 해당 디렉토리 내부의 파일은 직접 추적하지 않고, 서브 모듈 자체로 관리할 수 있게 되었습니다. 자, 그럼 서브모듈 도입을 완료했습니다!! (짝짝짝) 서브모듈을 도입함으로써 저희는 안전하고 보다 편하게 기밀 정보들을 하나의 모듈처럼 관리할 수 있게 되었습니다.

 

서브모듈 업데이트하기

그럼 이제 서브모듈을 어떤 식으로 관리할 수 있을까요? 

우리가 라이브러리를 사용하더라도 최신의 버전이 나오면 해당 버전을 사용할 수 있어야 합니다.
이처럼 Git의 Submodule 또한 submodule 자체를 업데이트 할 수 있고, 이를 main repository에서 가져올 수 있습니다.
단, 여기서 주의해야 할 점이 있는데 바로 실질적으로 내용에 대한 업데이트는 서브 저장소 자체에서 이루어진다는 점입니다.

예를 들어볼까요? 라이브러리의 업데이트는 main repository에서 하지 않고 새로운 버전을 참조하는 방식으로 업데이트를 하게 됩니다. submodule을 이용하는 경우 역시 이와 같습니다. submodule 을 업데이트 하기 위해서는 submodule 자체를 관리하는 서브 저장소로 이동하여 수정해주어야 합니다. 그리고 당연하게도 local에서만 수정하면 서브 저장소를 submodule로 사용하는 메인 저장소에서는 해당 변경사항을 알 수 없기 때문에 push까지 진행해서 내용을 업데이트해야 합니다. push까지 끝냈다면 다시 메인 저장소로 돌아와 봅시다. 우리가 라이브러리를 업데이트 하기 위해서는 버전을 변경해야 하듯, git submodule은 submodule로 관리하는 프로젝트의 commit id 를 참조하기 때문에 가장 최신의 commit id 를 참조하도록 버전을 변경해야 합니다.

git submodule update --remote

위의 명령어를 통해서 메인 저장소가 참조하는 commit id를 최신의 값으로 변경할 수 있습니다.  


서브 저장소를 업데이트하는 과정에서 저희는 시행착오를 거쳤는데요, 그 과정과 최종 선택한 방법에 대해 마지막으로 이야기해보려 합니다.

 

☝🏻 GitHub 웹 인터페이스에 직접 push하고 메인 로컬 저장소에서 update하는 방식

처음에 저희가 사용했던 방식입니다. 서브 저장소의 GitHub 웹 인터페이스에 직접 접근하여 수정된 파일을 push를 한 후, 다시 작업하고 있는 메인 로컬 저장소로 돌아와 update를 하는 방식이죠.

이렇게 직접 Push를 한 후, 메인 저장소로 돌아와 서브모듈을 update를 하면 checked out '7bcbbfe0cd8ac68398833e306011b398a40b14b2' 라는 문구를 볼 수 있습니다. 이건 메인 저장소가 서브모듈의 참조값을 최신 커밋으로 옮겼다는 뜻으로 성공적으로 작동함을 확인할 수 있습니다.

✌🏻 각자의 로컬 환경에서 관리하는 방식

해당 방식은 서브 저장소를 git clone하여 서브 저장소만의 로컬 환경을 만든 후, 수정사항이 생길 때마다 로컬에서 수정하고 원격 저장소로 push하는 방식입니다. 사실 앞서 설명한 방식에서 github 인터페이스에 직접 접근하여 올리는 방식만 아닐 뿐 똑같은 결과를 위한 과정입니다. 이후 메인 저장소에서 update를 하면 아까와 같이 성공적으로 작동함을 확인할 수 있습니다.

 

하지만 이러한 방식들의 문제점은!!! 사실 없고 귀찮았습니다...ㅎ

딸깍

 

 

위의 2가지 방법으로도 충분히 저희가 의도한 대로 파일을 관리할 수 있었으나 첫 번째 방법과 두 번째 방법 모두 하나의 환경에서 관리하지 못해서 이리저리 왔다 갔다 해야하는 불편함이 존재했습니다. 변경사항이 생겼을 때 첫 번째 방법은 깃허브 페이지로 이동해야 한다는 점, 두 번째 방법은 다른 로컬 환경으로 이동해야 한다는 점이었죠.

 

때문에 저는 '우리가 메인으로 작업하고 있는 IDE 환경에서 서브 모듈까지 한꺼번에 업데이트 할 수 없을까?' 라는 고민을 시작했습니다. 그렇게 시행착오 끝에 찾게된 방법이 바로 지금 설명드릴 방법입니다.

 

🎉  메인 로컬 환경에서 서브모듈 로컬 환경으로의 전환

번거롭게 이동하지 말고 server-yml 폴더에 직접 접근해봅시다. server-yml을 메인 저장소에 종속된 서브모듈이 아닌 하나의 독립적인 서브 저장소라 생각하고 접근해본 것이죠. 

처음에 접근하게 되면 아래 사진과 같이 브랜치가 특정 커밋을 가리키고 있는 것을 확인하실 수 있습니다. 메인 저장소는 서브모듈의 commit id를 참조하는 방식으로 버전을 관리한다고 했으니 이는 당연한 현상입니다. 그리고 실제로 저 commit id가 서브 저장소의 가장 최신 커밋 주소입니다. 여기서 서브모듈의 특정 커밋을 참조하는 대신 우리가 기밀 정보들을 저장하고 있는 main 브랜치로 옮겨봅시다!! (이때 Previous HEAD 어쩌구 라는 오류가 뜨며 브랜치 이동이 안된다면 main 브랜치의 정보를 pull 받아오신 후 브랜치를 변경하시면 됩니다.)

이렇게 main 브랜치로 이동한 후, 이곳에서 직접 application.yml파일을 수정하고 push하면 어떻게 될까요? 로그에서 확인할 수 있듯이 서브 저장소에 성공적으로 push가 된 것을 확인할 수 있습니다.

이후, 해당 폴더에서 나와 다시 메인 로컬 환경으로 돌아가봅시다. git status를 입력하면 server-yml이 변경되었다고 뜹니다. update도 마찬가지로 성공적으로 작동하게 됩니다. 모든 동작이 오류 없이 성공했네요:)

이후, 작업을 다 마친 후 server-yml도 함께 add하여 메인 저장소에 push를 하면, 가장 최신의 참조값으로 업데이트된 서브모듈을 확인하실 수 있습니다.

 

마무리하며 🙇🏻‍♀️ 

이것이 가능한 이유는 무엇일까요? 서브모듈은 독립적인 Git 저장소로, 메인 저장소에 포함되어 있지만 자체적으로 커밋, 브랜치 등을 관리합니다. 즉, 서브모듈은 메인 저장소에 종속되어 있지만 자체적으로 독립된 Git 저장소로 작동합니다. 따라서 서브모듈 디렉토리로 이동하여 브랜치를 전환하고 작업을 수행할 수 있었던 것입니다.


여러분도 소프트웨어 개발의 중요한 철학 중 하나인 "공통으로 사용될 수 있는 코드는 모듈로 만들자" 를 협업 도구인 Git에도 적용시켜보는 것이 어떨까요?

 

지금까지 한끼족보팀 서버 개발자 김가연이었습니다. 감사합니다.

'Server' 카테고리의 다른 글

쿼리문 고민(feat.JPA)  (2) 2024.08.28