Home 16. 버전 관리와 브랜치 관리
Post
Cancel

16. 버전 관리와 브랜치 관리

16.1 버전 관리란?

버전 관리 시스템(VCS)는 파일의 시간에 따른 변경 기록(버전)을 추적하는 시스템이다. 파일의 메타 데이터를 관리하며 이 메타 데이터와 파일들의 버전별 복사본을 합쳐 리포지토리라고 한다. VCS를 이용하면 여러 개발자가 같은 파일들로 동시에 작업할 수 있어서 팀 업무를 효과적으로 조율할 수 있다.

초창기 VCS에서는 파일 단위로 락을 걸어 수정중인 파일에 대해 다른 사람은 수정하지 못하도록 막았고, 조금 진보된 VCS에서는 변경된 파일들의 묶음을 하나의 단위로(원자적으로) 취급 하였다.

1990년대에 널리 쓰인 CVS 시스템은 이런 원자성을 제공하지 못하여 잘못하면 커밋이 충돌나서 변경 내역을 잃어버릴 수 있었다. 원자성을 보장하면 기존 변경이 의도치 않게 덮어써지는 사태를 막아준다.

16.1.1 버전 관리가 중요한 이유

버전 관리는 엔지니어가 소스 코드와 시간의 상호작용을 관리하는 핵심 도구이다. VCS는 파일이름, 작성시각 조합을 파일 내용과 연결해주며, 동시에 마지막 동기화 지점과 리뷰 기록을 추적하는 데 필요한 메타데이터도 관리해준다. 버전 관리는 개발 작업의 한 요소인 시간을 명확하게 드러내준다. 프로그래밍에서는 꼭 필요하지 않지만, 소프트웨어 엔지니어링에서는 아주 중요한 요소인 시간을 말이다. 오늘날의 VCS는 대부분 브랜치 이름까지 입력으로 받아 병렬로 매핑해준다.

VCS를 주저하는 이유가 있다면 프로그래밍과 소프트웨어 엔지니어링을 제대로 융합하지 못했기 때문이다. 경영진이 엔지니어의 일을 소프트웨어 엔지니어링이 아닌 소프트웨어 개발로만 생각해도 VCS를 주저하게 된다. 엔지니어의 업무 핵심을 프로그래밍으로 인식하여 코드와 시간의 상호작용을 제대로 이해하지 못한다면 실수를 되돌리기 위해 이전 버전으로 돌아간다라는 기능은 이상하고 값비싼 사치로 느껴질 수 있다.

버전 관리를 이용하면 개발자가 한 명이든 여럿이든 비슷한 프로세스로 개발할 수 있다는 장점도 있다. 프로젝트 되돌리기 기능은 잘 사용하지 않을 수 있다. 하지만 일관된 프로세스는 팀과 조직을 확장할 수 있는 중요한 열쇠다. 개발이란 본질적으로 분기하고 병합하며 전진하는 프로세스이다.

또 VCS는 법과 규제 관련 관행도 변화 시켰다. VCS는 모든 코드라인에 가해진 모든 변경을 기록한 공식 이력으로 인정되어 법적 다툼이 발생했을 때 감사 자료로도 이용된다. 그리고 개발자들의 행동 양식에도 변화를 가져왔다. 커밋 메세지를 작성하는 동안 자신을 되돌아보며 의미 있는 시간을 갖게 된다.

16.1.2 중앙집중형 VCS vs 분산형 VCS

중앙집중형 VCS

단 하나의 중앙 리포지터리를 이용하는 모델로 개발자들은 각 파일을 체크아웃하여 로컬 컴퓨터에서 이용할 수 있다. 이 파일들의 버전 관리 상태와 관련한 작업들은 반드시 중앙 서버에 전달해야 한다.

1970~1980년대에는 동시 편집을 막아주는 락킹에 집중했다. 단 한 사람만이 파일을 편집할 수 있도록 보장했다. 작은 수정사항이나 여럿이 같은 파일을 편집할 일이 거의 없을 때는 이 모델도 훌륭했으나 이런 구조는 확장하기가 어렵다.

