[기고칼럼] 게임 클라이언트의 '과부하' 원인, "이것 때문입니다."

칼럼 | 박태학 기자 | 댓글: 24개 |



[▲ 문대경 아이펀팩토리 대표]
인벤에서는 게임업계 1.5세대 인물로 안정적인 게임서버엔진인 아이펀 엔진을 개발한 아이펀팩토리의 문대경 대표님을 모시고 서버 관련 컬럼을 기고 받게 되었습니다.

문대경 대표는 1999년 넥슨 입사 후 2005년까지 넥슨에서 출시되는 다수의 프로젝트 서버 프로그램을 책임졌으며, 현재 아이펀팩토리의 대표로 게임서버 엔진인 '아이펀엔진'을 개발하였습니다.

아이펀팩토리가 개발한 '아이펀 엔진'은 네트워크, DB처리, 분산 시스템 등 게임 서버 구현에 필요한 필수 기능을 손쉽게 구현해 개발 시간 단축을 돕는 모바일 게임 서버엔진입니다.

그 두 번째 시간으로 클라이언트 프로그래머와 서버 프로그래머, 비슷해 보이지만 서로 다른 고민을 가진 사람들이란 타이틀을 가지고 내용을 이어가겠습니다.

* 본 내용은 본지의 편집방향과 일치하지 않을 수도 있습니다.


클라 프로그래머와 서버 프로그래머. 비슷해 보이지만 서로 다른 고민의 사람들. Part 1

지난 칼럼 이후 많은 분들이 나의 지난 직장 생활이 연애 한 번 못 해 볼 정도로 힘들었는지 몰랐다며 위로를 보내주셨다. 그러나 사실 연애가 문제가 아니라 당시에 머리가 너무 빠져서 탈모치료까지 받고 있었다는 것을 아는 사람은 몇 없다.



▲ 으흐흑!


그리고 비단 나뿐만 아니라 게임 회사의 프로그래머들은 나처럼 골머리 앓다가 조기에 탈모가 오는 경우가 더러 있다. 그럼 대체 무엇이 그들의 청춘을 힘들게 하는 걸까?

당연한 이야기겠지만, 프로그래밍에 있어 성능의 병목이 되는 것이 있다. 그런데 클라와 서버의 경우가 다르다. 병목은 작업이 원래 복잡해서 병목인 경우도 있고, 작업 자체는 단순하지만 처리해야 되는 양이 워낙 많아서 병목이 되는 경우도 있다. 그럼 클라와 서버의 어떤 작업이 성능상의 병목이 되고, 어떻게 그것들을 사전에 확인하는지를 두 번으로 나눠서 살펴보도록 하겠다. 먼저 이번 편에서는 클라에서 주로 처리하는 작업에 대한 내용을 살펴보고 다음 편에서는 서버 쪽 작업을 살펴보도록 하겠다.


Part 1. 클라에서의 병목: 화면 만들어내기와 AI, 그리고 물리 엔진

1) 가장 빈번하면서 쉽게 병목이 되는 작업: 화면 만들어내기

예전 배불뚝이 TV 에서부터 최신 LED 디스플레이까지, 우리가 일상적으로 사용하는 디스플레이들은 일정 시간 단위로 화면을 다시 그려주는 방식으로 동작한다. 이를 주사율 (refresh rate)이라고 부르는데, 보통 초당 60번, 혹은 120번, 경우에 따라서 240번까지 화면을 다시 그리게 된다. 그리고 이 작업에 상당한 전력을 소모한다. 초당 다시 그리는 횟수가 많을수록 화면 상의 움직임은 자연스럽게 보이게 된다. (물론 우리 눈의 한계 때문에 일정 이상의 주사율은 별 의미가 없다고도 한다)



