HTML5로의 이행 - 1부
작성자: 데이비드 갈레아노, 던컨 텝스 (David Galeano, Duncan Tebbs) 작성일: 2013년 2월 7일
이 글은 3 부작 중 제 1 부로, 전직 크리테리온의 노련한 콘솔 개발자들이 HTML5 개발로의 대세 변화 과정에 대해 논하고 있다. C 에서 작업할 때와 자바스크립트에서 작업할 때의 차이점, 또 브라우저 환경에 따라 부딪치게 되는 난관들에 대해 설명하고 있다.
모든 플랫폼이 그렇듯이 HTML5 에 대해서도 혹평을 하는 사람들이 있다. 이중에는 정당한 평도 있지만 일부는 루머이거나 지난 정보에 근거한 것이다. 반면 업계의 성공한 많은 비즈니스 리더들이 HTML5 를 지원하고 있으며, turbulenz.com1 의 많은 게임들은 HTML5 야말로 오늘날 고급 게임에 적합한 프로그램임을 증명하고 있다. 여기서 우리가 HTML5 를 지원해야 하는 이유를 자세히 살펴보려로 한다.
HTML5 관련 표준은 고급 게임이 웹 기반에서 실행 가능하도록 하는 플랫폼으로서 빠르게 성장하고 있다. 이렇게 웹 표준을 타깃으로 만든 게임은 다양한 컨텍스트로 구현할 수 있으며, 최신 디바이스와의 연결성이 좋은 것은 물론 하드웨어까지 활용할 수 있는 장점이 있다.
터뷸렌즈(Turbulenz)에서는 많은 연구 인력과 엔지니어들을 투입하여 웹 기반의 고성능 게임을 개발해왔다. 콘솔 게임 기술을 개발한 경험이 풍부한 게임 개발자의 관점에서 HTML5 및 관련 기술들에 접근하여 정확성과 높은 성능을 구현해내고 있다.
이 글에서는 콘솔에서 웹으로 이동하면서 우리가 경험한 것들, 즉 잘된 사례들과 이 기술들을 사용한 시기, 최적화 전략, 문제 대응 방법에 대해 논하고자 한다.
터뷸렌즈를 사용해서 제작한 게임들 중 일부는 게임 네트워크인 turbulenz.com2 에서 해볼 수 있다. 이것들은 우리의 HTML5 플랫폼 및 인프라를 사용하여 온라인 게이머들도 고품질 3D 게임을 즐길 수 있도록 제작한 것이다. 당사는 2009 년 초에 일렉트로닉 아츠(Electronic Arts)의 몇몇 디렉터들과 리드 프로그래머들이 모여 설립했으며, 현재는 세계적으로 우수한 엔터테인먼트사들의 개발자들과 사업가들이 모인 기업으로 성장하였다.
1 부에서는 현재 HTML5 의 대세와 게임 관련 기술들에 대해 다루고, 향후 게임 개발자들이 기대할 수 있는 개발 환경과 워크플로우(workflow)에는 어떠한 것들이 있는지 얘기하려고 한다.
게임 플랫폼으로서의 브라우저
브라우저는 새로운 OS 가 되어 많은 기회를 가져다 주었지만, 문제점들도 안고 있다. 과거에 게임은 전통적으로 고립된 상태에서 하는 것이었고, 많은 자원을 투입하여 기계의 최고 성능을 이끌어내는 것이 관건이었다. 또한 브라우저에서 사용하는 게임 코드는 다른 탭이나 윈도우즈에서 실행 중인 다른 게임이나, 해당 기기에서 실행중인 다른 모든 프로세스와 경쟁해야 한다.
어떤 점에서는 각각의 브라우저를 각기 다른 플랫폼으로 다루어야 마땅하다. 모든 브라우저에서 공통으로 가능한 일부 인터페이스도 있고 항상 사용 가능한 리소스도 있지만, 기능을 더욱 개선하기 위해서는 항상 런타임 특성을 점검하고 멀티플 코드 경로와 제 2 의 해결책(workaround)을 제공해야 한다.
브라우저와 브라우저 버전, OS 와 OS 버전을 다루는 테스트 매트릭스는 방대하다. 게다가 하드웨어 리소스는 네이티브 애플리케이션처럼 직접 엑세스할 수 없음에도 개발자들은 그래픽 드라이버 버그와, 이 드라이버와 인터페이스하는 브라우저 레이어의 버그 문제를 해결해야 한다.
브라우저 업데이트가 빨라지고 자동으로 업데이트되는 브라우저도 있다 보니, 테스트가 필요한 특정 지원 버전을 리스트로 만들어 관리하기는 어려워지고 있다. 터뷸렌즈에서는 항상 최신 버전의 브라우저로 작업을 하며, 많이 사용하는 브라우저 버전은 리스트를 만들어 관리하고 있다. 이 글을 쓰고 있는 지금 이 리스트에는 인터넷 익스플로러 8, 9, 10, 파이어폭스 3.6, 최근에는 사파리 5.1 과 맥 OS X, 최신 버전의 크롬까지 포함되어 있다. 우리는 느린 넷북부터 고성능 데스크톱에 이르기까지 다양한 하드웨어에서 Nvidia, AMD, 인텔 등 흔히 사용하는 비디오 카드들을 모두 사용하여 테스트한다.
브라우저의 상대적인 시장 점유율은 항상 유동적이고, 인구 구성과 일치하지도 않는다. 먼저 타깃 시장을 정하고 이 시장과 유사한 고객 그룹의 사이트에 해당하는 브라우저 스탯(stat)을 찾아내는 것이 더 바람직할 것이다.
개발 플랫폼으로서 브라우저는 다른 플랫폼에 비해 몇 가지 이점이 있다. 일반적으로 이터레이션(iteration)이 매우 빠른 것이 특징이다. (자바스크립트는 보통 실행 과정에 컴파일 단계가 없으며, 페이지를 즉각 리프레시(refresh)하여 최근 버전의 코드를 로드해 실행한다). 웹 개발자들은 디버깅과 프로파일링을 위한 다양한 도구를 사용해왔으며, 이는 효율적인 개발 환경 조성에 큰 도움이 되고 있다. 이에 대해서는 추후 다시 자세히 설명하기로 한다.
일반적으로 개발자들이 브라우저에 코딩을 할 때는 방어적으로 할 것을 권한다. 다양한 브라우저로 테스트를 해야 하며, 정기적으로 새 버전의 상태를 확인해야 한다.
게임 개발을 위한 자바스크립트
브라우저에서 사용할 수 있는 다목적 프로그래밍 언어는 하나밖에 없다. 자바스크립트가 그것인데, 공식적으로는 ECMScript 라는 이름으로 알려져 있다. 이 글에서 프로그래밍 언어에 대해 설명하려는 것은 아니지만, 우리가 C/C++ 기반에서 자바 스크립트에 접근했을 때 발견한 특징적인 현상들이나 예상 외의 현상들에 대해서는 고찰해볼 만한 가치가 있다.
특히 처음 C/C++에서 자바스크립트로 넘어가면서 개발자들은 여러 가지 도전 과제에 당면하게 된다. 자바스크립트의 구조는 C 와 비슷하지만 언어 자체는 기능적 언어인 리스프(Lisp)와 공통점이 더 많다. 클로저(closure)와 일급함수(first-class functions)가 있기 때문이다.
클로저는 매우 강력하여 비동기(asynchronous) 프로그래밍도 훨씬 쉽고 명확하게 할 수 있다. 그러나 개발자가 작업 과정을 정확하게 인지하지 않으면 교묘한 에러들이 발생할 수 있다.
예를 들어 루프(loop) 내부에 클로저를 만드는 것은 흔히 하는 실수이다. 해당 루프를 수행하는 중에 계속 변화하는 변수를 참조하는 것을 말한다. 이렇게 되면 클로저에서 참조한 변수가 클로저가 만들어진 시점이 아니라 실행된 시점의 값을 갖기 때문에 혼란을 초래한다.
자바스크립트에는 일급함수가 있어서 다른 함수에서 리턴되고 변수에 할당되고 딕셔너리에 저장되며, 파라미터(parameters)로 넘기는 것이 가능하다. 스트링(String)은 런타임에 함수로 컴파일될 수 있지만, 스트링이 알려지지 않은 소스에서 넘어와서 코드의 다른 부분도 방해할 수 있기 때문에 안전 문제로 이 방법은 추천하지 않는다.
자바스크립트는 객체지향적이지만 클래스가 없다. 자바스크립트는 컨스트럭터(constructors)가 있으며 프로토타입 중심의 상속(inheritance)을 한다. 객체는 키값(key-value) 딕셔너리처럼 모든 것을 네임(name)으로서 최적 상태로 저장하고 검색할 수 있다. 데이터를 저장하거나 검색하는 코드 네임의 오타 등 잘못된 네임으로 값에 접근하는 것 또한 흔히 하는 실수이다.
객체는 다른 객체의 프로토타입으로 배치될 수도 있다. 객체에서 속성(property)이 발견되지 않으면 런타임에서 프로토타입 객체를 점검할 것이다. 함수가 객체에 저장될 수 있고 객체들은 프로토타입을 공유할 수 있기 때문에, 프로토타입 메커니즘에 따르면 메소드(method)와 코드는 익숙한 방식으로 재사용할 수 있다. 함수도 객체처럼 작동하며 네임으로 속성을 저장하고 검색하는 데 활용될 수 있다.
자바스크립트 객체에는 디스트럭터(destructor)가 없다. 자바스크립트 런타임은 더 이상 참조할 값이 없으면 디스트럭션을 시작하고, 자바스크립트 코드는 디스트럭션이 되어도 전혀 를알림(notification)을 받지 않는다. 우리는 자바스크립트 코드에서 메모리 누수 (프로그램이 필요하지 않은 메모리를 계속 점유하고 있는 현상) 문제가 심각하다는 것을 발견했다. 일부 자바스크립트 프로파일러에서는 객체에 힙 스냅샷들(heap snapshots)의 카운트(counts)를 제공하기도 하는데, 이는 도움이 되기는 하지만 이렇게 하기 위해서는 객체가 리터럴이 아닌 (non-literal) 컨스트럭터로 만들어져야 한다. 이 때 이들을 구분하기위해 새로운 오퍼레이터가 필요하다. 일부 프로파일러에서는 또한 힙 스냅샷들에서 레퍼런스 트래킹(reference tracking)을 제공하기도 하는데, 이는 해당 객체가 가비지 컬렉트(garbage collect)되지 않은 이유를 밝히는 데 도움이 된다.
가장 좋은 사례로는 객체 소유(ownership) 정책을 분명하게 정의하는 방법을 추천한다. 이렇게 하면 주어진 객체의 참조값을 점유하는 (또는 내보내는) 코드가 어디에 있는지 찾아내기가 용이해진다.
자바스크립트는 스태틱 타입(static type)이 없기 때문에 프로그램이 다할 때까지 다양한 타입의 변수를 갖는 것이 허용된다. 또한 같은 오퍼레이션에서 다른 타입이 사용될 경우 일부는 자동 변환이 일어나기도 한다. 예를 들어 스트링에 숫자를 더해서 스트링으로 변환된 숫자의 스트링 병합(concatenation)을 일으킬 수도 있다. 이러한 에러는 찾기도 힘들고 성능에도 문제를 일으키게 된다.
※ 자세한 내용은 첨부(PDF)화일을 참고하시기 바랍니다.
|