확장 문제를 해결하고자 1990~2000년대에는 락을 한 사람이 독점하는 대신 어느 버전과 동기화했는지 추적하기 시작했다. 커밋에 포함된 모든 파일이 가장 최신 버전을 기준으로 했는지를 확인하는 것이다. CVS 시스템은 한 번에 여러 파일을 수정할 수 있고, 하나의 파일을 동시에 여러 개발자가 체크아웃할 수 있도록 했다.

분산형 VCS

2000년대 중반을 시작으로 가장 유명한 VCS들이 분산형 VCS 패러다임으로 갈아타기 시작했다. 선봉에 선 것이 깃과 머큐리얼이다. 분산형 VCS 세계에서는 중앙 리포지터리라는 제약이 사라지고 리포지터리의 복제본을 가지고 있다면 커밋할 수 있는 리포지터리를 소유한 것이다.

중앙이라는 것은 개념적으로만 존재할 뿐이다. 본질상 특정한 하나를 진실 공급원이라고 지정하지 않아도 되므로 오프라인 작업과 협업에 더 유리하다.

중앙집중형 VCS에서는 기술적으로 명확하게 정의된 중앙 리포지터리를 제공하고, 분산형 VCS에서는 프로젝트 대다수가 중앙 리포지터리를 정책 수준에서 정의한다.

16.1.3 진실 공급원

중앙집중형 VCS는 시스템 설계에서부터 진실 공급원 이라는 개념을 사용한다. trunk에 가장 최근 커밋된 것이 현재 버전이다. 개발자가 프로젝트를 체크아웃하면 기본적으로 트렁크 버전이 제공되고 수정 내역을 이 버전위에 다시 커밋하면 해당 변경이 완료된다.

분산형 VCS에는 여러 리포지터리 중 어느 것이 단일 진실 공급원이라는 개념이 없다. 중앙 통제나 조율 없이 커밋 태그와 PR을 전혀 다른 개발 브랜치로 전달할 수 있다.

실제로 깃 허브와 깃랩 같은 분산형 VCS 서비스를 많이 사용하고 있다. 이 서비스 이용자들은 프로젝트의 리포지터리를 복제하고 포크할 수 있지만 주 리포지터리는 여전히 하나뿐이다. 변경 사항이 주 리포지터리의 트렁크 브랜치에 반영되어야만 비로소 작업이 완료된다.

중앙의 진실 공급원이 없다면 누군가는 다른 릴리스에 포함시킬 기능 목록을 따로 관리해야 할 것이고, 결국 이 목록이 중앙화된 진실 공급원 모델을 모방한게 된다.

팀이 커져도 인원수 증가보다 적은 추가 노력으로 관리할 수 있는 시스템을 찾는다면 단 하나의 리포지터리와 하나의 브랜치를 궁극적인 진실 공급원으로 지정해야 한다.

16.1.4 버전관리 vs 의존성 관리

버전관리 정책은 개념적으로 의존성 관리와 매우 비슷하나 버전관리 정책은 주로 코드를 어떻게 관리할지를 다루고, 의존성 관리는 다른 조직에서 통제하는 프로젝트들을 관리해야 하기 때문에 훨씬 어렵다.

16.2 브랜치 관리

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

브랜치 관리 정책을 논의하려면 최소한 진행 중인 작업은 모두 하나의 브랜치와 같다는 점을 인정하고 시작해야 한다. 개발자가 상위 진실 공급원으로 푸시하기 전까지 수많은 변경사항을 로컬 리포지터리에 커밋해 놓은 분산형 VCS 모델을 생각하면 더 명확하다. 중앙집중형 VCS에서도 아직 커밋하지 않고 계류 중인 변경들은 브랜치에 커밋한 변경과 개념적으로 다르지 않다.

16.2.2 개발 브랜치