▲ 화면의 주사율이 높을수록 움직임이 많은 화면에서 더 선명한 표현이 가능하다. (출처 - https://reviews.lcdtvbuyingguide.com/lcdtvpics/lg/truemotion.jpg)


게임 클라가 담당하는 가장 큰일 중 하나는 이런 방식에 맞춰서, 일정 주기별로 디스플레이에 뿌려질 화면을 만들어 내는 것인데, 초당 몇 번의 화면을 만들어 내느냐를 FPS(frame per second)라는 단위로 표시한다. 개인적으로 게임에서 60 fps 정도면 클라가 그래픽 처리를 잘하고 있다고 생각하고, 아무리 못해도 30 fps 이상은 되어야 한다고 생각한다. 디스플레이 주사율은 하드웨어적으로 고정된 값이지만, 게임 클라가 만들어내는 fps 는 클라가 얼마나 화면을 제때제때 찍어내느냐에 따라 달라지는 가변적인 값이다.

그럼 디스플레이가 초당 60번을 갱신하는데, 게임 클라는 초당 30번밖에 화면을 만들어 내지 못하면 어떤 일이 발생할까? 그런 경우 같은 화면을 2번 표시하게 된다. 이렇게 되면 정적인 게임에서는 큰 차이가 없을지 모르지만, 반응성이 중요한 게임에서는 유저의 콘트롤이 바로바로 반영되지 않는 것처럼 뭔가 모를 답답함을 느끼게 된다. 이른바 손맛이 떨어진다는 느낌을 받을 수도 있다.

클라가 초당 30번 화면에 뿌릴 내용을 만든다는 말은 곧, 33미리세컨드 안에 필요한 작업을 모두 마쳐야 된다는 뜻이 된다. 표시되는 그림이 정적이고, 단순히 그림 간의 겹치는 정도만 처리해도 되는 2D 게임이라면 이 시간 제한이 그다지 큰 문제가 되지 않을 수도 있다. 하지만, 게임 내에서 시점을 조작할 수 있는 실시간 3D 게임의 경우, 시점에 따라 무엇이 어떻게 보일지를 매번 계산해줘야 하기 때문에 녹록지않은 제한이다. 이 때문에 클라에서는 화면에 보이지 않는 부분은 건너뛰고, 보이는 부분만을 그리는 트릭을 쓴다.

예를 들어 두 개의 물체가 앞뒤로 겹쳐 있다면, 두 물체를 다 그리는 것이 아니라 뒤쪽에 감춰진 물체는 건너뛰고 앞에 있는 물체만 그리는 식이다. 사실 말은 쉽게 했지만, 시점 변화가 가능한 3D 게임 같은 경우에는 무엇이 앞에 보이는지를 계산하는 것조차도 쉬운 일은 아니다.

그리고 2D든 3D든 화면에 보이는 것들이 많아지기 시작하면, 그것들을 다 조합해서 화면을 만들어내는 게 점점 힘든 작업이 된다. 아마 많은 유저들이 공성전처럼 사람이 많이 몰리는 곳에서나 이펙트가 잔뜩 터지는 화면에서는 게임이 느려지는 경험을 한 적이 있을 것이다. 이건 33미리세컨드 혹은 16미리세컨드처럼 정해진 시간 안에 화면을 다 만들어내지 못하다 보니 이전 화면이 그대로 표시되고 보여줘야 될 화면이 밀리기 때문에 생기는 현상이다.

특히 우리가 접하는 3D 기술은 기본적으로 물체를 그릴 때 수많은 삼각형 다면체의 조합으로 표시하는데, 이 때문에 매끄러운 곡면이나 머리카락, 물과 같은 것들을 표시하는 것은 그 자체로 힘든 작업이다.



▲ 사용되는 삼각형이 많아질수록 보다 정교한 구 형태가 된다. 대신 화면에 그리는 것도 오래 걸린다. (출처 - http://fly.srk.fer.hr/~unreal/theredbook/chapter02.html)


이 때문에 초기 3D 게임에서는 곡면들이 거친 다면체처럼 보이기도 하고, 화장실도 안 갈 것처럼 아름다워야 할 히로인이 떡진 머리로 등장하기도 했었다.



▲ 당대 최고의 그래픽을 보여준 Final Fantasy 8. 그런데 지금 보면 여주에게 샴푸를 사주고 싶어진다.


그래픽 처리가 워낙 복잡하고 오래 걸리는 작업이다 보니, 그래픽 처리에 필요한 작업들은 아예 하드웨어로 심어버리는 경우가 많다. 이렇게 컴퓨터 공학에서 하드웨어의 힘을 빌리는 것을 “하드웨어 가속”이라고 하는데, 그래픽에서는 GPU 라고 불리는 칩이 하드웨어 가속의 핵심이다. 화려한 그래픽의 3D 게임들이 고가의 그래픽 카드를 요구하는 것도 그 이유다. 더 복잡한 그래픽을 처리하기 위해서는 그만큼 고성능의 하드웨어 가속이 필요하다. 당연한 말이겠지만 이런 고성능 GPU 들은 그만큼 열도 많이 발생하기 때문에 거대한 방열판이 달리게 된다.

여담이지만, 아이러니하게도 그래픽 처리는 거의 수학의 영역이다. 더욱 화려한 그래픽을 표현하기 위해서는 더욱 정나미 떨어지는 복잡한 수학식을 접해야 된다. 그 때문에 GPU 는 사실 소숫점 연산과 벡터 연산에 특화되어있다. 이런 점에 착안해서 GPU 를 다른 복잡한 계산에 활용하는 것이 소위 GPU 컴퓨팅이다.


2) NPC 들에게 생명을 불어넣는 AI

게임 내 AI는 클라나 서버 모두에서 구현할 수 있다. 그리고 당연한 것이겠지만, AI가 똑똑할 수록 AI를 돌리는 작업이 버거워지기 시작한다. 그 때문에 AI를 어디서 구현할지 선택할 때 내가 사용하는 규칙은 다음과 같다.

1) 한번에 무거운 AI 여러 개를 구동해서는 안 된다.
2) 서버는 여러 사용자 처리로 인해 AI를 여럿 돌려야 한다. 복잡한 AI는 클라에서 돌리고, 서버는 단순한 AI를 돌리는 것이 좋다.
3) 보스몹처럼 중요한 AI는 서버에서 돌린다.
4) 만일 서버에서 AI를 돌리는 것이 버거울 경우, AI만 떼어내서 별도 AI 서버를 만들 수 있다.
5) 클라에게 중요한 AI를 돌리게 했다면, 서버에서 결과 값 검증 정도는 해야 한다.


