로그인

회원가입 | ID/PW 찾기

연재

게임 개발에 사용되는 도구들 ③

게임 프로그래머 문기영의 ‘게임 프로그래머 이야기’ 13화

ProgC 2015-04-10 16:30:00

지난 연재에서 두 편에 걸쳐 게임 개발에 사용되는 개발 도구에 대해 알아보았다. 이전에 소개했던 개발 도구가 기획자 등 다른 직군도 사용하는 것이었다면, 이번에는 좀 더 프로그래머들에게 꼭 필요한 개발 도구를 알아보고자 한다.

 

 

■ 분산 빌드(Distributed Build)

 

옛날에 게임을 만들 때는 혼자서 개발이 가능했지만 현재  높은 수준의 게임들을 개발하기 위해서는 한 명의 프로그래머가 만드는 건 거의 힘들다고 봐야 한다. 게임에 필요한 에셋 데이터 제작을 제외로 하더라도 작성해야 하는 소스 코드의 양이 매우 크기 때문이다.

 

※ 노트: 에셋(Asset)이란 게임에 필요한 그림, 사운드, 파라메터 데이터와 같은 게임 코드를 제외한 데이터를 의미한다.


소스 코드를 작성하고 나면 컴퓨터에서 돌아가는 프로그램으로 만들기 위해 컴파일 과정을 거치게 된다. 이 때 소스 코드의 양이 많으면 컴파일 시간이 매우 오래 걸리게 된다.

 

소스 코드를 컴파일 해서 컴퓨터가 이해할 수 있는 코드로 변환한다

 

※ 노트: 컴파일러(Compiler)를 통해 원시 프로그램으로부터 목적 프로그램을 만들며, 이때 실행 가능한 프로그램 형태로 만들어 주는 과정을 빌드(Build)라고 한다.

컴파일러는 소스 코드를 컴퓨터가 이해할 수 있는 형태로 바꾸어 주는데, 이러한 컴파일러 역시 하나의 컴퓨터 소프트웨어다.

 

※ 노트: 컴파일러와 같은 컴퓨터 프로그램 역시 프로그래머가 만들 수 있다. 이것에 관한 자세한 내용은 “컴파일러 설계” 홍릉과학출판사, 김상욱 저 혹은 “컴파일러 : 원리, 기법, 도구” 교보문고, Alfred V. AHO, Ravi Sethi, Jeffrey D. Ullman 저를 참고하길 바란다.

이 컴파일러는 프로그래머가 작성한 소스 코드를 해석해서 컴퓨터가 이해할 수 있는 형태로 변환하는데 이 소스 코드의 양이 너무 많으면 컴파일러가 컴파일 하는데 많은 시간을 필요로 한다. 그렇다면 얼마나 많은 양일까?

 

● 퀘이크3: 30만 라인

● 언리얼 엔진3: 2백만 라인

 

코드의 크기는 아래 노트에서 참고하길 바라며 일반적으로 프로그래머들 사이에서 1만 라인의 코드를 스스로 작성할 수 있을 정도면 ‘초보 딱지는 막 뗀 수준’이라고 한다.

 

※ 노트: 코드의 크기 출처는 //www.informationisbeautiful.net/visualizations/million-lines-of-code

언리얼 엔진3가 약 2백만 라인 코드인데 이것이 어느 정도인지 실감이 안될 것이다. 1백만 라인의 코드를 A4용지로 뽑으면 18,000페이지 정도의 양이다. 실로 어마어마한 양이다. 이것들을 우리가 사용하는 컴퓨터에서 컴파일 해야 하는데, 아무리 컴퓨터가 빨라졌다고 하더라도 코드의 크기가 커지면 커질 수록 속도가 늦어진다.

 

코드의 크기가 클때 속도가 늦어지는 이유는 컴파일 과정이 단순히 소스 코드를 읽는 과정이 아니기 때문이다. 컴파일러가 소스 코드를 분석해서 다른 코드로 변환하는데, 이 작업들이 만만치 않다. 게다가 소스 코드가 여러 개의 파일로 분산 되어 있는데, 이것들을 처리하려면 중간에 파일 I/O 과정도 필요로 하게 된다.

 

※ 노트: I/O는 입출력(Input/Output)의 약자이며 컴퓨터가 어떤 처리를 하기 위해 데이터를 입력할 때 데이터를 입력하고 이러한 데이터를 알고리즘에 의해 가공한 후 모니터나 프린터로 결과를 내는 것을 출력이라고 한다. 

 

소스 코드를 컴파일 하기 위해서는 파일에 저장된 소스 코드의 내용을 메모리로 읽어야 하는데, 대부분 파일은 디스크에 저장되어 있다. 컴파일 과정에는 디스크에 저장된 파일을 열고/닫는 작업이 속에 있어 파일이 많으면 속도에 큰 영향을 준다. 물론 이러한 파일 I/O를 줄이기 위해 속도를 향상 시키는 방법도 존재하는데 이것은 여기서 논외로 하겠다.

 

