현재 근무하고 있는 팀에서는 프론트엔드 개발 인원이 부족해 프로젝트 1개당 백엔드가 많으면 5-6명의 개발자가 배치되는 반면에 1~2명만의 프론트엔드 개발자가 배치되고 있는 상황입니다. 그래서 프론트엔드 개발자 개인의 업무 부하가 매우 컸습니다. 도메인과 프로젝트와 무관하게 공통으로 사용할 수 있는 코드를 모아 코드베이스를 만들어 사용하면 이러한 업무부하를 조금이라도 줄일 수 있지 않을까 생각했습니다. 각자 다른 레포지토리에서 신규 프로젝트를 만들어야하는 팀 특성을 고려하여 이런 코드베이스를 만들 방법에 대해서 생각해보았습니다. 2가지 방법을 생각했는데 사내 NPM 패키지 배포와 Git Submodule을 이용한 방법이었습니다.
어떤 방법으로 구현을 할지 결정하기 위해 두가지 방법의 장단점을 비교했습니다. 현재 팀은 저희 회사의 Gitlab 인스턴스를 사용하고, 프로젝트별로 클라이언트측 회사의 Gitlab 인스턴스를 사용하는 케이스가 존재하여 관련 부분 또한 고려할 대상에 포함되었습니다.
결과적으로 사내 nexus npm 패키지를 배포하기 위해서는 관련 팀의 승인을 받아야 하는 번거로움과 코드 수정이 있을 때마다 패키지 배포를 해야하며 각 프로젝트에서 버전 수정 과정을 거쳐야 한다는 단점을 생각하여 Git Submodule을 사용하기로 결정했습니다.
Git Submodule을 사용하기 위해서 Git Submodule에 대해서 알아보았습니다.
Git Submodule은 한 Git 저장소 안에 다른 Git 저장소를 하위 디렉토리 형태로 포함시키는 기능입니다. 메인 저장소와 서브모듈은 각각 독립적인 Git 저장소이며, 서브모듈의 특정 커밋을 메인 저장소에 고정하여 서브모듈에 대한 버전을 관리할 수 있습니다.
메인 저장소에서는 서브모듈의 위치와 정보를 다음과 같은 형식으로 .gitmodules 파일에 저장합니다.
[submodule "<서브모듈 경로>"]
path = <서브모듈 경로>
url = <Git 저장소 경로>
메인 저장소는 서브모듈의 커밋 해시값을 추적하기 때문에 서브모듈의 내용이 변경되더라도 메인 저장소는 특정 버전만을 참조할 수 있습니다.
메인 레포지토리를 A, 서브모듈 레포지토리를 B라고 하겠습니다. Git 저장소에서 서브모듈 레포지토리를 만들고 A에서 다음과 같은 명령어를 통해 submodule을 추가할 수 있습니다.
git submodule add <서브모듈 Git 저장소 경로>
서브모듈을 포함한 프로젝트를 클론할 때는 추가 명령어가 필요합니다. 다음과 같이 2가지 방법으로 프로젝트를 클론할 수 있습니다.
git clone --recursive <메인 Git 저장소 경로>git submodule init && git submodule update다음과 같이 서브모듈의 변경사항을 메인 Git에 업데이트할 수 있습니다.
# 1. 서브모듈 디렉토리 내부에서 pull 받기
cd <서브모듈 경로>
git pull origin main
# 2. 메인 프로젝트 디렉토리에서 업데이트
git submodule update --remote
# 최신 커밋이 아닌 특정 커밋으로 고정할 경우 사용
cd <서브모듈 경로>
git checkout <원하는 커밋 해시 또는 태그>
cd ..
git add <서브모듈 경로>
git commit -m "서브모듈 버전 업데이트"
서브모듈의 코드를 직접 수정하고 반영해야할 경우 다음과 같이 반영을 해야합니다. 즉, 서브모듈과 메인 프로젝트의 Git에 모두 반영을 해주어야 하는 것이죠.
# 1. 서브모듈 디렉토리로 이동
cd [서브모듈 경로]
# 2. 변경사항 커밋
git add .
git commit -m "서브모듈 수정"
# 3. 원격 저장소에 푸시
git push origin main
# 4. 메인 프로젝트로 돌아가서 서브모듈 변경사항 커밋
cd ..
git add [서브모듈 경로]
git commit -m "서브모듈 업데이트"
앞서 설명한 것처럼 현재 저희 팀은 저희 회사의 Gitlab 인스턴스를 사용하고, 프로젝트별로 클라이언트측 회사의 Gitlab 인스턴스를 사용하는 케이스가 존재했습니다. 이러한 경우 Gitlab Runner에서 프로젝트를 클론할 때, 다른 Gitlab Instance에서 서브모듈을 clone하기 때문에 문제가 발생했습니다.
이를 해결하기 위해서 URL을 통해서 클론을 할때 서브모듈이 저장된 Gitlab 인스턴스에서 clone을 할 경우 토큰을 설정하여 clone을 할 수 있도록 만들어 주어야 합니다.
Gitlab 공식문서에서 Personal access token을 사용하여 clone하는 방법에 대해서 나와있어 해당 방법을 사용하도록 gitlab ci 파일을 설정해주었습니다.
# .gitlab-ci.yml
default:
hooks:
pre_get_sources_script:
- git config --local url.https://<submodule gitlab access token>@<submodule gitlab instance url>.insteadOf <submodule gitlab instance url>
이렇게 설정해주니 정상적으로 다른 깃랩 인스턴스에서 정상적으로 clone을 받아와 빌드를 수행하는 것을 확인할 수 있었습니다.
이러한 결과를 가지고 서브모듈 기반의 공통 코드베이스를 사용하면 어떨지 다른 프론트엔드 개발자와 이야기해보면서 실제로 프로젝트들을 보면서 공통으로 뺄 수 있는 코드가 있을지 살펴보았습니다. 하지만 유틸함수 등은 es toolkit과 같은 라이브러리를 사용하고 컴포넌트의 경우는 디자인이 모두 달라 공용으로 사용할 수 없는 경우가 많았습니다. 즉, submodule을 도입해도 생각보다 공용으로 사용할 수 있는 코드가 적어 도입은 하지 않기로 결정했습니다.
아쉽게 사용하지는 않게 되었지만 이번 기회로 Git submodule이라는 기능을 알고는 있었지만 제대로 사용해볼 기회는 없었는데, 이번 기회로 해당 기능에 대해서 조금 더 자세하게 알아볼 수 있었습니다.