소스 버전 관리는 개발에 없어서는 안 되는 주요한 항목입니다. 저희는 이전에 계속 소스세이프를 사용하다가 푸른돌조사단 프로젝트를 진행하면서 svn을 본격적으로 도입하게 되었는데, 이 과정에 대해 얘기해보는 것도 재미있을 것 같아 글을 쓰게 됐습니다.
소스세이프는 사실 평이 좋지 않은 버전 관리 툴이기 때문에 소스세이프를 계속 사용했다는 것에 대해 의문이 있는 분들이 꽤 있을 것입니다. 여기에는 몇 가지 이유가 있었는데요. 먼저 비주얼스튜디오에 통합하여 사용할 수 있는 툴이라는 점이 이유였습니다. 하지만 이것만으로는 사용 이유가 충분치 않을 것입니다. 이미 비주얼스튜디오에 플러그인을 설치해서 svn을 사용할 수 있기 때문이지요.
그렇다면 다른 이유를 들어봐야겠지요. 그것은 branch 같은 기능을 지원하지 않는다는 점 때문입니다. 모두들 이 점을 단점으로 생각하시겠지만 소스세이프는 이런 기능이 없기 때문에 오히려 굉장히 사용방법이 단순하지요. 그래서 그래픽 디자이너도 사용하기에 큰 무리가 없는 수준입니다. 그래픽 작업물들도 히스토리 관리를 하고싶은데 그렇다고 svn의 개념을 프로그래머가 아닌 다른 팀에게 학습시키는 것은 오버헤드이고 또 그렇게 해도 잘 관리되기가 어려울 것입니다. 그리고 여기에 덧붙여 프로젝트의 크기가 대체로 크지 않아 주로 한 명의 프로그래머가 하나의 프로젝트를 담당하게 되는만큼 branch를 만들게 될 필요성도 크지 않았습니다. 오히려 기능이 적은 것이 적합하다고 판단되었기에 소스세이프를 선택한 것이지요.
그렇다면 다른 이유를 들어봐야겠지요. 그것은 branch 같은 기능을 지원하지 않는다는 점 때문입니다. 모두들 이 점을 단점으로 생각하시겠지만 소스세이프는 이런 기능이 없기 때문에 오히려 굉장히 사용방법이 단순하지요. 그래서 그래픽 디자이너도 사용하기에 큰 무리가 없는 수준입니다. 그래픽 작업물들도 히스토리 관리를 하고싶은데 그렇다고 svn의 개념을 프로그래머가 아닌 다른 팀에게 학습시키는 것은 오버헤드이고 또 그렇게 해도 잘 관리되기가 어려울 것입니다. 그리고 여기에 덧붙여 프로젝트의 크기가 대체로 크지 않아 주로 한 명의 프로그래머가 하나의 프로젝트를 담당하게 되는만큼 branch를 만들게 될 필요성도 크지 않았습니다. 오히려 기능이 적은 것이 적합하다고 판단되었기에 소스세이프를 선택한 것이지요.
하지만 점차 프로젝트 규모가 커지고 하나의 프로젝트에 참여하는 프로그래머 수가 많아지는만큼 소스세이프로는 한계가 발생하기 시작했습니다. 당시 네박자쿵짝을 개발하던 쯤이었는데 이 때에 처음으로 svn 도입을 하게 되었습니다. 그래픽 디자이너나 레벨 디자이너들은 기존대로 소스세이프를 사용하고, 프로그래머들만 svn으로 migration하는 방향으로 진행하였습니다. 하지만 결과적으로 도입에 실패하였고 프로그래머들도 다시 버전 관리를 소스세이프로 하는 것으로 돌아왔습니다. svn 사용법이 익숙치 않은 데다 프로젝트 관리 규칙을 미리 합의하지 않고 들어간 것이 문제였습니다. 프로젝트 히스토리를 잘 관리하기 위함이 목적이었는데, branch가 중구난방 네이밍도 제멋대로이니 오히려 히스토리를 쫓아가기가 버거웠습니다.
그러다가 푸른돌조사단 개발에 들어가면서 다시 svn 도입에 대한 필요성이 제기되었고, 이번에는 규칙을 잘 정하고 시작해서 이전과 같이 히스토리 관리가 엉망이 되지 않도록 하자고 얘기가 되었습니다. 그래서 이에 대한 논의를 시작하게 되었고, 중요한 방침 두 가지를 정했습니다.
첫째, 어느 피씨에서든 svn을 세팅하기만 하면 쉽게 프로젝트의 빌드가 가능한 상태가 될 수 있도록 하자.
둘째, 버전 히스토리를 추적하기가 용이하게 하자.
둘째, 버전 히스토리를 추적하기가 용이하게 하자.
이를 가지고 잡았던 구조는 대략 이랬습니다.
Projects (프로젝트 루트 폴더)
-+ 프로젝트A
—+ trunk
—–+ Source
——-+ Client
-+ 프로젝트A
—+ trunk
—–+ Source
——-+ Client
——-+ Server
——-+ Resource
—+ branches
——-+ 브랜치명A
—+ tags
-+ …
——-+ 브랜치명A
—+ tags
-+ …
Common (라이브러리 루트 폴더)
-+ 라이브러리A
-+ …
-+ 라이브러리A
-+ …
일반적인 svn 사용법처럼 프로젝트 하위에 trunk, branches, tags를 만들었습니다. 여기서 trunk 폴더의 하위를 보면 Source라는 폴더가 하나 끼어있습니다. 이렇게 depth를 하나 추가한 이유는 프로젝트의 branch를 만들 때에 브랜치명으로 폴더가 하나 만들어지면서 depth가 하나 늘어나게 되는데, 이로 인해 프로젝트에서 참조하는 라이브러리의 상대 경로가 trunk와 branch에서 달라지는 경우를 방지하기 위해서입니다. Source 하위에는 Client, Server, Resource의 폴더를 나누었습니다. 리소스 파일을 다른 곳에서 관리하면 관리가 이원화되어 빌드에 문제가 생길 것으로 여겨져 Resource 폴더도 추가하게 되었습니다. 그래픽 팀이나 다른 팀의 작업물까지 svn으로 관리하기는 버거우니 프로그램에서 런타임에 사용하는 바이너리 파일만을 업로드하기로 했습니다.
이 방향으로 잡고 관리를 시작했고 trunk만 사용 중일 때에는 특별한 문제가 없었습니다만, branch를 만들게 되면서 문제가 생겼습니다. svn 루트 폴더를 통째로 받기만 하면 프로젝트를 빌드할 수 있게 하자는 것이 목적이었는데, 프로젝트 루트 폴더를 갱신하면 프로젝트의 branch들까지 모조리 받게 되니 branch가 하나씩 늘 때마다 같은 프로젝트를 여러 개 복사해서 받는 꼴이니 괜한 시간이 허비되는 것이었습니다. 그래서 아래 방향처럼 바꾸게 되었습니다.
ProjectBranches
-+ 프로젝트A
-+ …
Projects
-+ 프로젝트A
—+ Client
—+ Server
—+ Resource
Common
-+ 라이브러리A
-+ …
trunk, branches, tags의 폴더를 사용하는 것이 널리 쓰이는 방식이지만 꼭 따를 필요는 없으니, 각 프로젝트에서 branches 폴더를 떼어내고 branch만을 관리하기 위한 상위 폴더를 만들었습니다. tags 폴더는 사실상 사용하는 경우가 없어 지워버렸습니다. svn 가장 상위에서 Projects는 trunk 같은 역할, ProjectBranches가 branches 같은 역할을 맡도록 한 것입니다. 그리고 ProjectBranches 폴더는 따로 받지 않고, 필요한 경우 Projects의 폴더에서 switch를 하는 식으로 사용하기로 했습니다. 아무래도 branch를 전부 받게 되지 않기 때문이었습니다. branch를 전부 받지 않게 되다보니 depth를 맞추기 위해서 억지로 끼워 넣었던 Source라는 불필요한 폴더도 삭제하게 되었습니다.
branch 폴더를 분리하고나니 좀 더 사용이 수월해져 한동안 잘 사용을 했습니다. 하지만 시간이 지나고나니 서버 프로그래머에게 불편한 점이 생겼습니다. 클라이언트 프로그래머인 저는 개발을 진행하면서 계속 로컬 파일이 최신으로 업데이트 되지만, 서버 프로그래머가 간만에 클라이언트 프로토콜을 확인하려고 프로젝트를 업데이트하면 변경된 리소스까지 왕창 받아오게 되었습니다.
그리고 리소스의 바이너리 파일을 관리하는 측면에서 또 다른 종류의 불편함이 있었습니다. 그래픽 디자이너나 레벨 디자이너가 작업물을 만들고 빌드에 포함시키기로 확정이 되면 프로그램에서 사용하는 바이너리 파일로 변환을 하는 작업까지 마치게 되는데, 이를 업로드하려면 항상 프로그래머를 거쳐야 하는 것이지요. 그러다보니 다른 팀에서 작업물을 빌드에 반영하는 것이 누락되는 과정이 빈번히 생기고, 빌드를 하는 날이면 프로그래머는 야근을 하게 되는 것이 반복되었습니다.
소스코드가 들어간 프로젝트 폴더만을 받고 싶은데 리소스까지 왕창 받아오는 문제, 그리고 리소스 파일 업로드를 프로그래머를 거쳐야하는 문제를 해결하기 위해 Resource 폴더도 상위로 빼내고 이 폴더는 그래픽 디자이너나 레벨 디자이너들이 업로드를 하고, 프로그래머는 update로 받아오도록 다시 관리 구조를 바꿨습니다.
ProjectBranches
-+ 프로젝트A
-+ …
Projects
-+ 프로젝트A
—-+ Client
—-+ Server
-+ …
Resources
-+ 프로젝트A
—-+ 그래픽리소스
—-+ 레벨링데이터
—-+ …
-+ …
Common
-+ 라이브러리A
-+ …
프로그램 팀이 아닌 다른 팀에서는 svn을 사용하지 않도록 하려 했으나, 빌드 리소스 관리에 문제가 지속적으로 발생했고 어차피 리소스 파일들도 히스토리가 관리되어야 할 거면 이미 잘 만들어진 툴인 svn을 사용하는 게 좋겠다는 생각이 들었습니다. 그리고 svn을 통해 업로드한 파일은 CDN 관리 서버에서도 받아올 수 있고, 빌드 자동화 서버에서도 스크립트를 이용해 빌드 시에 최신 리소스를 받아올 수 있으니 추가적인 이점도 있었지요. 그래서 그래픽 디자이너와 레벨 디자이너 분들에게 Tortoise SVN을 세팅을 해드리고 지속적으로 사용법을 익힐 수 있도록 서포트를 해드렸습니다. 초반에는 파일 conflict가 발생한다거나 add 해야 할 파일들이 누락되는 등의 문제로 리소스 파일이 제대로 업데이트 되지 않아 푸른돌조사단 컨텐츠 패치 시에 몇 번 문제를 겪기도 했지만, 후에는 담당자 분들의 숙련도가 올라가 패치 프로세스도 안정화 될 수 있었습니다.
처음 생각했던 것만큼 원활히 진행되지는 않았지만 몇 차례 구조를 수정하면서 처음에 원했던 원칙들인 쉽게 프로젝트를 세팅하고, 버전 히스토리 추적을 용이하게 하자는 목표를 어느 정도 만족할 수 있게 되었습니다. 이전 svn 도입이 실패했을 때와 비교해보면, 단순히 툴에 대한 평이 좋다거나 혹은 주변에서 다들 쓴다거나 해서 도입하는 것이 아니라 원하는 목표나 원칙을 잘 세우고 들어간 것이 이런 차이를 만든 것이 아닐까 합니다. 어떤 일이든 항상 방향성을 잘 잡고 시작하는 것이 중요하다고 느끼게 해준 경험이었습니다.
by Jake Noah