예를 들어 소스 코드 5개가 있다고 치자.

 

a.cpp

b.cpp

c.cpp

d.cpp

e.cpp

 

하나의 파일을 컴파일 하는데 1시간 정도가 소요된다고 치면 5개니까 5시간을 필요로 한다. 

 

하나의 컴퓨터에서 5개의 파일을 순차적으로 처리하는 모습

 

※ 노트: 현재 우리의 컴퓨터는 CPU가 하나만 있다고 가정하고 있다.

이것을 좀 빨리 처리하는 방법이 없을까? 예를 들어 a, b, c, d, e 각각의 파일들을 컴퓨터1, 컴퓨터2, 컴퓨터3, 컴퓨터4, 컴퓨터5가 각각 하나의 파일을 컴파일 하는 것이다.

 

컴퓨터 5대가 동시에 파일 하나씩 컴파일 하고 있다!

 

이렇게 소스 코드를 여러 대의 컴퓨터로 분산해서 컴파일 하면, 모든 작업을 끝내는 데 1시간이면 된다.

 

※ 노트: 물론 링크하는 과정은 독자 분들이 쉽게 이해하기 위해 생략했다.

이렇게 작업할 것을 여러 컴퓨터로 나누어서 작업하는 것이 분산 컴퓨팅의 핵심이며, 앞서 살펴본 것이 분산 빌드이다.

 

여기서 예를 들고 있는 컴퓨터는 CPU가 하나라고 가정했는데, CPU가 하나 이상 있으면 그 개수만큼 더 효과적으로 이 작업을 수행할 수 있다.

 

필자의 컴퓨터는 CPU가 8개 있으므로 더 빠른 빌드가 가능하다

 

CPU가 많으면 하나의 컴퓨터에서도 효과적으로 빌드가 가능하지만, 최근에 출시 되고 있는 높은 성능의 게임을 개발하기 위해서는 빌드를 위해 더 많은 컴퓨터가 필요하다. 그렇지 않으면 컴파일만 하는데 몇 시간을 소비할 수도 있다!

 

특히 컴파일 시간이 길어지면 프로젝트를 진행 하는데 있어서도 매우 안 좋다. 왜냐하면, 최근의 개발 추세인 반복(Iteration) 과정이 느리게 되면 코드를 수정하고 확인하는데 있어 두려움이 생기기 때문이다. 특히 게임 플레이에 관련된 코드들은 그 수치를 수정하고 다시 게임을 테스트 해보는데 까지 걸리는 시간이 짧아야 한다. 테스트까지 시간이 오래 걸리면 테스트 하는 횟수가 줄어들게 되고 결론적으로 좋지 않은 게임이 만들어 지기 때문이다.

 

※ 노트: 데이터를 외부로 빼놓는 프로그래밍 기법인 데이터 드리븐 프로그래밍이 있지만 모든 데이터를 외부로 빼놓는 것도 힘들 때가 있다. 이럴 때 컴파일 시간이 많이 걸리게 되면 결론적으로 테스트를 덜 하게 된다.

그렇다면 이러한 과정을 하나의 컴퓨터가 아닌 여러 컴퓨터를 이용할 수 있는 방법이 있지 않을까? 그것이 바로 분산 빌드를 도와주는 도구인 인크리디 빌드(Incredibuild)다.

 

※ 노트: 인크리디 빌드(IncrediBuild)는 분산 빌드를 지원하는 도구로써 //www.incredibuild.com/를 참고하면 더 자세한 내용을 알 수 있다.

이 도구를 사용하면 앞서 알아본 것처럼 여러 대의 컴퓨터를 사용해 소스 코드를 나누어서 컴파일한다.

 

인크리디 빌드를 사용해 분산 빌드를 하는 모습. 출처 : //blog.nettention.com

 

재미있게도 이 분산 빌드의 약점(?)을 이용해 다른 사람의 업무를 방해하는 방법이 있다. 그 핵심은 누군가 빌드를 하면 다른 사람의 컴퓨터 리소스를 일부 가져다 사용한다는 점이다.

 

누군가 프로젝트를 지속적으로 리빌드 하면 다른 사람의 컴퓨터 리소스를 지속적으로 사용하게 된다. 이렇게 되면 다른 사람의 컴퓨터를 느리게 만들 수 있다. 리빌드는 프로젝트를 처음부터 끝까지 다시 빌드 하는 것인데, 프로젝트의 크기에 따라 많은 시간이 걸리게 된다. 그리고 리소스를 빼앗기는(?) 다른 동료의 컴퓨터까지 느리게 만든다.

 

