본문은 게임잼을 앞두고 기초적인 형상 관리에 익숙치 않은 모든 개발자들의 학습 및 프로젝트 초기 설정(setup) 비용을 감소시키기 위해 작성되었다. 이 글의 예상 독자로는 게임잼에 처음 참가하거나 게임을 만들고 싶은데 기본적인 형상 관리에 익숙하지 않은 모든 개발자를 포함한다.

형상 관리란?

하나의 게임을 구성하는 기본적인 요소들을 나열하자면 코드(codes)와 해당 코드가 참고할 데이터, 그리고 그래픽 리소스와 사운드 리소스를 비롯한 각종 리소스들을 언급할 수 있다. 형상 관리 시스템(VCS, Version Control System)은 이러한 코드와 데이터의 변경 내역들을 일종의 스냅샷으로서 모두 기억하고 필요하다면 어떤 변경 시점으로든 되돌릴 수 있는 시스템이다.

왜 게임잼의 참가자들에게 형상 관리가 필요한가?

  1. 게임잼은 1인팀이 아닌 이상 협업을 전제로 한다. 협업의 경우, 게임을 구성할 코드나 데이터를 제작하는 사람이 2명 이상이 되게 된다. 이때, 일반적으로 약 48시간의 한정된 시간 동안 진행되는 프로젝트이기 때문에 동시에 진행되는 병렬적인 작업 프로세스가 필수이다. 만약 하나의 팀에서 형상 관리를 이해하고 형상 관리 도구를 사용할 줄 아는 팀원이 단 한 명이라면 다른 팀원들이 게임을 구성할 코드나 데이터를 추가할 때마다 이 사람을 거쳐야 한다. 이는 해당 팀의 작업 프로세스에 있어서 코드나 데이터를 추가하는 프로세스가 병목구간(bottleneck)이 된다는 뜻이다. 이 비용을 사전에 줄이기 위해서라도, 팀원 내에 형상 관리를 이해하고 형상 관리 프로그램을 사용할 줄 아는 팀원이 많을 수록 좋다.
  2. 1에서 말한 것처럼, 게임잼은 동시에 진행되는 병렬적인 작업 프로세스를 전제로 한다. 그런데 이 동시성과 병렬성은 복수의 기여자들이 서로 충돌할 수 있는 위험성을 내포하고 있다. 예컨대, 같은 코드의 구간이나 데이터를 복수의 기여자들이 변경했다면 기여자들의 두 가지 의도가 충돌하고 있다는 의미이기 때문에 팀의 차원에서 이를 중재할 필요가 있다. 형상 관리 도구는 이같은 작업 기여에 대한 충돌이 발생했을 경우 이 충돌 시점과 내역에 대한 기록을 가지고 있기 때문에 코드나 데이터의 충돌을 명시적으로 또한 세밀하게 중재할 수 있는 가능성이 확보된다.
  3. 게임잼은 짧은 시간 동안 게임을 완성해야 하기 떄문에 코드나 데이터는 재사용성(reusability)보다는 기능(feature) 추가 여부에 높은 가치를 두고 제작되게 된다. 코드의 경우를 예로 들면, 재사용성이나 확장성을 고려하기 보다는 “일단 게임이 돌아가게 한다(make it work)”는 의도에 맞춰 작성된다는 뜻이다. 이러한 코드는 굉장히 빠른 속도로 작성될 수 있지만 게임잼 내내 요구사항의 변경 또는 그 자체의 불안정성으로 인해 많은 버그를 만들어 낼 위험을 가진다. 이런 경우, 코드나 데이터가 추가된 어떤 시점부터 문제가 발생했는지 빠르게 파악하고 해당 코드나 데이터를 수정하는 디버깅 생산성이 매우 중요해진다. 형상 관리 도구는 이러한 목적을 달성하는 수단이 된다.

본문에서 다룰 형상 관리 기초의 범위와 한계

  1. 독자가 Github 저장소를 생성하고 이와 연동된 Unity 프로젝트를 생성할 수 있다.
  2. 독자가 해당 게임 프로젝트에 코드나 데이터를 추가하거나 삭제할 수 있다.