참고로 보통 2번을 끄집어내는 순간 클라 프로그래머와의 갈등이 시작되는데... 어쩌겠는가. 나는 서버 프로그래머인 것을. ^^

AI 기술 중에는 고급 기법으로 머신 러닝, 그중에서도 통계학적 머신 러닝 같은 기법들이 존재한다. 실제 아마존이나 넷플릭스 등의 서비스는 사용자의 과거 구매 패턴을 학습 후, 취향을 파악한 뒤 연관 상품을 추천하는 기능을 활용하고 있다. 머신 러닝의 핵심은 과거 데이터를 활용해 현재 선택지의 확률을 조정하는 것이다. (이게 과거 데이터를 이용해서 기계를 학습시키는 것 같다고 해서 머신 러닝이라고 불린다) 알파고 역시 이런 머신 러닝 기법을 이용하여 과거 기보들을 학습하고 지금 두는 바둑에서 가능한 수의 확률을 계산했다.

그러나 게임은 이렇게까지 복잡한 AI 기법을 사용하지 않는다. 안타깝게도 AI 영역이 그다지 발전하지 못한 국내에서 머신 러닝을 잘 다루는 사람도 드물 뿐더러, 그런 AI를 만들어놔도 게임에서는 써먹을 수 있는 곳이 적기 때문이다. 최강 몬스터라면 모를까, 일반 몬스터에 이런 AI를 채택한다면 “초보 던전에서 토끼한테 당했어요. 만랩토끼인가봐요...” 같은 상황이 발생할 것이다. 물론 도전해오는 플레이어들의 공격 패턴 강약약중강약에 따라 점점 강해지는 최강 보스몹 같은 것을 만든다면 다른 이야기가 되겠지만.

그 때문에 게임 클라에서 많이 사용되는 AI는 머신 러닝이 아닌 단순 패턴에 따라 반응하는 몬스터 구현이나, 길찾기 구현 정도이다. 길 찾기는 스타크래프트나 롤에서 유닛을 클릭했을 때 그 지점으로 이동하게 하는 기능 등에 쓰이는데, 얼마나 넓은 지역을 길찾기 대상으로 고려하느냐에 따라 길 찾기 결과와 연산의 과부하가 비례하게 된다. 스타크래프트에서 가끔 정찰 보내 놓은 프로브가 이상한 지역에 갇혀서 못 나오는 경우를 경험해본 유저라면, 그건 성능 문제 때문에 더 넓은 지역을 대상으로 길찾기 작업을 못 했기 때문이라고 이해하면 될 것이다.



