Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

가장 저명하다고 생각되는 SWEng-GameDev 메일링 리스트와 기타 다른 여러 온라인 포럼에서의 토론결과 C++은 게임 개발을 위한 가장 좋은 선택이라는 결론이 나왔다. 다양한 종류의 언어가 있고, 그 중 몇몇은 열렬한 지지를 받기도 하지만, 실제 언어를 선택해야될 경우 C++이 압도적으로 선택되어지고 있다. 그러나 어떠한 온라인 토론에서든지 이에 대한 반대 의견이 있으며, 이러한 반대의 견을 받아들이고 재 토론하는 것은 토론을 발전시키는 원동력이 된다.

C++ 언어는 좋은 평가를 받지만 두가지 정도에 있어서 공격을 받기도 한다. 하나는 low-level 요소를 다루기에 언어의 추상화 단계가 (쓸데없이) 높다라는 점과 C에 비해서 일관성이 결여된다라는 주장이다. 이 주장이 말하는 바는 C로 더 효과적인 코드를 만들어 내기가 쉽다라는 점이다. C++은 높은 수준에서 정보를 추상화 할 수 있는데, 이는 코드를 읽고 해석하는것을 비능률적으로 만들 수 있다. 예를 들어서 C에서 다음 코드를 읽는다고 가정해 보자.
a = b+c;
우리는 a,b,c가 primitive 타입이라는 것을 알 수 있으며, 매우 간단하게 몇 줄의 어셈블리(:12) 코드로 변환할 수 있다. 그러나 C++에서는 overloaded로 인해서 a,b,c가 크기를 알 수 없는 객체가 될 수 있다. 이는 더 많은 메모리와 시스템호출 기타 자원을 소매하게 만든다. 이러한 문제를 해결하는 유일한 방법은 컴파일러로 하여금 C++언어의 여러가지 기능을 지원하지 않도록 하는 것 뿐이다.

저수준의 언어와 비교하는 것과는 반대로, 다른 한편에서는 고수준 언어로써의 C++을 비판한다. C++은 고수준 언어이면서도, C와 이전 C++과의 하위 호환에 지나친 부담을 가진 관계로 ANSI/ISO 표준에 늦게 대응하고 있다고 비판한다. 하위 호환에 대한 부담감 때문에, 현대적인 언어가 가지고 있는 gabage collection, aspects, closures, reflection과 concurrency 등을 지원하지 못하다고 있다. C++은 .h include 파일과 .cpp 파일이 분리되는 구시대적인 방식을 여전히 사용하고 있다. 그래서 프로그래머는 모든 함수에 대해서 선언정의를 분리하기 위한 파일을 만들어야 한다. 이러한 주장들에 의하면 게임은 C#, Eiffel 혹은 Objective Caml로 만들어져야만 한다.

양진영의 의견은 서로 대립되고 있다. 이말은 달리 해석해보자면, 성능에 민감한 코어부분은 C로 만들고 그렇지 않은 부분은 좀 더 고수준의 스크립트 언어로 게임코드를 만드는게 효율적일 수 있다는 얘기가 된다. 이를테면 C++은 저수준언어와 고수준언어사이의 어중간한 위치에 있는 모양새로 볼 수 있다.

그러나 이러한 불평과 불만에도 불구하고, C++은 성공하고 있다. 왜 C++인가? 이 언어는 성공을 계속이어갈수 있는 알수없는 비범함을 갖추고 있는 것인가 ?