게임잼을 위한 형상 관리 기초 Step by Step (Git with Unity의 경우)

  1. Github 계정을 생성한다.

    Create Github account

  2. 연 $7를 내고 비공계 저장소를 무한정 만들 수 있는 유료 계정을 원하지 않는다면 그냥 Continue.

    Choose personal plan

  3. 가입에 선택적으로 입력 가능한 사항들에 대해 답변한 뒤 Submit.
  4. 진행하기 전에 우선 이메일 인증을 받아야 한다.

    Start a project

  5. 개발할 게임 프로젝트와 연결할 저장소를 생성한다. Unity 엔진으로 게임을 개발할 경우에는 .gitignore: Unity를 선택한다. .gitignore에 대해서는 차후 설명한다.

    Create a new repository

  6. 게임 프로젝트와 연결할 저장소가 성공적으로 생성되었다.

    Produce101 repository

  7. 이제 Unity로 돌아가서 Unity 새로운 프로젝트와 해당 폴더를 생성한다. 본문은 Unity가 아닌 형상 관리 도구에 초점을 맞추고 있으므로 Unity 설치 단계에 대한 자세한 도움말은 생략한다.

    Create new project unity

  8. 형상 관리 도구를 설치한다. 형상 관리 도구는 SourceTree, GitKraken 등이 있다. 본문에서는 GitKraken으로 진행한다. 왜냐면 SourceTree는 추하고 GitKraken은 아름답기 때문이다.

  9. 설치한 GitKraken을 연다.

    GitKraken Startup

  10. File -> Init Repo를 선택한다.

    File -> Init Repo

  11. .gitignore Template의 경우는 형상 관리 대상에서 특정 파일을 제외시키는 목록에 해당한다. Unity 엔진에서 생성하는 일부 파일들의 경우 형상 관리할 필요가 없으므로 주어진 목록 중 Unity를 선택한다. 이는 5와 중복되는 작업에 해당하며 둘 중 한 번만 하면 된다.

    Init Repo Unity

  12. 이제 앞서 생성한 Git 저장소의 돌아가서 해당 저장소의 HTTPS 주소를 복사해온다.

    Clone with HTTPS

  13. 복사해온 Git 저장소의 주소를 통해 원격(remote) 저장소를 추가한다.
    1. REMOTE 오른쪽 공간에 마우스 오버하면 + 버튼이 뜬다.

    Add Remote

  14. 형상 관리에 있어 각 변경 시점은 흔히 그래프로 표시된다. 현재 자신의 컴퓨터에 속하는 로컬(local) 저장소가 방금 추가한 원격 저장소와 분리되어 있는 것을 볼 수 있다. 여기서 로컬 저장소의 상태가 원격 저장소의 상태를 추척해야만, 다시 말해 동기화해야만 자신 외의 다른 팀원들이 자신이 추가한 작업을 받아볼 수 있다. 따라서, 로컬 저장소의 상태를 원격 저장소에 밀어넣는(push) 과정이 필요하다. 상단 우측의 “Push” 버튼을 눌러 해당 과정을 수행한다.

    Push Remote

  15. 로컬 저장소와 원격 저장소가 연결되는 첫 단계에서 로컬과 원격의 상태가 다른 경우 “Force Push”가 부득이 필요한 경우가 발생하는데, 이 경우에는 초기화 시의 편의를 위해 “Force Push”를 그대로 수행한다. 이 경우, 원격 저장소의 내용은 모두 사라지고 해당 내용이 로컬 저장소의 내용으로 대체된다. 파괴적인 작업이므로 정말 필요하지 않은 경우에는 “Force Push”를 함부로 사용해서는 안 된다.

    Force Push

  16. 이전 단계와 달리 로컬 저장소와 원격 저장소가 하나의 그래프로 합쳐진 것을 볼 수 있다.

    After Pushed

  17. 이제 본격적으로 게임에 들어갈 코드 또는 데이터를 추가할 시간이다. 우선 Unity 프로젝트를 생성할 때 자동으로 생성된 각종 설정 파일들을 로컬과 원격 저장소 모두에 추가해보자. Git은 로컬 저장소에 추가되기 전에 “Staged Files”라는 중간 단계를 두고 있다. 코드나 데이터가 머무는 일종의 무대(stage)라고 기억하면 편하다. 여기에 파일이 추가된다고 해서 바로 파일이 저장소에 들어가는 것이 아니라, 파일을 추가하기 위해서 반드시 거쳐야 하는 중간 단계로서의 공간인 것이다. “Stage all changes”를 클릭해 모든 변경 사항들을 “Staged Files”에 추가한다. Git에서는 이 동작을 추가(add)라고 부른다.

    Staged Files

  18. 다음으로, “Staged Files”에 추가된 모든 파일을 로컬 저장소에 실제로 넣을 시간이다. Git에서는 이 동작을 커밋(commit)이라고 부른다. 커밋을 위해서는 기여자가 정확히 어떤 작업을 수행했는지 기록하기 위해 커밋 메시지(commit message)를 입력하게 되어있다. 본래는 첫 문장을 커밋 메시지의 제목에 해당하는 요약(Summary)으로, 다음 줄부터는 설명(Description)으로 나뉘게 되지만, GitKraken은 이 둘을 별도로 입력할 수 있는 인터페이스를 제공한다. “초기 설정 파일 추가(Add initial settings)”라고 적어넣고 설명은 생략하도록 하자.

    Commit

  19. 커밋 이후에는 방금 추가한 설정 파일들이 로컬 저장소에 추가된 것을 확인할 수 있다. 유의할 점은, 여기서 추가된 파일들은 원격 저장소가 아니라 로컬 저장소에 추가되었다는 사실이다. 이렇게 되면 해당 파일들은 아직 다른 팀원들이 접근할 수 있는 상태가 아니다. 상단 우측의 “Push” 버튼을 눌러 로컬 저장소의 변경 내역을 원격 저장소에 적용하도록 하자.

    After Commit

  20. 원격 저장소에도 설정 파일들이 추가되었다. GitHub 프로젝트 페이지로 돌아가도 해당 파일들이 추가된 상태를 확인할 수 있다. 이제 나머지 팀원들은 단순히 “Pull” 버튼을 누름으로써 해당 변경 내역들을 다운로드 받을 수 있다. “Push”가 자신의 변경 내역을 밀어넣는 동작이라면 “Pull”은 다른 기여자가 공통된 원격 저장소에 추가한 변경 내역 모두를 끌어와 자신의 저장소에 적용하는 동작이라고 할 수 있다.

    After Pushed End

  21. 자, 이제 게임 파일을 추가하고, 변경하고, 또는 삭제하는 작업을 수행할 때마다 형상 관리 도구는 어떤 파일이 추가되고, 변경되고, 또는 삭제되었는지 모두 추적할 것이고 각 변경 내역을 추가(add), 커밋(commit)하도록 지원해줄 것이다. 이제 원격으로 안전하게 게임이 저장된 상태로 멋진 게임을 만들어보자!

    Remove Empty Prefab