※ 노트: 필자는 이런 것이 “가능하다”라는 것을 보여주고 싶은 것이지 실제 동료가 의도적으로 계속 리빌드를 하면 핵꿀밤을 선사할 것이다!!

 

■ 빌드 머신(Build Machine)

 

프로그래머가 작성한 소스 코드, 디자이너가 그린 기린 그림, 사운드 디자이너가 만든 웨이브 파일, 기획자가 만든 파라미터 데이터 파일들이 한 곳에 모여 실행 가능한 컴퓨터 소프트웨어를 우리는 게임이라고 한다.

 

이렇게 게임 하나를 만들기 위해서 필요한 데이터가 있고, 실행 가능한 상태가 되기 위해 절차적으로 실행해야 하는 단계들이 존재한다. 그러한 단계들을 처음부터 끝까지 자동으로 실행시켜주는 것이 바로 빌드 머신이다.

 

프로그래머가 소스 코드를 작성하면 컴파일러를 통해 오브젝트 파일로 변환하며 ,그래픽 디자이너들이 그려낸 그림들을 하나의 파일(스프라이트 시트 혹은 아틀라스 이미지)로 만들기 위해 패킹을 하기도 한다. 또, 오디오 디자이너가 만든 웨이브 파일들을 MP3 형태로 변환을 한다거나 하는 작업들이 존재할 수 있다. 

 

이러한 작업들은 회사 마다 다르며, 프로젝트를 어떻게 만들어 나가느냐 에 따라서 다르다. 그리고 이러한 작업들은 변경 사항이 하나 생기면 처음부터 끝까지 차례대로 실행해야 한다.

 

이 작업들은 개인 혹은 소규모 게임 개발팀의 경우 수동으로 하지만, 대규모 게임의 경우는 단계들도 많고 사람이 하게 되면 실수할 가능성도 있으며 업무 시간에 할 수 없는 경우(예를 들어 프로젝트 전체 리빌드. 보통 새벽 시간에 하게 된다.)가 있기 때문에 자동화 시킨다.

 

이러한 작업들을 쉽고 편하게 자동화 시켜주는 도구가 바로 빌드 머신이다. 빌드 머신은 Jenkins, ANT, Maven가 있고 필요에 따라서는 회사에서 직접 프로젝트를 빌드하는 소프트웨어를 만들어서 쓰는 경우도 있다.

 

※ 노트: Jenkins는 //jenkins-ci.org 를 참고하도록 하자

※ 노트: ant는 //ant.apache.org 를 참고하도록 하자

※ 노트: Maven은 //maven.apache.org 를 참고하도록 하자

 

■ 디버거(Debugger)

 

컴퓨터 소프트웨어에서 프로그램이 오동작 일으키는 것을 ‘버그가 났다’고 표현하는데 놀랍게도 이 표현은 실제 사건에 기반한다.

 

컴퓨터 최초의 버그

 

옛날 컴퓨터는 매우 컸고 열이 많았는데, 나방이 날아다니다가 컴퓨터 속에 끼어들어 컴퓨터가 오동작을 일으킨 사건이 벌어졌다. 그 이후로 컴퓨터 소프트웨어에서 오동작을 일으키는 모든 것을 우리는 버그라고 한다.

 

그리고 이러한 버그를 잡기 위해서 사용하는 도구를 디버거(Debugger)라고 한다. 디버거가 존재하는 이유는 컴퓨터가 동작하고 있을 때 내부적으로 어떤 계산을 하고 있는지 우리 눈으로 보여주지 않기 때문이다. 계산 식이 올바르다고 하더라도 계산 식에서 사용하는 데이터의 값이 잘못된 값을 가지고 있다면 결과적으로 계산 결과가 의도하지 않은 결과를 내뱉는다.

 

때문에 디버거가 이러한 값들을 보여주거나 중간에 변경이 가능하게 해준다. 또한 컴퓨터 프로그램은 프로그래머가 작성한 순서대로 명령어를 수행하는데, 이 순서를 화면에 보여주거나 바꿀 수 있게 해준다.

 

비주얼 스튜디오의 디버거 기능을 사용해 중단점을 걸어 놓은 화면

 

data는 초기 값으로 1을 가지며 여기에 3을 더해 4를 얻고 여기에 10을 곱해 최종적으로 data는 40이 된다. 중요한 것은 이러한 내용은 컴퓨터 프로그램이 실행 중일 때는 전혀 보이지 않는다는 점이고 화면 결과 40만 화면에 나타난다.

 

프로그램을 수행한 결과

 

프로그램이 원하는 결과를 출력하지 않으면 프로그램에 버그가 있다는 것이고 이것을 찾아내 해결하는 것 또한 프로그래머가 하는 일이다. 앞서 살펴본 코드는 매우 간단하기 때문에 누구나 코드를 바로 읽고 이해할 수 있지만, 코드가 2백만 라인 정도 되면 어디에서 문제가 생기는지 찾아내는 것 자체가 매우 큰 일이 될 수 있다. 이럴 때 디버거를 이용하면 된다.

 