이에 대해서 나름대로 분석을 해보았다. C++이 게임개발을 위한 언어로써 지배적인 위치에 있는건 사실이지만, 관성적인 측면이 상당부분을 차지한다. 당신이 경험있는 프로그래머를 찾고자 할때, 구루 수준의 C++프로그래머를 찾는것이 OCaml 프로그래머를 찾는것 보다 훨씬 쉽다. 콘솔게임을 개발해야 할경우에도 마찬가지다. Microsoft와 Sony 모두 C++ 컴파일러를 제공한다. 다른 언어를 통해서 개발하길 원한다면 스스로 컴파일러를 만들어야 한다. 만들어진 게임을 미들웨어와 연결시켜야 하는 경우를 생각해보자. 대부분의 게임 미들웨어 패키지 - Gamebryo, Havok, FMOD, SpeedTree, Unreal 엔진 - 는 C++로 만들어져있다. C++과 함께 가장 대중적인 언어라고 생각되는 C를 이용해서 개발할 때 조차도, 고립되는 경우를 생각해야 한다.

그러한 관성적인 것은 언어 외적인 측면이야 라고 무시할 수도 있을 것이다. 그러나 C++의 이러한 network_effect(:12)의 힘을 절대 무시할 수 없을 것이다. 예를 들어보겠다. Naughty Dog 은 Jak and Daxter - ps2에 관심 있다면 들어본 게임일 것이다. 우리나라에도 발매되었던 게임으로 2탄까지 꽤 인기를 누렸던 작품이다 - 게임을 GOAL(Game Oriented Assembly Lisp)라는 사내 LISP 언어를 이용해서 만들었다. 게임을 만들기 위해서 그들 자신의 컴파일러와 링커, 디버거를 만든데는 GOAL을 위한 뜻깊은 투자를 위한 뜻도 담겨있었다. 이 언어는 매우 효율적으로 훌륭한 게임의 제작이 가능하도록 만들어 지도록 지원했음이 분명하다. 그러나 후에 소니가 타이틀을 구매하기로 했을 때, Naughty Doc는 이미 만들어진 코드를 C++로 변환하라는 압력을 받았다. "Sony는 만들어진 코드를 그들과 그들의 다른 스튜디오가 공유하기를 바랬다" 라고 Naughty Dog의 리더 프로그래머인 Scott Shumaker는 압력의 이유를 말하고 있다.

그러나 이러한 외부적인 이유외에, 나는 C++이 Game개발에 있어서 가지는 타고난 강력함에 타겟을 맞추어서 설명하고자 한다. 이를 위해서는 왜, 그리고 어떻게 C++이 오늘날까지 발전을 해오고 있는지를 이해하는게 중요하다. C++은 C에서 만들어졌다. C++은 Unix 운영체제의 시스템 프로그래밍을 위한 언어로 만들어졌으며, 유닉스가 성공하는데 결정적인 역할을 담당했다. C는 매우 타이트한 언어다. C로 만들어진 함수는 거의 그대로 Assembly(:12)로 다시 읽을 수 있을 정도다.

C++은 이러한 C에 추상계층을 추가했다. C++은 C에 Simula(:12)에서 영감을 얻은 객체지향적 개념을 확대추가한 언어다. 큰 틀에서 보자면 C++은 C에 단지 class와 상속을 추가한 정도다. C++을 디자인한 Bjarne Stroustrup 는 그의 C++ FAQ에서 C++언어는 템플릿의 사용, 다형성, generic 프로그래밍 multiparadigm 프로그래밍 스타일을 지원하도록 개발 촛점을 맞추었다라고 말하고 있다.

C++은 multi-paradigm 개발을 지원하는 언어로, generic, imperative 그리고 객체지향 프로그래밍을 지원한다. 모든 C++ 프로그램은 특정한 문제를 푸는데 있어서, 이를 풀기위한 재사용 가능한 효율적인 모델로 쓰여질 수 있다. 반대로 C++은 그 자신의 성공의 피해자이기도 하다. 언어는 개발자나 고객이 필요로 하는 기능을 가진 라이브러리를 계속적으로 추가시켜 나간다. C++역시 그렇지만, 비지니스적인 측면에서 보면 몇가지 문제점을 가지고 있다. C++ 프로그래머를 구하는건 어렵지 않지만, C++의 특징 때문에, 프로그래머는 C++의 객체지향모델과 같은 저수준의 내용과 컴파일시간에 이루어지는 (비교적 최근에 추가된 기능인) template metaprogramming와 같은 것들을 동시에 이해해야 한다. 이러한 이해가 확실하지 않은 프로그래머의 손에 쥐어진 C++은 위험한 도구로 사용될 수 있다.