개발 브랜치는 구현은 다 했지만 커밋하진 않았어요 와 이제부터 이 코드를 기준으로 개발하세요의 중간 단계이다. 하지만 테스트, 지속적 통합, 철저한 코드 리뷰와 같은 품질 강화 활동을 더 광범위하게 진행하는 편이 더 효과가 좋다.

제품의 안정성 유지 차원에서 개발 브랜치를 과하게 사용하는 버전 관리 정책은 잘못되었다. 거대한 개발 브랜치를 병합할 때는 많은 것이 변경된 상태이므로 문제 원인이라고 예상되는 범위를 좁히기가 어렵다. 브랜치 하나를 병합할 때도 극복할 게 많으므로 개발 브랜치에 의존하는 방식은 확장하는 데 한계가 있다.

병합 후 다시 테스트하는 데 드는 노력은 무가치한 오버헤드이다. 다른 접근 방법으로 트렁크 기반 개발이 있다. 대신 테스트와 CI를 적극 활용하여 모든 빌드와 테스트가 항상 성공하도록 관리하며 완벽하지 않거나 테스트되지 않은 기능은 비활성화한다. 엔지니어 개개인이 트렁크와 동기화하고 트렁크에 커밋해야 한다. 수많은 개발 브랜치에서 단일 진실 공급원으로 좁힌다는 것은 어차피 포함시킬 기능을 더 일찍 확정하기 위한 원점회귀 전략인 것이다.

16.2.3 릴리스 브랜치

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

개발 브랜치와 달리 릴리스 브랜치는 대체로 무해하다. 브랜치라는 기술이 문제가 아니라 어떻게 활용하느냐가 문제이다.

트렁크로부터 하루에도 몇 번씩 릴리스할 수 있는 지속적 배포가 잘 자리잡은 조직에서는 대체로 릴리스 브랜치를 건너 뛴다. 수정사항을 적용해 다시 배포하는 게 훨씬 쉽기 때문이다.

16.3 버전 관리 @구글

구글의 소스 코드 대부분은 하나의 리포지터리, 즉 모노리포에서 관리되며 약 5만여 엔지니어에게 공유된다. 구글이 주관하는 프로젝트 거의 모두가 이 안에서 이루어지고, 일반 대중을 상대하는 제품뿐만 아니라 이런 제품을 개발하고 지탱하는 데 필요한 내부 인프라까지 아우른다.

구글은 자체 개발한 중앙집중형 VCS(Piper)를 이용한다. 프로덕션 환경에서 분산 마이크로서비스 형태로 구동되게끔 만들어져서 세계 곳곳에 흩어져 있는 구글 엔지니어들에게 표준화된 스토리지와 소통 수단을 제공한다. 초기 구상 단계부터 구글 규모를 감당하는 데 집중한 덕분에 지금까지도 엔지니어들에게 부담을 주지 않는다.

16.3.1 원-버전

버전관리의 또 다른 축은 정책이다. 구글 버전 관리 정책의 중심에는 원-버전 이 있다. 이는 단일 진실 공급원 개념을 확장한 개념으로 ‘모든 의존성이 우리 리포지터리에 담겨 있고, 각 의존성은 단 하나의 안정된 버전만 존재해야 한다.’는 뜻이다. 따라서 서드파티 패키지들도 Piper에는 단 하나의 버전만 저장해둬야 한다.

16.3.2 시나리오: 여러 버전을 허용한다면?

여러 버전을 허용하게 되면 운 좋으면 빌드 실패로 끝나지만 최악의 경우에는 라이브러리의 서로 다른 두 버전과 링크되어서 이해하기 어려운 런타임 버그가 발생한다.

16.3.3 원-버전 규칙

개발자가 이 구성요소는 어떤 버전을 사용해야 하죠? 라고 묻는 상황을 만들지 않아야 한다. 이 말이 곧 원-버전 규칙이다. 즉 의존성을 새로 추가할 때 선택할 수 있는 버전을 제한한다. 라는 식으로 풀어서 표현할 수 있다.

16.3.4 장수 브랜치는 (웬만하면)금지

