22sook00 logo
SookDev
🌳

서브모듈 구축하기

목차

 
🚨 문제인식 큐샵에서 사용하는 에디터와 라이브 페이지에서 공통적으로 사용하는 컴포넌트들이 분명 있음에도 불구하고 각 레포지토리에서 “복붙” 하여 사용하고 있었다. 빠르게 고도화를 하여 매출을 내야 하는 상황에서 각 레포지토리에 코드를 복붙하는 개발자스럽지 못한 행동은 시간 낭비라고 생각한다. 뿐만 아니라 미처 확인하지 못한 부분에서 싱크가 맞지 않아 에러가 발생한 적도 종종 있었다. 앞으로 에디터의 기능 고도화가 이루어지는 만큼 사이드이펙트는 더 심해질 것이다.
 

1. 왜 서브모듈일까?

🌱 npm ? monorepo ? submodule?

💬
선택 과정에 있어 주관적으로 작성하였습니다. 언제든 의견 주시고 틀린내용이 있다면 알려주세요 🙌🏻

npm

이전에 아예 생각을 안해봤던것은 아니다.
개인프로젝트로 사용하고 있던 디자인시스템을 npm 으로 배포하여 사용중이었는데, 우리 팀도 npm 으로 관리하는 방향에 대해 제안을 한 적 있다. 하지만 리드님께서 npm 은 public 으로 배포해야하기 때문에 리스크가 있다고 하셨다. 너무나 당연한 얘기인데 미처 생각하지 못했다. 또한 npm 으로 배포 시 여러 작업자가 있을 시 유료 멤버십 결제를 해야한다고 한다.
 

monorepo

모든 관련 프로젝트를 하나의 저장소에서 관리하는 방식. ex - UI, PC, Mobile, Utils 등등 하나의 레포에서 관리
notion image
모노레포를 사용해본 경험은 없지만 이론적으로 봤을 때, 하나의 부모 레포지토리 안에 공통적으로 사용 될 여러 프로젝트들이 있는 개념이다.
모놀리스 형태의 큐샵의 에디터와 라이브 레포를 하나로 합치는것은 당연히 불가능하고, 다른 개념으로 접근해야 한다. 만약 우리가 UI, PC, Mobile 등 여러 프로젝트를 나누어 멀티레포식으로 이미 개발환경을 구축 했다면 모노레포를 선택했을지도 모른다.
아직 모듈화를 진행한 적이 없기 때문에 모노레포 내부에서 사용할 프로젝트 자체가 존재하지 않는 상황에서 바로 모노레포를 시도하는 것은 약간 오버스펙이라고 생각했다.
또한 큐샵 개발팀은 ci/cd 전략 및 버저닝 전략이 완벽하게 책정된것이 아니다.
모듈에 따라 CI를 돌릴지 말지 또 회의를 거쳐야 할테고 정해야 할 규칙이 많아질 수 있기 때문에 오히려 모노레포의 장점인 통합 버전관리 면에 있어서 더 혼란을 줄 수 있다고 생각했다.
 
장점:
  • 통합된 버전 관리: 모든 프로젝트가 같은 버전 관리 시스템 안에서 관리되므로, 변경사항 추적 용이.
  • 코드 공유와 재사용: 코드 베이스가 한 곳에 있기 때문에 코드의 공유와 재사용이 용이.
  • 변경사항 : 한 번의 커밋으로 여러 프로젝트에 걸쳐 변경 사항 적용 가능.
  • 통합된 빌드와 테스트: 전체 코드 베이스에 대한 빌드와 테스트를 쉽게 관리.
단점:
  • 규모의 복잡성: 프로젝트의 크기가 커질수록 관리의 복잡성 증가.
  • 빌드 시간: 전체 저장소에 대한 빌드 시간이 길어질 수 있다.
  • 액세스 제어: 소규모 팀이나 개인이 전체 코드 베이스에 액세스해야 하는 문제가 발생할 수 있다.
 

submodule

git 저장소 안에 다른 git 저장소를 디렉토리로 분리하여 독립적으로 관리하는 멀티레포 방식. ex - UI, PC, Mobile 을 여러개의 저장소로 관리하고 부모레포에서 클론
notion image
모노레포가 유행인 요즘 갑자기 멀티레포?
앞서 말했지만 모놀리스 형태로 레포를 관리하는 큐샵에서 공통으로 사용되는 코드들을 모듈로 분리하는것이 선행 되어야 한다고 생각했다.
서브모듈은 각각의 독립된 Git 저장소를 부모 레포지토리에 Clone 해서 포함할 수 있으며, 각 저장소의 커밋은 독립적으로 관리한다.
당연하게도 private 한 레포지토리도 가능하여 보안성을 유지할 수 있다.
클론을 하면 에디터나 라이브가 더 무거워지는게 아닌가? 라는 생각을 할 수 있겠지만 각 서브모듈의 최신 해시값만 git 에 올라가기 때문에 걱정하지 않아도 된다.
notion image
 