어셈블리어 코드도 볼 수 있다

 

프로그램의 함수 호출 순서를 볼 수 있다

 

함수 호출 순서를 보면 wmainCRTStartup()함수가 최초로 실행되고, _tmainCRTStartup(), wmain, funcB순서로 호출한 뒤 funcB 내부에서 funcA를 호출한 것을 확인할 수 있다. 만약 버그가 발생한 지점이 현재라면 우리는 2백만 라인의 코드를 다 뒤져볼 필요 없이 funcA만 보면 된다.

 

이처럼 디버거를 이용하면 프로그램이 실행될 때 내부 구조를 훤히 살펴볼 수 있다.

 

 

■ 물리 디버거(Physics Debugger)

 

마지막으로 알아볼 것은 물리 디버거다. 최근 게임들은 게임 내부에 물리 엔진을 탑재해 물리 현상을 표현하고 있는데 물리 엔진에서는 기본적으로 간소화된 모델을 사용한다. 예를 들어 화면에 보이는 캐릭터는 매우 많은 폴리곤을 사용하지만, 실제로 물리 엔진에 사용되기 위해서는 보통 간략화한 박스나 캡슐 형태로 사용하는 경우가 많다.

 

좌측은 실제 게임 화면. 우측은 디버거에서 물리 모델링을 표시. 출처 : Havok 엔진

 

최근에 많이 사용되는 유니티5, 언리얼 엔진4가 있지만 물리 디버거에 있어서 만큼은 하복 엔진을 따라 오기가 힘들다. 실시간으로 물리의 움직임이 어떻게 되는지 확인할 수 있고 강체의 속도를 보거나, 다양한 설정으로 물리연산을 확인할 수 있다.

 

※ 노트: 하복의 물리 디버거의 콘셉트는 다른 게임 엔진들도 본받아야 한다고 본다.

물리 엔진을 사용한다는 것은 물리 계산에 필요한 수치 값들도 모두 제대로 설정해주어야 한다는 뜻이다. 실제 환경과 비슷하게 물리를 구현하려면 중력 값이 9.8 m/s2, 질량, 마찰 계수와 같은 것들을 설정 해야 한다.

 

이때 중요한 점은 현실 세계에서 사용하는 수치와 완전히 같게 설정하는 것은 거의 불가능에 가깝다는 점이다. 우리가 사용하고 있는 수식 역시 모두 현실 세계를 가장 가깝게 모델링 한 것에 불과하기 때문이다.

 

※ 노트: 물리 모델의 한계도 한계지만 현실 세계를 컴퓨터 안에 그대로 구현해 넣는 것은 그냥 그 자체로 불가능하다. 왜냐면 현실 세계는 연속적이지만 컴퓨터 세계는 이산적이기 때문이다. 컴퓨터는 그 한계가 분명하게 있기 때문에(메모리의 크기, 연산 속도의 한계) 현실 세계에 있는 것을 그대로 표현할 수 없다.

지금까지 3화에 걸쳐 게임 개발에 사용되는 도구들에 대해 알아 보았다. 필자가 다루지 않은 도구들도 매우 많다. 그도 그럴 것이, 개발 도구의 필요성은 개발하는 게임의 종류, 개발 팀의 규모 등에 따라 다른 경우도 많기 때문이다.

 

게임 회사에 취업하면 이러한 도구 사용법을 배워서 게임 개발에 필요한 리소스를 만든다 거나 프로그래머라면 이러한 도구들을 제작해야 한다. 게임 프로그래밍 못지 않게 게임 도구를 만들어 내는 것도 매우 중요한 작업임에도 불구하고, 국내에는 자료도 많지 않고 (사실 게임 개발 도구 제작법은 외국에도 자료가 많지 않다.) 전담해서 업무를 진행하는 경우도 찾아보기가 드물다.

 

필자가 설명한 것 외에도 인하우스(In-house) 툴이라고 하여 게임 개발사 내부에서 사용하는 도구들이 존재한다. 좋은 도구가 있다면 도구의 사용으로 인해 얻는 이점을 서로 공유해서 게임 개발에 더 도움이 되는 방향으로 업계 전반적으로 발전하기 위해 노력했으면 좋겠다.

 

다음 화에서는 필자가 EA Canada 취업하면서 겪게 된 일과 경험에 대해 이야기 해보도록 하겠다.

  • 게임 개발에 사용되는 도구들 ①

  • 게임 개발에 사용되는 도구들 ②

  • 게임 개발에 사용되는 도구들 ③

  • [게임 프로그래머의 길] 해외 취업의 길? 어느 날 날아온 ‘우연한 기회’