원-버전 규칙에는 몇 가지 더 깊은 뜻과 정책이 내포되어 있다. 그중 가장 중요한 정책은 개발 브랜치를 되도록 만들지 말고, 만들더라도 매우 짧게 쓰고 없애햐 한다는 것이다. 오래 묵히지 말고 작업을 작은 증분으로 나눠 정기적으로 트렁크에 커밋해야 한다.

16.3.5 릴리스 브랜치는 어떤가?

릴리스를 매달 하면서 동시에 다음 릴리스를 준비하는 팀이라면 릴리스 브랜치 이용은 매우 합리적인 선택이다.

16.4 모노리포(단일 리포지터리)

모노리포 방식은 그 자체로 몇 가지 이점을 제공한다. 그중 최고는 원-버전을 고수하기가 쉽다는 것이다. 일관성 덕분에 도구를 새로 도입하거나 코드를 최적화한 혜택이 조직 전체에 훨씬 빠르게 전파된다.

중요한 것은 모노리포냐 아니냐가 아니라 원-버전을 최대한 준수하는 것이다. 즉 조직에서 이미 사용중인 라이브러리에 대한 의존성을 추가할 때 개발자가 버전을 선택하게 해서는 안 된다.

16.5 버전 관리의 미래

모노리포 방식의 이점을 공개적으로 논의 중인 기업이 구글만은 아니다. 마이크로소프트, 페이스북, 넷플릭스, 우버 역시 자신들의 방식을 공개한 바 있다.

모노리포에 대한 가장 큰 우려는 모든 것을 하나의 리포지터리에 담을 수 있는 기술이 있느냐 이다. 지난 몇 년에 걸쳐 깃에는 얕은 복제, 희소 브랜치, 최적화 등 대규모 리포지터리를 지원하는 기능이 다수 갖춰졌다. 구글은 이 노력이 앞으로 계속되어 그래도 리포지터리를 작게 유지해야 한다는 주장의 힘이 점점 약해지리라 기대한다.

구글은 버전 관리와 의존성 관리가 향후 10~20년 사이에 이 방향으로 발전할 것으로 본다. 아마도 현존하는 패키지 관리 단체나 리눅스 배포자 중 하나가 업계 표준의 가상 모노리포 구축을 촉진할 것이다.

16.6 마치며

버전 관리 시스템은 협업 효율을 끌어올리기 위해 업무 조율 정책에 기술을 접목하면서 자연스럽게 탄생된 결과물이다. 초기의 VCS들은 단순히 파일 단위의 락킹만 제공했고, 프로젝트와 팀의 규모가 커지면서 이 방식의 한계가 드러났고 버전 관리를 바라보는 관점도 달라졌다.

현재 분산 VCS의 탈 중앙화는 업계가 팔요로 해서 탄생한 합리적인 결과물이다. 그러나 분산 VCS는 설정을 엄격하게 통제하고 각 조직에 맞는 브랜치 관리 정책과 결합될 때 비로소 빛을 발한다. 또 예기치 못한 확장성 문제로 고생할 때도 많다.

선택에는 대가가 따르고 구글은 원-버전 규칙을 적극 권장한다. 개발자들이 어디로 커밋해야 할지, 어느 버전을 이용해야 할지를 선택할 수 없어야 한다.

16.7 핵심 정리

  • 개인 토이프로젝트가 아니라면 소프트웨어 개발 프로젝트에서는 무조건 버전 관리 시스템을 이용하자
  • 어느 버전을 사용할지 선택할 수 있다면 잠재적으로 확장성이 떨어진다는 뜻이다.
  • 원-버전 규칙은 조직의 효율에 지대한 영향을 준다. 선택할 일을 없애므로써 단순화할 수 있다.
  • 기존 연구들이 트렁크 기반으로 개발하는 조직일수록 성과가 좋을 가능성이 높음을 보여줬다.
  • 여러분에게 적합한 버전 관리 시스템을 사용하라
This post is licensed under CC BY 4.0 by the author.

15. 폐기

17. Code Search