그러나 이러한 위험에도 불구하고 C를 대안으로 선택하는건 옳지 않다고 본다. 왜냐하면 그럼에도 불구하고 C++은 C보다 더 강력하고 더 안전하고 효율적인 언어이기 때문이다.

더 강력하다고 ? 모든 C로된 개임은 재사용을 위해서 함수포인터를 포함하는 자료구조를 유지하는 가상의 함수 테이블을 만들어야 한다. 객체지향을 흉내내야 하기 때문이다. C++은 객체지향코드를 만들기 위한 기능을 자체적으로 지원하고 있다. 불가능한 것은 없다. C로도 객체지향을 할 수 있으며, (아마도) 어셈블리어로도 가능 할 것이다. 그러나 언어가 자체적으로 지원하는것과 그렇지 않은 것은 차이가 있다. 언어가 자체적으로 지원할경우, 프로그래머는 좀더 자연스럽게 자신의 의도를 코드를 통해서 표현할 수 있기 때문이다. C에서 매크로를 만들어서 preprocessor를 돌리는 것보다 C++의 template metaprogramming을 하는 것이 훨씬 효율적이다. 또한 C++은 template를 이용한 STL(:12)과 같은 컨테이너와 알고리즘을 제공한다.

더 안전한가 ? C에서라면 종종 아래와 같은 매크로를 만들어서 사용할 것이다.
#define MAX(A,B) ( (A) > (B) ) ? (A) : (B) 

MAX(x++, 2)
이 매크로가 한번 확장되고 나면 x는 (의도하지 않게)2만큼 증가될 것이다. C++에서는 std::max() 와 같은 inline templatized 함수를 이용해서, 저런 불쾌한 문제를 해결하면서도 동일한 효과를 누릴 수 있다. C는 템플릿을 지원하지 않기 때문에 void 포인터를 가지는 구조체를 사용해야 한다. qsort() 함수에서 void 포인터를 사용하는 예를 찾아볼 수 있다. void *형을 사용한다는 것은 type-safety system의 장점을 버려야 한다는걸 의미한다. 이렇게 될경우 컴파일 시간에 에러를 잡지 못하고, 직접 돌려봐야 에러를 잡을 수 있게 되는데, 불안전한 프로그램을 작성할 확률을 높이게 된다. C는 Resource Acquisition is Initialzation (리소스를 획득하면서 초기화 하는)이 존재하지 않는다. Scope lock와 smart pointer도 사용할수 없으며, 더욱 자주 메모리와 다룬 자원이 세어나가는 경우를 만나게 된다.

