안녕하세요. 이 글에서는 Pull Request(PR)이 없던 회사의 혼돈의 로컬 개발 환경에서, PR 단위 코드리뷰와 Git Flow를 도입했던 경험을 풀어보려고 합니다.
당시 저희 팀은 각자 로컬에서 Merge하고 Push하는 방식으로 작업했고, 모든 개발이 단일 브랜치(dev)에서 이루어졌기에 Cherry-pick 남발과 그로 인한 conflict가 반복되고 있었습니다.
이를 해결하기 위해 주니어 개발자인 저와 동료들의 변화가 만들어낸 이야기를 전해드리려 합니다.
도입 전 우리 팀의 브랜치 구조와 git 전략은 아래와 같았습니다.
- prod(main): 운영 환경에 반영되는 브랜치
- staging: 운영과 동일한 환경에서 테스트를 진행하는 브랜치
- dev: 모든 개발자가 작업하고 커밋하는 브랜치
이 구조는 GitLab Flow 방식으로 장단점이 있었지만, 저희의 작업 방식에 문제가 있었습니다.
로컬 중심의 Merge
각자 자신의 로컬에서 Merge하고 Push하다 보니, 충돌 발생 시 해결은 전적으로 개인 몫이었습니다.
개발자마다 로컬 상태가 다르다 보니, 누군가는 커밋을 뒤늦게 가져오면서 충돌을 마주하기도 했습니다.
단일 dev 브랜치에 모든 작업이 몰림
기능 개발, 버그 수정, 핫픽스 등 모든 작업이 dev 브랜치 하나에 몰려 관리가 어려웠습니다.
어떤 기능이 완료되었고, 어떤 기능이 아직 미완성인지 구분이 어려웠습니다.
긴급 배포의 어려움
특정 기능이나 긴급한 버그만 배포해야 할 때, Cherry-pick으로 staging에 특정 커밋만 가져와 반영했습니다.
이후 dev 브랜치를 다시 staging으로 병합할 때, 이미 Cherry-pick으로 들어간 커밋과 dev의 동일한 커밋이 충돌을 일으켰습니다.
이 충돌을 매번 해결해야 했고, 점점 더 복잡해졌습니다.
문제는 특히 dev 브랜치에서 작업하던 코드 중, 특정 커밋만 운영 환경(prod)에 먼저 반영해야 할 때 발생했습니다. 긴급한 버그 수정이나 특정 기능이 필요할 때 Cherry-pick을 사용했지만, 이는 반복적인 충돌 지옥을 유발했습니다.
왜 Cherry-pick이 문제였을까?
불완전한 반영 흐름:
dev에 커밋된 코드 중 일부만 Cherry-pick으로 staging에 반영하고, staging을 다시 prod로 Merge했을 때 dev와 staging 간 병합 이력이 맞지 않으면서 충돌이 발생했습니다.
반복적인 충돌:
이후 dev 브랜치를 staging으로 Merge하려 할 때, 이미 Cherry-pick으로 staging에 반영된 커밋과 dev의 동일한 커밋이 충돌을 일으켰습니다.
작업 중단:
이러한 충돌을 해결하는 과정에서 다른 작업이 중단되었고, 결과적으로 staging → prod로 이어지는 작업 흐름이 계속해서 방해받았습니다.
관리 복잡성 증가:
dev, staging, prod 간 병합 히스토리가 불일치하면서, 이후 작업 시 추가적인 충돌이 발생하는 악순환이 이어졌습니다.
저와 동료는 이러한 문제를 해결하기 위해 PR 기반 코드리뷰와 Git Flow 도입을 제안했습니다. 하지만 처음부터 모두가 이 방식을 환영했던 것은 아니었습니다.
팀원들:
"해본적이 없어서 어려워 보인다."
"PR 같은 걸 하면 더 오래 걸릴 것 같은데?"
"지금도 충분히 잘 되고 있는 거 아닌가?"
관리자:
"시간 낭비처럼 보인다."
이런 반응 속에서 Cherry-pick 문제를 중심으로 동료들과 관리자를 설득하기 시작했습니다.
저는 과거 Cherry-pick 문제로 인해 발생했던 충돌 사례를 기반으로 설득을 진행했습니다.
충돌 사례 재현:
이전에 발생했던 Cherry-pick 충돌 상황을 재현해 보여주며, dev → staging → prod 간 작업 흐름이 얼마나 쉽게 꼬이는지를 시각적으로 설명했습니다.
Git Flow 전략의 대안 제시:
Git Flow 전략을 사용하면, 브랜치 관리가 체계적으로 이루어져 Cherry-pick 없이도 특정 작업을 staging에 반영할 수 있습니다. 또한, 병합 전 리뷰와 테스트를 통해 충돌 가능성을 사전에 제거할 수 있음을 강조했습니다.
시간 절약 효과:
Git Flow와 PR 도입이 초기에는 익숙하지 않을 수 있지만, 장기적으로 충돌 해결에 드는 시간을 줄이고 작업 흐름을 개선할 수 있음을 어필했습니다.
설득만으로는 부족했기에, 저는 테스트 MR을 만들어 팀원들이 변화를 직접 체감할 수 있도록 했습니다.
테스트 환경 구성:
간단한 기능을 dev 브랜치에서 작업한 뒤, 해당 기능을 PR 단위로 staging과 prod로 Merge하는 시뮬레이션을 진행했습니다.
기존 방식과 비교:
Cherry-pick 방식과 PR 방식을 비교하며, PR 방식을 통해 충돌이 발생하지 않고 작업 흐름이 매끄럽게 진행되는 모습을 보여줬습니다.
참여 독려:
팀원들이 직접 PR을 작성하고 리뷰를 요청해 볼 수 있도록 유도해, PR 작성과 리뷰가 복잡하지 않다는 점을 체감하게 만들었습니다.
(당시 설득을 위한 Test MR)
Git Flow는 dev, staging, prod 간의 혼란을 정리하는 데 중요한 역할을 했습니다.
- main (prod): 운영 환경
- staging: 운영과 동일한 조건의 테스트 환경
- dev: 개발 통합 브랜치
- feature/*: 기능 단위의 작업 브랜치
- hotfix/*: 긴급 수정 사항 처리 브랜치
코드리뷰를 강제적으로 도입하지 않고, 팀원들이 부담 없이 적응할 수 있도록 설계했습니다.
리뷰어 지정 방식:
리뷰 요청자가 스스로 리뷰어를 지정할 수 있도록 해 강제성을 줄였습니다.
Pn룰 도입:
Pn룰을 추가해 리뷰 강도 조절를 조절할 수 있게 하여 리뷰 과정을 협업과 학습의 장으로 만들었습니다.
P1: 꼭 반영해주세요 (Request changes)
P2: 적극적으로 고려해주세요 (Request changes)
P3: 웬만하면 반영해 주세요 (Comment)
P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
P5: 그냥 사소한 의견입니다 (Approve)
저희는 다음과 같은 리뷰들이 주로 생기게 됐습니다.
물어보기
칭찬하기
놓친부분 있는지 확인해주기
충돌 문제 감소:
PR 단위로 작업하면서 Cherry-pick이 필요 없어졌고, dev → staging → prod 병합 과정에서 충돌이 거의 발생하지 않았습니다.
작업 흐름의 투명성:
Git Flow와 PR을 통해 작업 이력과 변경 사항이 명확히 기록되면서 관리 효율이 증가했습니다.
협업 문화 정착:
코드리뷰는 단순한 오류 검출이 아니라, 협업과 학습의 장이 되었습니다.
작업자와 리뷰어가 소통하며 더 나은 코드에 대해 토론했고, 팀의 코드 품질이 전반적으로 향상되었습니다.
PR 기반 코드리뷰와 Git Flow는 단순히 도구를 도입하는 것이 아니라, 팀 전체의 협업 문화를 바꾸는 여정이었습니다.
새로운 시도를 한다는 건 언제나 쉽지 않습니다. 하지만 저희 팀원들은 작은 변화에서 시작하여 이제는 없으면 안되는 회사의 개발 문화를 만들게 됐습니다.
이 경험이 비슷한 상황을 고민하고 계신 분들께 작은 힌트가 되었으면 좋겠습니다. 😊