장점:
  • 독립성: 서브모듈은 각각 독립적인 저장소로, 자체적인 버전 관리가 가능.
  • 재사용성: 공통 코드 라이브러리를 서브모듈로 관리함으로써 다른 프로젝트에서 재사용.
  • 액세스 제어: 각 서브모듈에 대한 액세스를 별도로 제어 가능.
단점:
  • 복잡성: 서브모듈을 추가하고 업데이트하는 과정이 복잡할 수 있다.
  • 커밋 관리: 서브모듈의 변경 사항을 추적하려면 부모 저장소에서 서브모듈의 커밋을 참조해야 한다.
  • 의존성 관리: 서브모듈 간의 의존성을 관리하는 것이 더 어려울 수 있다.
 
🍃
결론 아직은 레포를 관리할만한 인력이나 시간이 부족하기 때문에 관리의 복잡성이 있는 모노레포보다 프로젝트 간 독립적인 성향이 강한 서브모듈이 더 적합하다고 판단했다.
 

2. 서브모듈 구축

테스트를 위해 각 세개의 레포를 구축하였다.
Editor : 에디터 레포지토리 Live : 라이브 레포지토리 Next-Submodule : 에디터와 라이브의 공통 스타일 컴포넌트가 담길 서브모듈 레포지토리

🌿 서브모듈 환경설정

서브모듈 레포지토리 생성

  • 공통으로 사용할 코드 작업 후 push
서브모듈의 역할은 에디터와 라이브에서 공통으로 쓰일 컴포넌트만 작업하기 때문에 간단하다.
똑같이 레포지토리를 생성하고 내가 공통으로 사용할 컴포넌트 작업을 한다.
나같은 경우 테스트로 버튼 드롭다운 을 생성하여 commit , push 했다.
( 추후 설정 문제로 골머리를 썩고싶지 않으면 버전을 동일하게 가져가는것이 좋을 듯 하다. )
서브모듈을 push 까지 하고 난 후 아래의 명령어로 해시값을 확인하면 현재 febff4e 인것을 볼 수 있다.
notion image
  • git remote -v로 현재 서브모듈의 저장소 위치 알아내기.
에디터와 라이브에서 적용하기 위해서 서브모듈의 저장소 주소를 알아두어야 한다.
notion image
 

에디터와 라이브에 서브모듈 추가하기

  • 에디터와 라이브에 다음 명령어로 추가한다.
  • 만약 특정 디렉토리를 생성하여 추가하고 싶다면 저장소 뒤에 생성할 디렉토리 이름만 추가하면 된다.
에디터/라이브 레포에 추가하면 내가 설정한 경로에 next-submodule 레포와 .gitmodules 가 생성될것이다.
  • .gitmodules 파일
  • cd next-submodule 로 들어가서 git log 를 찍으면 서브모듈 레포에서 찍은 해시값과 동일한것을 확인 할 수 있다.
    • notion image
 

서브모듈이 적용된 에디터, 라이브 push 하기

  • 가져온 서브모듈의 컴포넌트가 잘 동작한다면 push 를 진행.
위에서 설명한대로, 서브모듈의 코드 자체가 올라가는것이 아니라 최신 해쉬값을 가진 서브모듈이 연결되어 올라가게 되는것을 볼 수 있다.
notion image
 
notion image
 

🌿 서브모듈이 적용된 프로젝트 이용법

서브모듈 초기 클론

누군가 세팅해놓은 서브모듈이 적용된 에디터/라이브가 올라가면 다른 개발자들은 각 레포를 클론을 받거나 업데이트한다.
초기에 서브모듈이 적용된 프로젝트를 클론하거나, 서브모듈이 적용된 브랜치를 이용한다면 처음에는 빈 디렉토리 밖에 보이지 않는다.
  • submodule init 을 통해 .gitmodules 에 기입된 정보를 기반으로 로컬에 환경설정을 한다.
  • update를 통해 리모트 저장소에서 데이터를 가져온다

수정 된 서브모듈 적용하기

서브모듈에서 수정 된 코드가 있다면 에디터, 라이브 레포지토리에서도 수정된 코드가 반영되어야 한다.
서브모듈은 최신 해시값을 통해 반영되는 독립적 프로젝트이기 때문에 에디터/라이브 루트 경로에서 아무리 git pull 해도 소용이 없다.
  • 첫번째 방법 : cd next-submodule 명령어로 들어와 git pull origin next-submodule 을 하여 적용한다
  • ✨ 두번째 방법: submodule update --remote
    • 원격 저장소의 최신을 로컬 저장소에 바로 업데이트
    • 만약 업데이트만 한다면 가장 마지막 커밋으로 업데이트가 된다.
두번째 방법을 사용하여 next-submodule 로 경로이동 없이 루트에서 바로 서브모듈을 업데이트 하니 변경되는것을 볼 수 있다.
notion image
 