더욱 효율적이다 !? C++ 컴파일러는 은 type-base 의 alias를 분석하고 명령을 저장하는 것을 허용한다. 일반적인 c 컴파일러는 이러한 일을 할 수 없다. (Type-Based Alias Analysis는 http://www.ddj.com/184404273 문서를 읽어보기 바란다). inlining는 C++컴파일러로 하여금 필요없는 함수호출을 줄이도록 해준다. 그러므로 함수호출로 인해서 소비되는 overhead를 줄일 수 있다. template와 같이 사용하게 될경우 C++은 효과적인 인라인코드를 자연스럽게 생성해준다 (템플릿을 사용할경우 코드의 양이 크게 늘어나는 문제가 발생하기도 했지만, C++컴파일러의 성능이 좋아지면서 대부분 해결되었다). C++이 std::sort()가 C의 qsort()함수보다 성능이 더 잘나오는 이유가 여기에 있다. 마지막으로 C++은 표준 라이브러리 컨테이너를 제공한다. 이걸 이용할 경우 개발자가 신경써야 할 것을 극적으로 줄여준다. 예를 들어서 STL(:12)를 이용해서 Hash Map을 구현할 경우, 20줄 내외면 될걸 (장담하건데) C로 비슷한 기능을 가진채로 구현하려면 1000줄은 넘겨야 할것이다. 성능또한 junior급의 C 프로그래머가 만든것 이상을 보장할 수 있다.

그렇다 나는 C보다 C++을 좋아한다. C++은 gameplay 코드와 핵심엔진의 효율적인 작성을 위한 더욱 높은 수준의 추상화를 지원해 주기 때문이다. 물론 C와 비교해서는 그렇지만 다른 더욱 최근에 발표된 언어들에 비해서는 몇 가지 결함을 가지고 있음을 알지만, 실제 이러한 결함이 크게 문제 되지 않고 있다. 고백하자면 나는 그러한 언어들의 고수준의 여러가지 기능과 철학을 충분히 활용 할 만한 능력을 가지고 있지 못하다. 나는 C++을 이용해서 코드를 만들 때도 많은 부분을 proecedural 방식으로 작성한다. 오히려 그게 더 명확하고 효율적이고 빠른 코드를 만드는데 도움을 줄 경우가 많기 때문이다. C++은 프로그래머에게 적당한 타협점을 만들어주는 언어다. 그리고 gabage collection을 통해서 얻을 수 있는 이익에 대해서도 매우 회의적이다.

그러나 C++을 선택하는 가장 중요한 이유는 C++이 빠르다라는 점 때문이다. 비슷한 능력을 가진 개발자가 코드를 만들었다고 가정했을 때, C++이 다른 고수준의 언어들 보다 더 빠른 코드를 만들어 낸다는 것은 의심의 여지가 없다. 특히 게임의 핵심엔진을 만들 때 이러한 차이는 두드러진다. gampleplay code의 경우에는 결과가 달라질 수 있다. gameplay 부분은 디자인, 고객 요청의 변화등에 따른 요구에 빠르게 대응할 필요가 있는데, C++은 상대적으로 느릴 수 밖에 없다.

빠른 개발주기를 가져가기 위해서, 당신은 간단히 컴파일 될 수 있거나, 혹은 컴파일 자체를 필요로 하지 않은 간단한 언어가 있었으면 할 것이다. 또한 프로그램의 리스타트등의 작업없이 코드의 변화된 부분을 게임내에서 즉시 확인하고 싶어할 것이다. C++이 가지는 포인터라든지 까다로운 int, float, 문자열 작업, 컨테이너등을 사용하고 싶지 않을 것이다. 이들은 gameplay 코드를 만드는데에는 지나치게 부담이 되는 요소들이다.

이런 부분은 Lua를 이용해서 해결해 보기 바란다. 이 off-the-shelf 스크립트 언어는 많은 게임회사에서 C++과 함께 널리 사용되고 있다. Lua는 lightweight, dynamically type를 지원하는 interpreted 언어다. 또한 garbage collection은 메모리할당과 누수가 더 이상 이슈가 되지 않을 정도로 훌륭하게 작동한다.

이렇게 한개 이상의 언어가 사용하는 것에 대해서 거부감을 가지는 개발자도 있겠지만 (나도 매우 싫어한다) 고정관념은 버리라고 있는 것이다. 게임엔진은 C++로 만들고 gameplay는 Lua로 만들어라. 내가 생각하는 가장 좋은 방법이며, 많은 게임들이 이렇게 만들어 지고 있다. 블리자드의 wow같은 경우에도 각종 add-on과 UI들이 lua로 만들어 졌다. 필자가 생각하기에 앞으로 10년내에 게임개발과 관련되어서 C++을 능가할 수 있는 언어가 나올거 같지 않다. C#과 Mono는 이 부분에 있어서는 Lua의 발뒤꿈치도 따라가지 못하고 있다. 당분간 게임개발을 위한 최상의 언어조합은 C++/Lua가 될 것이다.

  1. http://www.lua.org
  2. http://redwiki.net/wiki/wiki.php/Lua
keyword : Script Lua C++ game