Thursday, September 18, 2014

모바일 게임 서버 제작 방법

안녕하세요? 비니아빠 바야바입니다.
일단 조회수를 위해 제목만 거창하게 달아봤습니다. 죽여주세요.
오늘은 제가 만든 온라인 게임들은 어떻게 만들어졌는지 진짜 간단하게 소개해보려고 합니다.
2G->3G->LTE를 거치면서 모바일 네트워크 성능은 점점 더 진화하고 있고,
앞으로 모바일 온라인 게임이 마켓의 트렌드가 자리잡을 날도 머지 않았기 때문입니다.

1. 게임 서버
알까기 온라인의 초창기 시절에는 집에서 개인PC 한대를 서버 전용으로 돌렸습니다.
동접이 늘어나서 향후에는 17만원 상당의 서버 호스팅 서비스를 이용했구요.
알까기, 장기, 오목, 탱크가디언까지 4개 온라인 게임을 1대의 서버에서 모두 실행했습니다.
최근에 개발한 치킨팝 온라인은 KT의 클라우드 서비스를 이용하고 있는데 성능은 괜찮습니다만,
KT측의 클라우드 서비스가 죽어서 2번 정도 서비스가 중단되는 사태가 있었습니다.

게임 서버는 윈도우 서버를 사용했고, Visual C/C++를 이용해 서버당 동접 3천명을 처리하도록 개발했습니다.
알까기는 최대 1700명을 기록했고, 장기가 900명, 오목이 250명, 탱크는 150명 수준을 기록했습니다.

게임 서버의 스레드는 이벤트 방식으로 원스레드 방식을 썼습니다.
Z9별이라는 MMORPG를 개발할 당시에는 멀티스레드를 사용했습니다만, 제가 만든 게임들은 모두 턴 게임였기 때문에
필요성이 느껴지지 않아서 그냥 원스레드로 개발했고, 성능에도 아무런 문제가 없었습니다.

2. 데이터 베이스
게임의 DB는 윈도우 서버라서 MS-SQL을 썼습니다.
다만 서버 호스팅 비용보다 MS-SQL 임대 비용이 더 비싼 관계로, 월 6,900원짜리 DB호스팅을 이용했습니다.
그럭저럭 사용할 만한 수준은 됐습니다만, 역시 전용 DB가 없으니 속도상 느린 것은 어쩔 수 없더군요.
DB호스팅을 한 후에, 게임 서버와 ODBC로 연결하여 쿼리를 날렸습니다.
MySQL이 더 편하신 분들은 MySQL을 쓰셔도 아무런 문제가 없습니다.

3. 소켓과 프로토콜
온라인 게임을 만들려면 서버에서 TCP 소켓을 열고 패킷을 주고 받아야 합니다.
제가 자바를 할줄 몰라서 그렇긴 합니다만, 자바로도 충분히 게임 서버를 만들 수 있을걸로 생각됩니다.
게임 서버에서 TCP 소켓을 열고, 패킷을 주고받을 프로토콜이 완성되면
안드로이드 클라이언트에서 서버와의 통신을 위한 스레드를 하나 만듭니다.
게임이 돌아가는 동안에도 네트워크와 계속 통신하면서 데이터를 보내고 받아오고 해야 하기 때문입니다.
socket.setSoTimeout( 60000 );
socket.setTcpNoDelay( true );
저는 클라이언트의 소켓 옵션을 2가지 지정했습니다.
모바일의 네트워크 상태는 아직 불안정하기 때문에 setSoTimeout 시간을 60초 정도 지정해주었고,
setTcpNoDelay를 true로 셋팅해서 패킷을 다 기다리지 않고 곧바로 보내도록 지정했습니다.

서버에서 오는 패킷을 받기 위해 10000 바이트의 버퍼를 만들어서 데이터를 쌓았습니다.
쌓여진 데이터의 선두부터 체크해서 1개의 패킷이 구성될 수 있을 만큼 데이터가 쌓였으면 패킷을 처리하고
다음 패킷의 크기만큼 쌓일때까지 계속 스레드를 돕니다.

여기서 중요한건 통신 스레드에 Sleep을 어느정도 걸어줘야 한다는 겁니다.
안그러면 폰에 따라 게임의 속도에도 영향을 주게 됩니다. 저 같은 경우는 Thread.sleep( 100 );을 해줬습니다.

4. 데이터 구조
저는 서버와 주고 받은 모든 값을 byte형 배열로 처리했습니다.
패킷에 char, short, int 등의 데이터를 byte 단위로 쉬프트 연산해서 1바이트씩 쪼개서 배열에 차례대로 넣고,
문자열을 보내야 할 경우에도 문자열을 byte형 데이터로 바꾸어서 전체 길이 만큼 배열에 추가시켰습니다.
서버에서 보내지는 데이터도 당연히 byte 배열이고, 배열 내용에서 다시 char, short, int, 문자열 등을 추출합니다.
한가지 기억해두셔야 할 것은 안드로이드가 사용하는 문자열은 UTF-8이고, 윈도우 서버에서 사용하는 문자열은
아스키 코드라는 점이죠. 그래서 서버에서 받은 문자열을 사용하려면 코드 변환을 해줘야 합니다.
반대로 서버에서 클라이언트로 문자열을 보내려면 역시 반대로 코드 변환을 해줘야 하고요.

5. 온라인 게임 제작시 주의할 점
안드로이드의 네트워크 기능은 아직 불완전 합니다.
3G와 WIFI가 다 켜져 있을 경우, WIFI가 꺼지고 3G가 잡히던가 하면 서버와의 접속은 여지없이 끊어집니다.
여러가지 해결책이 있겠습니다만, 일정 시간마다 클라이언트가 서버로 라이브 패킷을 보내도록 해서
일정 시간 이상 피드백이 없으면 네트워크 상태가 고르지 못한 것으로 간주하고 연결을 끊어버리거나,
게임 화면을 그대로 유지하면서 접속만 다시 시도하는 방법 등이 있겠습니다.
온라인 게임은 유저끼리 승패를 겨루는 경우가 많기 때문에 이런 처리가 없으면 상대방이 연결이 끊어졌을때,
다른 한쪽은 하염없이 계속 기다리고 있어야 하는 불상사가 생깁니다.
연결이 끊어지면 끊어졌다라는 신호라도 서버로 바로 보내주면 좋으련만, 안드로이드는 그런 친절함은 없어 보입니다.

이상입니다.
온라인 게임 개발에 대해 궁금하셨던 분들에게 약간이나마 도움이 되셨길 바랍니다.

http://www.androidpub.com/2048035

No comments:

Post a Comment