Unity에서 형상 관리를 할 떄 유의할 점

  1. .meta 파일은 Unity가 해당 파일에 대한 각종 정보를 따로 저장하기 위한 메타 파일이다. 작업자는 항상 이 .meta 파일이 Unity 내에서 추가한 파일 외에 자동으로 생성되었는지 확인해야 한다. 그렇지 않으면, 다른 팀원이 해당 파일을 Unity에서 열 때 또 다른 .meta 파일이 생성되게 된다. 이러한 중복 파일 추가는 변경 내역이 충돌하는 원인이 된다. Unity 내에 작업을 추가한 뒤에 씬을 저장하거나 Unity 창을 닫는 식으로 아직 생성되지 않은 .meta 파일들을 안전하게 생성할 수 있다.
  2. Unity에서는 Unity 자체의 형상 관리 목적으로 Unity Collaborate라는 도구를 제공한다. 하지만 저자는 이 도구를 업무나 게임잼에서 사용한 적이 없고 해당 도움말은 Git과 Unity를 활용하는 방식만을 소개하는 것을 목적으로 하기 때문에 이는 본문이 다룰 범위를 벗어난다.

해당 도움말을 사용할 때의 유의할 점

  1. 본문은 Git, Unity, GitKraken 등 제한된 조합에 대한 구체적인 설명이기 때문에 다른 형상 관리 시스템(e.g. Subversion)이나 도구(e.g. SourceTree)를 사용하는 경우에는 다른 웹상의 문서를 참고해야 한다.
  2. 하지만 추가(add), 커밋(commit)과 같은 동작은 Git이라는 형상 관리 시스템에 종속되기 때문에 다른 형상 관리 도구를 사용하더라도 동일하게 적용된다.
  3. 본문은 형상 관리 시스템과 도구를 사용할 때 발생할 수 있는 모든 상황들을 다루고 있지 않다. 때문에 “Pull”을 할 때 작업 내역이 충돌(conflict)한다거나, 작업 내역의 더 효과적인 관리를 위해 PR(Pull Request)를 사용한다거나 하는 기능은 고급 기능으로 간주하고 본문에서 제외했다. 필요한 기능들은 다른 문서를 통해 학습할 것을 권한다.

더 읽어볼 것들

  1. Pro Git 한글화 문서
<끝>