버전 관리와 브랜치 관리

강재민·2023년 8월 14일

버전 관리란?

VCS는 파일의 시간에 따른 변경 기록을 추적하는 시스템입니다.
또한 협업 관점에서 SSOT (Single Source of Truth)의 존재는 매우 중요합니다.

버전 관리가 중요한 이유

개발이란 본질적으로 분기하고 병합하며 전진하는 프로세스이모, 분기와 병합은 여러 개발자 사이에서 이루어지는 혹은 한 명의 개발자가 여러 시간대에서 수행하는 작업들을 체계적으로 관리해주는 핵심 개념입니다. VCS는 어느게 최신이지? 라는 질문을 사라지게 해줍니다. 변경 추적처럼 오류가 끼어들기 쉬운 작업을 자동화합니다. 버전 관리는 여러 개발자와 여러 시점 사이를 교통정리해주는 멋진 도구입니다.

중앙집중형 VCS

중앙집중형 VCS는 단 하나의 중앙 리포지터리를 이용하는 모델입니다.
개발자들은 각 파일을 체크아웃하여 로컬 컴퓨터에서 이용할 수 있습니다.
이 파일들의 버전 관리 상태와 관련한 작업들은 반드시 중앙서버에 전달해야 합니다.
개별 개발자가 커밋하는 모든 코드는 결국 중앙 리포지터리로 커밋됩니다.

개발자가 리포지터리의 가장 최근 변경까지를 동기화한 후 수정한 것이라면 커밋할 수 있게 합니다.

분산형 VCS

전통적인 중앙집중형 VCS와 개념적으로 가장 큰 차이는 '어디에 커밋하는가?' 혹은 '이 파일들의 어느 복사본이 리포지터리로 간주되는가?'

분산형 VCS 작업 흐름
1. 기존 리포지터리를 로컬에 복제합니다.
2. 파일을 변경합니다.
3. 로컬 리포지터리에 커밋합니다.
4. 2~3을 원하는 만큼 반복합니다.
5. 로컬에 적용된 커밋 중 일부를 혹은 전체를 다른 리포지터리로 커밋합니다. 이때 다른 리포지터리는 1에서 복제해온 리포지터리일 수도, 아닐 수도 있습니다.

'진행 중인 작업'은 브랜치와 비슷하다.

'커밋 전 작업은 하나의 브랜치와 같다'라는 생각은 특히 리팩터링 시 잘 들어맞습니다.
한 개발자가 'Wideget의 이름을 OldWidget으로 바꾸자'라고 말했다 칩시다. 이 말은 조직의 브랜치 관리 정책과 이해 정도, 그리고 어디까지를 브랜치로 간주할 것인가에 따라 여러 가지로 해석될 수 있습니다.
1. 진실 공급원 리포지터리의 트렁크 브랜치에 있는 Widget의 이름을 바꿉니다.
2. 진실 공급원 리포지터리의 모든 브랜치에서 Widget의 이름을 바꿉니다.
3. 진실 공급원 리포지터리의 모든 브랜치에서 Widget의 이름을 바꿉니다. 그리고 Widget을 참조하는 계류 중인 변경들까지 모두 찾아서 바꿉니다.

개발 브랜치

일관된 단위 테스트가 보편화되기 전 시절에는 작은 변경 하나라도 시스템을 망가뜨릴 위험이 컸기 때문에 '트렁크'를 특별 취급하는 게 당연했습니다.

테크 리드는 이렇게 이야기하곤 했을 것입니다. "우리는 새로운 변경이 모든 테스트를 통과할 때까지 트렁크에 커밋하지 않습니다. 그리고 우리 팀은 기능별로 개발 브랜치를 따로 만들어 사용하죠"

개발 브랜치(dev branch)는 '구현은 다 했지만 커밋하지 않았어요''이제부터 이 코드를 기준으로 개발하세요'의 중간단계 입니다. 개발 브랜치를 따서 해결하려는 것 (제품이 불안정해지는 일방지)은 온당 신경 써야 하는 문제입니다. 하지만 TEST, CI, Code Review와 같은 품질 강화 활동을 더 광범위하게 진행하는 편이 효과가 훨씬 좋습니다.

제품 안정성 유지 차원에서 개발 브랜치를 과하게 사용하는 버전 관리 정책은 근본적으로 잘못 되었다고생각합니다. 결국은 똑같은 커밋들이 트렁크에까지 병합될 것입니다. 큰 단위로 한 꺼번에 병합하기보다는 작게 작게 자주 병합하는 게 쉽습니다. 각각의 변경을 작성한 당사자가 병합하는 편이 서로 관련되어 당사자를 나중에 알아내기가 쉽습니다.
거대한 개발 브랜치를 병합할 때는 많은 것이 변경된 상태이므로 문제 원인이라고 예상되는 범위를 좁히기가 어렵습니다.

브랜치 하나를 병합할 때도 이처럼 극복할 게 많으므로 개발 브랜치에 의존하는 방식은 확장하는 데 한계가 있습니다. 소프트웨어 조직에서 흔히 겪는 생산성 저하 사례죠. 다수의 브랜치에서 장기간 독립적으로 개발을 진행했다면 병합 시 엄청난 우여곡절을 겪을 것이고, 병합 후에도 더 많은 위험이 수면 밑에 도사리고 있을 것입니다.

개발 브랜치에 중독되어 가는 과정

조직이 이 함정에 걸려드는 과정은 간단합니다. '오래된 개발 브랜치를 병합하니 안정성이 떨어진다'는 경험이 '병합은 위험하다'는 결론으로 이어지는 것입니다.

병합을 했을 때 문제가 발생하다보니 병합을 더 조심스럽게 더 천천히 하게 되고 결국에는 고질적인 문제는 해결이 안되고 계속해서 문제를 외면하는 꼴이 되는 것이죠.

이때 나온 전략이 TBD입니다. TBD를 통해 병합 후 다시 테스트하는 데 드는 노력을 들이지 않아도 되기 때문이죠.

릴리스 브랜치

제품의 릴리스 간격 (혹은 릴리스 수명)이 몇 시간 이상이면 릴리스 브랜치를 따로 생성하는 게 좋습니다. 이 브랜치는 릴리스한 제품과 정확히 같은 코드를 담게 됩니다. 공식 릴리스 후 다음 릴리스 전에 심각한 결함이 발견된다면 트렁크에서 해당 수정 코드를 최소한으로 선별하여 릴리스 브랜치로 병합합니다.핫픽스

개발 브랜치와 릴리스 브랜치의 가장 큰 차이는 생을 마감하는 모습입니다.
개발 브랜치는 트렁크에 다시 병합될 텐데, 중간에 다른 팀이 브랜치를 추가로 따서 가지를 더 뻗을 수도 있습니다. 반면 릴리스 브랜치는 홀로 존재하다가 결국 사라질 것입니다.

구글의 DORA 조직의 연구 결과에 따르면 최고 수준의 기술 조직에는 릴리스 브랜치 조차 없습니다.
트렁크로부터 하루에도 몇 번씩 릴리스할 수 있는 지속적 배포가 잘 자리 잡은 조직에서는 대체로 릴리스 브랜치를 건너뜁니다. 수정사항을 적용해 다시 배포하는 게 훨씬 쉽기 때문이죠.

그래서 별도 브랜치를 두고 병합할 코드를 선별하는 일은 모두 불필요한 오버헤드인 셈입니다.

DORA 연구에서 '트렁크 기반 개발' 조직과 '장기간 유지되는 개발 브랜치가 적은' 조직일 수록 기술적 성취가 뛰어나다고 이야기합니다.

0개의 댓글