notion image
 

🪴 서브모듈 적용 시 주의할점

경로 및 환경설정

에디터/라이브 에서 next-submodule 에 있는 컴포넌트를 절대경로로 가져오기 위해 jsconfig.json 에 path 를 추가한다.
에디터에서 서브모듈의 버튼을 import 하니 다음과 같은 에러가 발생한다.
notion image
그 이유로, 서브모듈의 스타일 절대경로도 @/styles 로 시작하고 부모레포의 절대경로도 @/styles
설정되어 있기 때문에 경로가 충돌되어 에러가 발생하는 것이었다.
처음부터 @sub/* 으로 해두었으면 좋았겠지만 어쩔 수 없이 둘 중 한 레포의 경로를 바꿔야 했다.
코드양이 더 많은 에디터/라이브 의 styles 는 그대로 두고 서브모듈에서 가져오는 컴포넌트는
@sub/* , @sub/styles/* 로 path 를 구분하는 방향으로 해결했다.
실제로 서브모듈을 도입한다면 구분을 확실히 할 수 있도록 경로설정 에도 신경을 써야 할 것 같다.
경로 외에도, 서브모듈에 라이브러리가 많거나 웹팩 & 바벨 설정한 프로젝트라면 그만큼 환경설정 할것들이 많아 질 수 있다.
왠만하면 라이브러리 버전의 통일하고, 번들러를 구성하다면 웹팩에 추가 로더가 필요할 수도 있다.
문득 번들러를 직접 구성하지 않은 프로젝트임에 감사하게 되었다.
 

필수적인 커뮤니케이션, 그리고 깃관리

그렇다면 서브모듈이 적용된 후 작업을하며 깃관리는 어떻게 진행되어야 할까 ?
서브모듈 파일 수정 후 부모레포에서 git status 를 치면 다음과 같이 next-submodule 이 수정된것으로 나온다.
notion image
서브모듈의 해시값이 변경되면 기존에 서브모듈을 이용하던 레포에서 git diff 명령어를 통해
서브모듈의 해시값과 diff가 발생됨을 확인할 수 있다.
이 과정에서 서브모듈을 이용하는 레포는 서브모듈의 코드를 저장하는 것이 아닌, 해당 서브모듈의 해시값을 저장함을 한번 더 알 수 있다.
notion image
만약 만약 고의든 실수든 에디터/라이브 레포에서 서브모듈을 변경했을 경우, cd next-submodule 경로로
들어가 똑같이 git commit/push 를 진행하면 된다.
이럴경우 동일한 서브모듈이 적용되어있는 라이브페이지도 동시에 변경이 되기 때문에 주의가 필요하다.
⚠️
서브모듈 작업은 공동으로 사용되는 만큼 변경된 부분에 대해 반드시 공유가 되어야 한다.
팀의 규칙에 따라 다르겠지만 변경된 해시값을 레포에서 커밋으로 남김으로써 이력관리를 해야할 것 같다.
 

3. 큐샵에 submodule 적용한다면

🌱 해결해야할 문제

우리 프로젝트에는 서브모듈을 어느 범위까지 적용시킬 수 있을까?

서브모듈을 활성화 시키기 위해서 현재 코드들을 모듈로 세분화 하여 분리해야 하는데
그러기엔 대공사 (대공사 === 자칫 대참사) 가 되기 때문에 프론트팀의 아이디어와 도움이 필요하다.
현재 내가 생각할 수 있는 범위는 다음과 같다
  • 중복되는 코드만 조금씩 모듈화 시도
  • 문제가 없을 시 API 없이 공통으로 사용되는 컴포넌트 로 확장하여 모듈화
  • API 통신까지 가능한 컴포넌트로 확장하여 모듈화
  • 디자인 시스템 도입될 경우, AD & HP 까지 별도로 스타일을 관리하는 모듈로서 관리.

배포테스트

⚠️
배포 테스트가 반드시 필요하다
이번 서브모듈 테스트를 위해 vercel 로 배포를 진행하였다.
제일 간단하게 배포될것 같아 vercel 로 선택하였는데 절망적이게도 vercel 에서 서브모듈을 지원해주지 않아 직접 환경을 구축해야 했다. (npm run build 시 문제 없으나 vercel 에서 배포가 전혀 진행되지 않았다.)
배포 해결과정은 다음 글에서 볼 수 있다.
🔗 submodule → vercel 배포 이슈 해결하기
큐샵은 AWS 를 사용하기 때문에 또 다른 배포 이슈가 있을 가능성이 있다.
서브모듈 구축 후 별도의 배포서버를 구축 후 충분한 테스트를 거친 후 prod 에 배포해야 할 것 같다.
 
🔗 배포된 서브모듈 적용 에디터 사이트 :
🔗  배포된 서브모듈 적용 라이브 사이트 :
 

참조
🔗  저장소 안에 저장소 - git submodule
🔗  모노레포 대신 서브모듈 선택 이유