티스토리 뷰

인류 역사 중 구석기 시대와 신석기 시대를 나누는 핵심은 도구이다. 구석기 시대는 뗀석기였고 신석기 시대에서는 간석기였다. 물론 뗀석기 보다 간석기가 더 날카롭고 만들고 난 후의 모양새도 훨씬 좋았다. 인간은 도구를 사용해야 한다. 물론 환경에 따라 발전된 도구를 사용해야 한다.


프로젝트를 개발함에 있어서 가장 중요한 도구중에 하나는 형상 버전 관리 도구이다. 어떠한 프로젝트라도 혼자가 아닌 여러명이 개발할 것이고, 서로간의 개발된 소스를 어떻게 공유하고 보존할 것인가에 대한 해결책은 바로 형상 버전 관리 도구이다.

먼 옛날(?) CVS부터 SVN, GIT 까지 각 시대를 대표하는 형상 버전 관리 도구가 있었고 개인적으로 생각하기에는 우리나라에서 가장 많이 사용되는 도구는 SVN라고 판단된다. 그리고, 지금 프로젝트를 하고 있는 곳에서도 형상 버전 관리 도구 표준이 SVN이었고 이를 사용해왔다. 그런데, 우리는 커다란 문제에 봉착하고 말았다.


처음에는...

첫 시작은 어떤 프로젝트도 똑같이 오순도순하며 개발하였고, 규모도 작았었다. 서로 일을 나눠해도 그렇게 겹치거나 어렵지도 않았다. SVN에 메인인 trunk에 서로 올려두고 필요한 것들을 공유하며 개발을 진행해 왔다. 사실 서로 소스 공유가 간편하게 사용할 수 있다면, 어떠한 형상관리 도구를 선택한 들 문제가 될 것인가? 


편한게 장땡이었다.


이클립스와 연결해서 사용하기 편리한 SVN은 우리에게 아주 적합한 도구였다.


문제적 환경

커다란 문제는 서비스오픈 이후 다가왔다. 서비스를 오픈하기 전 소스를 정리하고 배포판을 만드는데 이러한 과정을 우리는 '소스 프리징'이라 불렀다. 그리고 이 시점에 사용하기 위해서 젠킨스를 통해 빌드/배포 로직을 모두 구성하였고 그리 어렵지 않게, 문제가 발생해도 예상했던 범위 내에 모든것을 처리하고 배포를 완료했으며, '운영기' 라는 서버 환경에 안착, 서비스를 시작하게 되었다.


그렇게 서비스는 오픈하게 되었고, 이후 동일한 서비스 내 '고도화' 라는 거창한 이름을 달고 새로운 프로젝트를 하기 시작 했다.


이렇게 프로젝트를 하게 되면 화면 단위나 기능 단위로 업무가 묶에 되고 이 단위로 움직이게 되는데, 문제가 발생한 것이 바로 만들어진 A, B, C 기능'개발기'에 배포하여 기능을 확인하고 싶지만, '운영기'에는 A 기능만 반영하고 싶다라는 것이다.


멀리서 보면 당연하다고 생각하겠지만 이때 당시 우리에게는 어마무시하게 큰 문제였다.

trunk에는 개발자 누구나 자신이 만들어진 기능들을 올리게 되는데, 심지어 다 만들어진 기능이 아닌 것들도(테스트 완료되지 않는 것 등) 서로간의 공유를 위해서 올려져 있는 상태에서 특정 기능'개발기''운영기'에 올리는 것은 쉽지 않은 일이다.


SVN으로 어떻게 해결할것인가?

이 문제를 해결하기 위해서 지금 사용하고 있는 SVN에서 처리하고 싶었다. 물론 SVN이 해당 업체의 표준이기 때문에 PM 입장도 SVN 내에서 처리 하기를 원했다. 그래서 첫 시도는 고육지책으로 각 개인별 '개발기'에 올릴 데이터를 자체적으로 원복하고 commit하라고 했다. 

