일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 자바 ORM 표준 JPA 프로그래밍
- 객체지향 쿼리 언어
- 30기
- JPA
- JPQL
- 모임 장소 추천
- Spring Batch
- GitHub Actions
- 쿠버네티스
- Container Registry
- 도메인 주도 개발 시작하기
- Spring
- 큐시즘
- cicd
- RESTClient
- redis
- 중간 지점 추천
- Domain Driven Design
- java
- 한국대학생it경영학회
- springboot
- K3S
- 중간 장소 추천
- 백엔드
- 이펙티브자바
- 약속 장소 추천
- 최범균
- 영속성
- ddd
- kusitms
- Today
- Total
코딩은 마라톤
모이삼에서 사용하는 Git-flow 방식을 소개합니다 본문
SPOT(스팟)의 서비스명이 모이삼으로 변경되었습니다!
모이삼도 많은 관심 부탁드려요~!
시작하기 앞서
https://developer-anxi.tistory.com/79
https://developer-anxi.tistory.com/80
앞선 두 개의 글에서 운영·스테이징 환경으로 분리하는 과정을 알아보았습니다.
Git-flow는 분리 이전에도 사용했습니다.
하지만 운영, 스테이징으로 분리됨으로써 메인 브랜치(prod, develop)와 보조 브랜치(release)가 추가되었고,
develop에서 prod로 작업 커밋을 옮기는 과정 또한 정했어야 하기 때문에 이번에 Git-flow 기반으로 모이삼의 방식을 만들었습니다!
모이삼의 Git-flow 전략
Git-flow는 메인 브랜치인 master, develop과 보조 브랜치인 hotfix, release, feature가 있습니다.
모이삼은 Git-flow를 약간 바꿔서 사용합니다.
- prod : 운영 환경으로 배포할 브랜치 (운영 환경)
- develop : 운영 환경 배포 이전의 개발한 기능이 존재하는 브랜치 (스테이징 환경)
- feature : 기능을 개발할 브랜치
- release : 운영 환경으로 출시하기 위한 임시 브랜치
- hotfix : prod 브랜치에서 발생한 버그를 수정할 브랜치
위와 같이 사용하고 있으며, prod 브랜치가 추가된지 얼마 안 됐고 릴리즈를 한 번밖에 안 해봤기 때문에 hotfix 브랜치는 아직 사용해보지 못했네요 😌
모이삼의 Git-flow 사용 방식
1) feature -> develop
1. 새로운 기능을 개발하기 위해 develop 브랜치에서 feature 브랜치를 생성합니다.
(develop)]$ git checkout -b feat/spot-100
2. feature 브랜치에서 새로운 기능을 구현합니다.
3. 기능을 다 만들었다면 작업 브랜치에서 변경사항을 스테이징 환경에 올리고(add), 커밋(commit)합니다.
(feat/spot-100)]$ git add .
(feat/spot-100)]$ git commit -m "FEAT: (SPOT-100) 세상을 뒤바꿀 모이삼 이벤트 생성"
4. 작업 브랜치를 origin 서버에 push합니다.
(feat/spot-100)]$ git push feat/add-event
5. Github에서 develop 브랜치를 base로 해서 feat/add-event 브랜치를 기반으로 Pull Request 생성합니다.
6. 동료에게 리뷰 승인을 받은 후 자신의 Pull Request를 merge 합니다. 모이삼은 동료의 리뷰 승인 (approve)을 받은 후에 merge 할 수 있습니다.
이렇게 하면 기능 개발이 완료되어 develop 브랜치에 합쳐지게 됩니다.
1-1) develop의 변경 사항을 작업 브랜치에 최신화
그런데 팀원이 개발하는 코드가 먼저 develop에 병합되면, 본인이 작업 중인 브랜치는 브랜치를 만든 시점의 develop과 달라지기 때문에 develop에 병합할 수 없게 됩니다.
현재 origin/develop 브랜치를 기반으로 현재 작업 브랜치를 갱신해줘야 하는데 저희는 이를 "최신화"라고 부릅니다.
보통 이런 경우는 개발 기간이 긴 작업과 짧은 작업이 겹칠 경우에 짧은 작업이 먼저 합쳐져서 긴 작업은 최신화를 해야 합니다.
(모이삼은 최근에 기능이 추가/변경되면서 개발할 부분이 많아 최신화를 항상 했네요 😅)
저희는 rebase를 통해 최신화를 하고 있습니다.
rebase를 사용한 이유는 merge를 하게 되면 merge 커밋이 추가로 생깁니다. 하지만 모이삼이 추구하는 건 불필요한 내용 없이 필요한 정보만 커밋에 반영되기를 원하기 때문에 rebase 방식을 사용하게 되었습니다.
최신화 과정은 간단합니다.
1. develop 브랜치로 이동해서 local develop에 origin develop을 반영합니다.
(feat/spot-100)]$ git switch develop
(develop)]$ git pull
2. 작업 브랜치로 돌아가 rebase를 수행합니다.
(develop)]$ git switch feat/spot-100
(feat/spot-100)]$ git rebase develop
3. 🚨(Optional) conflict가 발생할 수 있어요. IDE에서 conflict를 잘 해결할 수 있게 도와주니 주의해서 conflict를 해결해야 합니다!
4. 최신화한 작업 브랜치를 origin 서버에 push 합니다.
(feat/spot-100)]$ git push -f
이때 rebase를 하고 나서 그냥 push를 하게 되면 에러가 발생합니다. rebase를 하면 origin의 커밋과 local의 커밋 내용은 같지만, rebase 과정에서 커밋 해시 번호가 수정되기 때문에 히스토리가 달라지기 때문입니다.
이를 해결하기 위해선 force push를 해야 하지만 작업 브랜치는 혼자 작업하기 때문에 모이삼은 force push를 허용합니다.
1번 과정을 통해서 신규 기능이 개발되어 develop 브랜치에 합쳐지는 과정을 보았습니다. 모이삼에서는 develop 브랜치에 합쳐지면 스테이징 환경에 자동으로 배포됩니다.
2) develop -> prod
스테이징 환경에 배포 후 QA를 거쳐 운영서버에 배포할 기능은 prod 브랜치로 옮겨줘야 합니다.
1번 과정에서는 feature 브랜치를 사용했다면, 2번 과정에서는 release 브랜치를 사용하여 prod 브랜치로 옮깁니다.
1. develop 브랜치로 이동 및 develop 브랜치를 origin과 맞추기 위해 pull 합니다.
(develop)]$ git switch develop
(develop)]$ git pull
2. 배포를 위한 release 브랜치를 생성합니다.
(develop)]$ git checkout -b release/v0.1.1
3. release 브랜치에서 prod 브랜치에 옮길 커밋을 rebase를 하여 선별합니다.
'SPOT-143'의 커밋을 보면 태그가 붙어 있습니다. 만약 prod 브랜치를 처음 만들었다면, 태그가 아닌 prod 태그가 붙어 있을 거예요!
release(develop) 하위에 prod 브랜치의 커밋이 존재합니다. 그래서 prod 브랜치에 옮길 커밋은 태그 위의 커밋 중에서 선별합니다. 선별을 해서 올리지 않을 커밋을 제거하기 위해 rebase를 사용합니다.
(release/v0.1.1)]$ git rebase -i {태그 커밋 해시번호}
태그 커밋 이후부터 rebase를 진행하여 prod에 옮길 커밋만 남깁니다.
vi 화면에서 만약 a0c2870 커밋만 남기고 싶다면 아래 2가지 방법을 사용합니다.
- 나머지 커밋은 dd(vi 명령어_delete line)를 사용해 커밋을 제거하기
- pick을 drop(d)로 변경하기
이렇게 해서 살릴 커밋만 남겼다면 :wq를 통해 vi 화면에서 나오면 됩니다.
이때 rebase를 하면 conflict가 발생할 수 있습니다. conflict는 올릴 커밋의 작업 코드를 기반으로 해결하면 됩니다!
4. prod 브랜치에 합치기 위해 origin에 push 합니다.
(release/v0.1.1)]$ git push
5. Github에서 prod 브랜치를 base로 해서 release/v0.1.1 브랜치를 기반으로 Pull Request 생성합니다.
6. (PR Approve 이후) 태그 생성 및 Release Note를 작성합니다.
모이삼은 하기 내용을 기반으로 컨벤션을 만들어 사용하고 있습니다.
- Tag : v0.1.1
- Target : release/v0.1.1
- Title : v0.1.1 (태그와 동일)
- previous tag : 이전 버전 태그 사용
- Release Notes : Generate release notes 버튼 클릭
컨벤션을 기반으로 내용을 작성해 release note를 생성합니다.
7. Pull Request를 prod 브랜치에 merge 합니다.
Rebase를 함으로써 각 PR에 해당하는 커밋만 확인할 수 있습니다. 또한 Squash Merge 방식을 사용하여 배포 이력만 깔끔하게 관리하도록 하였습니다.
8. release 브랜치를 develop 브랜치에 반영합니다.
(release/v0.1.1)]$ git checkout develop
(develop)]$ git rebase release/v0.1.1
release 브랜치에는 6번 과정에서 만든 태그가 포함되어 있지만, develop 브랜치에는 반영되어 있지 않습니다.
태그를 통해 앞으로의 develop 브랜치의 커밋을 prod 브랜치로 옮겨야 하기 때문에 rebase 합니다.
이때 rebase를 하면 conflict가 발생할 수 있습니다. conflict는 develop 브랜치의 코드를 기반으로 해결하면 됩니다!
9. 태그가 반영된 develop 브랜치를 origin에 push 합니다.
(develop)]$ git push -f
태그가 반영된 develop 브랜치는 로컬 환경에서만 보이기 때문에 팀원도 볼 수 있도록 origin에 갱신해야 합니다.
근데 앞서 말씀드린 것과 같이 rebase를 하면 force push를 하기 때문에 작업 브랜치에서는 괜찮지만 같이 사용하는 develop 브랜치는 매우 신중해야 합니다.
그래서 모이삼은 force push 이전의 규칙을 만들었습니다.
- prod에 올릴 커밋 말고 나머지는 develop에 잘 살아 있는지 확인하기! (태그 위에 존재)
- conflict 발생 부분이 develop 기준으로 잘 해결 됐는지 확인하기!
- 동료에 확인을 받았는지 확인하기!
위 규칙을 통해 과정들이 순차적으로 잘 진행됐는지 확인하고 운영 서버에 출시합니다.
끝으로..
Git-flow 가이드대로 따르려고 했지만 미숙한 부분이 많다고 생각합니다.
merge 커밋을 남기고 싶지 않아서 rebase를 적극적으로 사용하고 있고 커밋 히스토리를 깔끔하게 관리할 수 있어 만족합니다. 하지만 히스토리 변경으로 인해 force push를 해야 한다는 점에서 trade-off를 고려했어야 했습니다.
모이삼의 백엔드 팀원은 소수(2명)이고, conflict가 크게 발생하지 않고 있으며 Git 학습에도 도움이 된다고 생각해서 rebase를 사용합니다. 추후 모이삼 팀원이 증원되거나, 안정성에 집중한다면 merge를 사용하는 방식도 고려하고 있습니다!
만약 이 글을 읽어주신 분들께서 도입을 하신다면, merge 커밋이 남아도 괜찮으면 merge 방식으로 사용하셔도 좋을 것 같습니다.
감사합니다.
'Backend' 카테고리의 다른 글
[Redis] Lua Script로 동시성 문제 해결하기 (2) | 2025.06.09 |
---|---|
[Redis] 외부 API Rate Limiter를 만들어보기 (with. AOP) (1) | 2025.05.28 |
[RabbitMQ] Delayed Message Plugin를 활용한 메시지 지연 처리 (SpringBoot) (4) | 2025.02.04 |
[도메인 주도 개발 시작하기] Chapter6. 응용서비스와 표현 영역 (1) | 2024.11.18 |
[도메인 주도 개발 시작하기] Chapter5. 스프링 데이터 JPA를 이용한 조회 기능 (1) | 2024.11.03 |