▲ 왜 마린은 일렬종대로 다닐까? 비슷한 위치에 있던 마린 각각에 대해서 같은 길찾기 알고리즘을 돌리기 때문에 결국 같은 길을 선택하게 되기 때문이다.


3)  화면을 좀 더 리얼하게 만들어주는 물리 엔진

게임에서 공이 튀어 오르거나, 사람이 뛸 때 몸이 흔들린다거나, 물체가 충돌해서 튕겨 나가는 것 등을 리얼하게 표현하기 위해서는 우리가 고등학교 졸업하면서 영원히 쓰지 않을 것처럼 느꼈던 고전 물리의 많은 부분이 활용된다.

예를 들어 공이 튀어오르는 것을 표현하기 위해서는 탄성력을 계산해야 되고, 충돌한 물체가 방향을 틀어 움직일 때는 운동량 보존의 법칙 같은 것들이 활용된다. 3D 게임을 하다가 물체를 뚫고 움직이는 경우를 경험한 적이 있다면, 이는 충돌 체크가 제대로 잘 안 된 것이다. 이 역시 크게는 물리 엔진의 영역이다. 약간 민망한 이야기가 될 수도 있는데, 내가 아는 어떤 RPG 클라 프로그래머는 새로 사용하게 된 그래픽 엔진에 포함된 물리 엔진 덕에 캐릭터가 달릴 때 살이 흔들리는 게 좀 더 리얼해졌다고 좋아했던 적도 있다. 물론 캐릭터는 매력적인 여캐였다.

우리가 고등학교 물리 시간을 떠올려보면 쉽게 이해할 수 있을 텐데, 당연히 이런 물리법칙 계산은 수학의 영역이고 화면에 출력되는 물체가 많아질수록 계산에 의한 부하는 커지게 된다.



▲ 이렇게 리얼하게 충돌하고 파편이 날아가는 것을 표현하기 위해서는 물리 법칙대로 계산 해줘야 된다. (출처 - https://i.ytimg.com/vi/wKz6_hbXlSE/maxresdefault.jpg)


4) 게임 출시 전 클라 부하 테스트 및 튜닝

지금까지 클라에서 과부하를 줄 수 있는 요소들을 설명했다. 그리고 이 요소들은 화면에 보여지는 물체들이 많아질수록 점점 더 과부하를 유발한다는 공통점이 있다. 그렇기 때문에 클라의 성능을 테스트하기 위해서는, 화면에 물체나 이펙트를 잔뜩 뿌려보고 앞에서 설명한 FPS가 얼마나 떨어지는지를 보면 된다. 그리고 FPS 가 왜 떨어지는지 분석하고 성능을 개선할 수 있다. 이런 부하 테스트와 성능 개선을 반복함으로써 점점 더 탄탄한 클라를 만들 수 있다.

그런데 클라 프로그래머들에게는 미안하지만, 클라이언트는 결국 하나의 PC, 스마트폰, 타블렛에서만 돌면 되고, 부하테스트 역시 프로그래머 개인 개발 환경에서 화면에 물체를 잔뜩 늘어놓는 것으로 쉽게 할 수 있다. 다음 편에서 설명하겠지만, 서버는 여러 대가 상호 작용을 하기 때문에 이보다는 좀 더 복잡하고 현실을 반영한 테스트가 필요하고 그 때문에 출시 전 성능 테스트는 클라보다 서버가 더 어렵다. 그리고 이 때문에 출시 후 서버가 버티지 못하는 일이 빈번하게 발생하는 것이다. 그런데 클라 쪽의 화면을 만들어 내는 작업이나 AI 구현은 이미 그 자체로 어려운 작업이기 때문에 어떤 의미에서는 서버 프로그래머와 다른 종류의 스킬셋이 필요한 직업군이라고 할 수 있겠다.




사실 서버 컬럼인데 이번 회에서는 클라이언트 이야기만 했다. 서버 작업이 클라이언트 작업과 뭐가 다른지를 설명하려면, 먼저 클라이언트에 대해서 이야기할 필요가 있었다. 다음 회에서는 서버 작업에 대한 설명과 디버깅의 어려움을 이야기하도록 하겠다.

댓글

새로고침
새로고침

기사 목록

1 2 3 4 5