그 시점에서 배포 담당자가 SVN 태그를 만들고 태그를 기반으로 배포를 했다. 물론 '운영기'에 올릴 데이터도 자체적으로 원복하고 커밋하고 태그 만들고 배포하는 과정을 거쳤다.


문제는 원복한 데이터로 커밋하게 되고 다시 돌아오는 것이 너무나 힘든 일이 었다. SVN 리비전을 뒤로 돌려 올리게 되면 서로간의 공유가 안되는 문제도 종종 발생하였고, 정해진 틀이 없이 각 개인별로 하기 때문에 엄격하게 나눠 commit하지 않으면 뒤로 돌릴때 어디까지 돌려야 하며 얼마나 돌려야 하고 수작업으로 틀어진 부분을 시간 들여 작업해야만 했다.


새로운 방안으로 브랜치를 도입하려 했으나, 이 또한 힘든 점은 브랜치 끼리의 머지를 손쉽게 지원하는 툴이 마땅치 않았기 때문이었다. (못찼았거나...) 이러한 경우 기능 단위로 브랜치끼리 반영될 소스들을 하나씩 찾아서 선택하여 반영하는 cherry-pick을 수행해야 하는데, 결국 기능단위로 '개발기'든 '운영기'든 배포되어야 하기 때문에 이 방법도 딱히 좋은 방안이 될 수 없었다.


결국 GIT로...

사실 이러한 문제를 해결하기 위한 마스터 키(?)는 예로부터 존재했었다. 바로 GIT. 자유자재로 브랜치를 부담없이 만들고 브랜치 별로 히스토리가 관리되며, 이를 통해 손쉬운 머지를 지원하는 GIT 말이다.


기존 프로젝트에서 GIT로 도입

그렇다면, '개발기', '운영기' 라는 환경을 사용하고 있는 전통적인 SI에서 이미 프로젝트가 수행되는 환경이라면 어떻게 GIT도입해야 할까? 계획없이 마구잡이로 GIT를 도입하게되면 SVN를 사용하는 그때와 다를 것은 없을 것이다. GIT가 기능이 많고 그 기능을 수행하여 많은 것을 할 수 있지만, 왜 사용해야 하고 어떻게 우리 프로젝트에 도입하여 사용되는지 모른다면 GIT에 메리트를 느낄 수 없다.


중요한 KEY는 바로 '기준 브랜치' 선정이다.


우리 프로젝트에서는 가장 중요하고 기준이 되는 브랜치가 '운영기 배포용'이기 때문에 이를 '기준 브랜치'로 선정했다. 


왜 이것을 가장 중요한 브랜치로 선정했을까? 


바로 '강제적 소스 환경 구성'이다. 모든 기능들은 결국 '운영기'배포하게 되어있다. 기능 단위로 개발할 때 어떤것은 '개발기'에, 어떤것은 '운영기'에 올라가게 되는데, 뒤집에 말하자면 어떠한 것도 '운영기'반영될 수 있다는 것이다. 이는 개발된 기능이 '운영기'에서 정상적으로 동작해야만 한다는 것이다.


즉, 누구나 개발하고 누구나 올리는 '개발기'를 기준으로 개발하게 되면 보이지 않는 손과 같이 나도 모르는 의존성이 독버섯처럼 피어나 '운영기'에 반영하면 안되는 기능이 생길 수 있다는 것이고, '개발기'는 배포되면 안되는 것들도 있을 수 있기 때문에 '운영기'에 넣는 것은 SVN의 이슈와 같이 힘들다.


그래서, 모든 기능들의 브랜치 생성은 '기준 브랜치'인 '운영기 배포용'을 기준으로 만들어져야 하는 것이다.


우리는 SVN에서 GIT로 어떻게 이동했나?

1. 모든 구성원들의 소스를 SVN에 올리고 정리한다.

2. 가장 먼저 '운영기'를 구성하기 위한 소스를 압축하여 준비하고, 뒤 이어 '개발기'를 구성하기 위한 소스를 압축하여 준비한다.

3. 기존 소스가 위치하는 프로젝트 폴더 내 GIT 로컬 저장소를 만든다.

4. 원격 GIT 저장소와 연결하고, .gitignore 파일을 만들어 반영하지 말아야 할 것들을 등록한다.

5. '운영기 배포용' 브랜치를 생성한다. (현재, 운영기 배포용 브랜치)

6. unstaged 항목을 무시하고, 프로젝트 폴더 내 소스를 삭제한다.

7. 프로젝트 폴더에 '운영기' 소스를 압축 해제한다.

8. '운영기' 소스를 죄다 '운영기 배포용' 브랜치에 커밋한다.

9. '개발기 배포용' 브랜치를 생성한다. (현재, 개발기 배포용 브랜치)

10. 프로젝트 폴더 내 소스를 삭제한다.

11. 프로젝트 폴더에 '개발기' 소스를 압축 해제한다.

12. '개발기' 소스를 죄다 '개발기 배포용' 브랜치에 커밋한다.

13. 끝


이렇게 연결되게 구성되면 '운영기 배포용'(deploy_prod)에서 생성된 모든 브랜치는 '개발기 배포용'(deploy_dev)에 그 기능만 머지 될 수 있고, '운영기 배포용'에 머지 되어도 '운영기' 환경에 문제 없이 머지가 된다.


GIT 사용 전략 예

작업을 하게 되면 화면이나 기능 단위로 구성한다. 각 업무는 숫자 번호가 부여되어 업무로 관리된다. 이 숫자 번호를 이용하여 신규 건은 'function', 기능 수정은 'patch', 버그나 이슈는 'issue'라는 prefix를 붙여서 브랜치 명명한다.


신규 화면 개발인데 관리되는 업무 번호가 1109이면 'function_1109'로 생성한다. 이 브랜치를 '운영기 배포용'브랜치에서 생성하여 서버 개발자와 화면 개발자는 서로 공유하여 작업한다. 테스트 및 작업이 완료되면, 브랜치를 생성한 담당자가 '개발기 배포용' 브랜치로 체크아웃한 후 작업된 브랜치를 머지한다.


머지된 '개발기 배포용'을 푸시하고 배포 담당자가 빌드/배포하여 '개발기'에서 업무담당자들과 테스트를 진행한다.

'개발기' 테스트를 완료한 브랜치 중 '운영기'로 배포 대상들은 배포 담당자가 직접 '운영기 배포용' 브랜치로 체크아웃하여 대상 브랜치와 머지하고 푸시한다.


배포 담당자가 빌드/배포하여 '운영기'에서 업무담당자들과 최종 테스트를 진행한다.


마지막으로...

GIT이 어떠한 이슈를 모두 해결할 수 있는 마스터 키는 아니다. 

우리와 같은 환경에서는 꼭 필요한 도구이지만, 단순한 프로젝트 환경이나 아직 운영기가 준비되지 않는 곳에서는 SVN으로도 충분히 케어가 가능할 것이다. 그냥 GIT쓰면 될일이라고 생각하지만, GIT를 처음 쓰게 되면 내 경험상 대부분의 개발자들이 사용하는 것을 싫어한다. GIT은 기능이 많고 생소한 단어들이 있어 이를 사용하기에는 적지않은 러닝 커브를 소요하기 때문이다.


나도 형상관리 도구가 표준으로 SVN이 정해진 환경에서 GIT를 도입하기 위해 도입되면 나타나는 기대효과 및 좋은 점에 대해 설명하는 것이 쉽지는 않았다. 예전에 SVN와 GIT를 동시에 사용하는 환경에서 형상 관리 서버가 죽었을때 SVN을 복구하는데는 한참 걸렸지만, GIT는 5분만에 원복 시킨 경험이 있어서 이런 저런 경험적인 요소가 있어 설득을 했던것 같다.


GIT를 쓸 수 있는 환경이라면 GIT를 쓰는 것이 맞고, 그게 아니면 환경을 잘 보고 어떤 도구를 사용할지 잘 선택해야 할 것이다.

댓글
댓글쓰기 폼