65. 소셜 게임은 ?
온라인 게임
소셜 게임 : 2012 서울 사례
소개 / 고려사항 / 1 차 구조
문제분석 / 구조개선 / 사내 테스트 / 결론
결론
보너스
66. 이전 서버와 비교하면
개선 전 서버는 C + + 개선 후 서버는 p h p
p h p 가 상대적으로 느린대도
구조개선으로 서버 성능은 향상 ( 1 000re q /s )
67. 이전 서버와 비교하면
유저데이터를 통으로 보관하여
소셜 기능에 부담도 덜어냄
이제 게임 서버가 병목이면 게임 서버 추가
D B 가 병목이면 D B 추가 하는 구조
관리편의성 증대
68. 다른 소셜 게임과 비교
Wooga 게임의 구조 Zynga 게임 ( 웹 ) 의 구조
http://www.slideshare.net/wooga/1000000-daily-users-and-no-cache
http://gdcvault.com/play/1012230/Engine
ering_Scalable_Social_Games
안녕하세요 . 넥슨 신사업본부 마젤란팀에 근무하는 윤석주입니다 . 저는 온라인 게임과 소셜 게임 서버는 어떻게 다를까 ? 에 대한 주제로 이야기를 나누고자 합니다 . 제목을 사례로 살펴보는 비교 분석이라 하였는데요 . 저희가 소셜 게임 서버를 만들면서 겪었던 사례를 소개 하려 하구요 . 온라인 게임과 어떻게 다른지 중간중간 얘기하려 합니다 .
먼저 저에 대한 소개를 간단하게 하겠습니다 . 2 년차 프로그래머구요 . 2012; 서울 모바일 클라이언트 담당하다가 서버쪽을 담당해서 2012: 서울 네이트 버전을 만들었고 지금은 아직 공개되지 않은 프로젝트에 서버를 만들고 있습니다 .
제가 발표할 목차입니다 . 처음에 소셜 게임에 대한 용어 정리를 하고 온라인 게임 서버와 소셜 게임 서버 순으로 이야기를 하고 결론을 내도록 하겠습니다 .
소셜 게임은 페이스북 같은 소셜 네트워크 서비스를 통하여 플레이 하는 게임을 의미합니다 .
이렇다보니 퍼즐 ( 클릭 ), 팜 ( 클릭 ), 레이싱 ( 클릭 ) 등 다양한 장르의 게임이 있지만 ( 클릭 )
이 발표에서는 팜 게임을 기준으로 잡고 진행하도록 하겠습니다 .
온라인 게임 부터 살펴보자면
MMORPG, 캐주얼 장르로 나뉘는 데요 .
MMORPG 의 경우 유저의 캐릭터
아이템
스킬
거래 시스템
이 있어 유저 데이터가 복잡하고 Transaction 의 원자성이 꼭 보장되어야만 합니다 . 아이템 복사 같은게 일어나면 재앙이니까요 . 그래서 DB 부하가 큰 편입니다 .
또한 유저간 상호작용이 이루어지고
월드의 같은 공간을 공유하게 되므로
서버에서 브로드 캐스트 하는 부하가 큰 편입니다 .
그러다보니 .. DB 부하를 줄이기 위해 서버를 나누고 그 안에서 브로드 캐스트 부하를 줄이기 위해 채널이나 지역으로 나누게 됩니다 .
GameTech2010 에서 인용한 아키에이지 서버 구조인데요 . 앞서 말씀드린것과 같이 브로드 캐스트 부하를 줄이기 위해 월드 서버가 여러 개 붙어 있는 모습입니다 . 만약 DB 부하가 늘어난다면 이렇게 ( 클릭 )( 클릭 ) 서버를 늘리겠죠 .
캐주얼 게임으로 넘어가 보면요
MMORPG 와는 다르게 간단한 정보를 가지고 있고
그러다 보니 DB 부하가 적은 편 입니다 .
캐주얼 게임도 MMORPG 와 비슷하게 유저간 실시간으로 상호작용이 있구요 .
그러다보니 MMORPG 와 마찬가지로 브로드 캐스트 부하가 큰 편입니다 .
정리하자면 캐주얼 게임은 DB 부하는 적은 편이라 서버를 하나로 구성하고 채널을 분리하여 브로드캐스트 부하를 분산하는 형태로 되어있습니다 .
아쉽게도 캐주얼 게임 서버 구조는 레퍼런스를 구하지 못해 이런식으로 되어있을것이다 라고 예상해 보았습니다…
이제 저희가 만들어 보았던 2012 서울의 사례를 통해 소셜 게임 서버에 대해 살펴보겠습니다 .
간단하게 게임 소개부터 하겠습니다 .
2012 서울은 화면에 보시는것 같이 자신만의 서울을 만들어 외계인으로 부터 서울을 지킨다는 게임이구요 . 장르로 따지면 변형 팜 게임이라고 보시면 됩니다 .
팜 게임의 재배지와 비슷한 용도인 미사일 타워가 있고
작물 재배하는것과 같은 미사일 생산 , 발사 기능이 있습니다 .
부가적으로 퀘스트 시스템과
게임 컨셉에 맞게 외계인과 전투하는 시스템이 있습니다 .
이 게임은 멀티플랫폼 타겟으로 개발하였구요 . PC 는 Flash 를 이용하여 nexon.com 에 런칭하였고 iPhone 과 android 에서도 같은 환경로 플레이 가능한 게임입니다 .
이 게임 서버를 만들때 고려했던 사항을 말씀 드리겠습니다 .
저희가 예상하기로 캐주얼 게임보다 유저 데이터가 많지만 MMORPG 보다는 적을것이라고 예상을 하였구요 . 유저간 거래가 없어서 Transaction 부하는 적을 것이라고 예상 하였습니다 .
소셜 게임은 온라인 게임과 다르게 유저간 교류가 대부분 간접적이라 기획적으로 브로드 캐스트 할일이 없었습니다 .
당시 다른 소셜 게임과 마찬가지로 단일 서버 구조를 고려하였는데 유저데이터가 많아 조금 걱정하였지만 유저의 액션 자체가 조건 비교 후 값을 변경하는 단순한 연산이라 처리량은 많지 않을것 이라 예상하였습니다 .
웹게임 특성상 유저들이 오랜시간 체류하게 되고 액션은 없지만 동접이 올라가는 효과가 있어서 그런 부분을 대비하려 Frontend 를 확장가능하게 설계하였습니다 .
추가적으로 온라인 게임과 다른 소셜요소인 친구 도시를 그대로 볼 수 있는 도시 방문 소셜 액션중 하나인 도시 방문 후 친구에게 선물주기 PVP 기능이 있었습니다 .
앞에 말씀드린 상황을 고려해서 서버를 만들었습니다 .
그렇게 해서 나온 구조는 캐주얼게임이랑 비슷하다고 할 수 있는데요 . C++ 로 만들었고 Front..( 클릭 ) 캐주얼 게임으로 따지면 채널 서버가 접속 유지와 인증 처리를 담당 하였구요 . Front 뒷단에 붙어서 처리하는 Process 라는 명칭의 서버를 만들었습니다 .( 클릭 ) 이 서버는 유저들의 액션과 , 소셜 기능을 처리하였구요 . 그리고 DB 는 읽기 부하 분산을 위해 ( 클릭 ) mysql 로 Replication 구성을 하였습니다 .
네 그렇게 해서 작년 2 월 24 일날 게임을 런칭 하였습니다 . 그리고 몇가지 서버 구조상의 문제를 발견 하였습니다 . 그 후 2012: 서울을 싸이월드에 런칭할 수 있는 기회가 생겨서 서버의 구조적인 부분을 해결하고 싸이월드에 런칭하는 것을 목표로 작업하였습니다 .
이전 버전의 문제 분석을 해보자면
예상했던것과 달리 유저 액션이 병렬적으로 이루어저 처리량이 생각보다 많았습니다 . 그런데 앞에서 보신것과 같이 Process 를 확장할 수 없는 구조로 만들어 두었죠 ..
그리고 소셜 기능이 문제였는데요 . 도시 방문 , 선물하기 같은 소셜 기능 사용량이 엄청 많았습니다 . 이게 왜 문제가 됬냐면요 ..
MMORPG 스럽게 유저가 가지고 있는 타워 , 스킬마다 쪼개서 DB 에 저장해 두었는데 소셜 기능인 선물 주기를 위해서는 기획적으로 도시 방문을 해야했고 다른 유저의 정보를 전부 읽어와야되니 마치 MMORPG 의 로그인이 부하가 큰것과 같이 엄청난 부하를 발생시켰습니다 . 게다가 이건 1 시간 쿨타임으로 친구를 전부 순회하면서 가능했던거라 유저분들이 정말 열심히 이용해 주었죠 .. 마치 저 짤방과 같은 꿈도 희망도 없는 상황이 벌어졌죠 ..
결국은 Process , DB 양쪽에서 부하가 다 걸리는 상황이 된거죠 ..
이러한 문제를 파악하고 있었는데 운이 좋게 2012: 서울을 싸이월드에 오픈할 수 있는 기회를 얻게 됩니다 . 싸이월드 오픈 시에는 문제가 있던 부분을 고쳐서 런칭하기로 하였습니다 .
통계를 보니 재미있던 부분이 있었는데요 . Flash 에서 접속한 유저는 대부분 오래 클라이언트를 켜두고 플레이를 하였구요 . 모바일 유저들은 잠깐잠깐 자주 로그인을 하는 패턴을 보여주었습니다 . 그래서 드는 의문이 굳이 접속을 유지시켜야 하냐는 것이였죠 . 웹에서 접속하는 유저를 위해 접속을 길게 유지하는것도 낭비인것 같고 모바일 유저들은 커넥션을 유지하는데 많은 비용이 들었으니까요 . 핸드폰 배터리가 빠르게 닳죠 ;;; 그래서 HTTP 프로토콜 위에 게임을 올려보기로 하였습니다 . 그러면서 요번서버는 웹 개발에 적합한 언어인 php 를 사용하게 되었죠 .
이전에 문제가 되었던 Process 의 병목을 해결하기 위해 Scale-out 가능한 구조가 필요하였습니다 . 우선 구조를 단순화 시키려고 하였는데요 . 기존에 Front 가 하던일이 접속 유지 , 인증 처리였는데 플랫폼에서 인증처리도 해주고 접속 유지도 웹 프로토콜로 바꾸면 필요 없어서 Front, Process 를 통합하여 직접 유저랑 통신하는 구조로 변경하였습니다 . 이렇게 구조를 단순화 한뒤 각각 Process 간 동기화가 문제였는데 . 이부분은 DB 를 통해서 하는쪽으로 생각하였습니다 .
DB 를 통해 동기화 하려면 자주 데이터 갱신을 해야되고 DB 에 부하가 몰릴것이라 예상하여 업데이트에 적합한 NoSQL 을 도입하였습니다 .
야후에서 벤치마킹한 결과를 가져왔는데요 . 결과가 보기 힘든데 .. 왼쪽그림은 Read 95 Update 5 정도의 빈도일때 읽기 속도를 나타내고 있습니다 .. 여기서는 선이 회색인 Mysql 읽기가 제일 빠르고요 . 바로 오른쪽에는 같은 상황에서 Update 속도를 나타내고 있습니다 . 여기서는 Hbase 가 제일 빠릅니다 . 오른쪽 두 그림중에 왼쪽을 보시면 Read 50 Update 50 정도의 빈도일때 벤치마크 인데요 . 아까 제일 빨랐던 mysql 이 입력이 많아질수록 확연히 느려지는게 보입니다 . NoSQL 인 카산드라가 제일 빠른편이군요 . 마찬가지로 바로 오른쪽 그래프에서 읽기가 많아져도 카산드라는 빠른 속도를 유지하고 있는것을 볼 수 있습니다 . 이처럼 DB 로 동기화 하기로 하여 DB 업데이트가 잦은 저희 게임엔 NoSQL 이 적합한 선택이였죠 .
또한 DB 도 Scale-out 을 편리하게 하기 위해 도입하였습니다 . 소셜 게임은 설치 절차가 없다 보니 유저가 빠르게 증가하는 편이였고 앞에서 게임 서버는 Scale-out 가능하게 해놨는데 막상 DB 가 scale-out 이 불가능하면 반쪽짜리가 될것 같아 그런 DB 를 도입하게 되었습니다 . NoSQL 은 서비스 작동중에 편하게 Node 추가 / 삭제를 할 수있고 대부분 Sharding 를 자동적으로 지원합니다 .
저희는 NoSQL 중에 Membase 를 선택하였는데요 크게 3 가지 이유가 있는데 메모리 캐시 기능 Memcached 프로토콜 편리한 관리툴 때문 입니다 .
Membase 의 데이터 캐시는 가장 최근에 어세스된 데이터가 RAM 에 올라가고 빈도가 낮아질수록 SSD, Hard disk 순으로 쓰게 되어있습니다 . 대부분 게임의 경우 최근에 활동한 유저에 다시 접근할 가능성이 매우 높으므로 게임에 아무 적합한 DB 라고 생각하였습니다 .
또한 Memcache 프로토콜을 사용하여 쉽게 접근할수 있었습니다 . 특히 memcache 라이브러리는 대부분 언어에 존재하고 프로토콜도 간단하여 정 쓸만한게 없으면 빠르게 만들어서라도 쓸수있겠다 싶어서 도입하게 되었습니다 .
추가로 웹에서 서버를 관리할수있는 툴이 제공 되어 손쉽게 그래픽 인터페이스로 서버를 추가 삭제 모니터링 할 수 있었습니다 . 이런 콘솔 화면에서 Remove Server 버튼만 클릭하면 자동으로 데이터를 다시 분산하고 서버를 제거합니다 . 거꾸로 서버가 추가되도 마찬가지죠 .
결정적으로 Zynga 에서 개발에 참여하고 사용한다해서 저희도 쓰게 되었습니다 . 검증이 되었으니까요 .
Membase 를 사용할때 몇가지 추가 작업이 필요한데요 . NoSQL 특성상 검색이 어려워서 게임 로그를 상세하게 남겨야 유저데이터 검색 , 분석이 쉬워지구요 Key-value Storage 다 보니 유저데이터를 통째로 serialize 하여 저장하여아 합니다 . Serialize 를 어떻게 할것인가에 대한 고려도 필요하구요 . 저희 같은 경우 성능은 조금 떨어지지만 편의를 위해 JSON 을 사용하였습니다 .
또한 DB 에서 Transaction 을 지원하지 않아 게임 서버 단에서 모든 액션이 성공한 후에 쓰게 하였습니다 . 완벽하진 않지만 MMORPG 와 달리 경제시스템이 없어서 별 문제 없이 사용할 수 있었습니다 . 유저 데이터에 Lock 이 없어서 원자성이 보장되는 ADD 명령으로 키를 추가해보고 성공하면 Lock 이 걸린걸로 체크하여 Lock 을 처리하였습니다 .
개선 후 서버 구조 입니다 . 연결이 느슨하게 HTTP 로 바뀌었고 ( 클릭 ) 기존에 Front + Process 가 통합되었으며 ( 클릭 ) GameDB 를 Membase 로 변경하였습니다 ( 클릭 ) 이제 유저가 몰리면 ( 클릭 ) 서버를 추가하면 됩니다 .
그리고 사내테스트를 해 보았습니다 .
사내 테스트를 해보니 생각보다 성능이 안나와서 분석해보니 유저 데이터를 가져오고 deserialize 하는데 많은 부분을 쓰고 있었습니다 . 그래서 캐시의 필요성을 느끼고 APC 를 사용하였습니다 . php 의 경우 한번 요청이 오면 초기화 하고 실행되고 종료되는 형식이라 메모리에 무언가를 저장할 수 없었는데 APC 는 로컬 웹서버에 메모리에 일정공간에 객체를 올려둘 수 있어서 성능상 낭비되는 부분을 수정할 수 있었습니다 . 그리고 로컬에 있는 객체가 최신 캐시인지 확인 하기 위해 Memcache 를 사용해서 마지막 업데이트 시간을 기록하여 최신 객체인지 체크하였습니다 .
캐시를 하고나니 서버가 여러대일 경우 어느 서버에 접속하게 될지 알 수가 없어 Cache hit 가 좋은 편이 아니였습니다 . 그래서 소프트웨어적 클라이언트에서 한번 연결이 되면 최대한 같은 서버에 접속하도록 변경하였습니다 .
소셜 게임 서버 구조 변경후 결론은
개선전 서버는 C++ 로 짰고 개선 후 서버는 php 로 짰는데 php 가 벤치마크 같은것을 보면 훨씬 느린대도 오히려 전체적인 서버 퍼포먼스는 향상 이전 서버는 DB 부하가 커서 게임의 대부분 액션이 매우 느렸습니다 .
특히 문제가 많이 됬던 소셜 기능은 NoSQL 을 사용하면서 데이터를 통으로 보관하여 부담을 많이 덜어 낼 수 있었습니다 . 이런 구조로 바꾼후에 게임 서버가 병목이면 게임 서버를 추가하고 DB 가 병목이면 DB 를 추가하는 손쉽게 scale-out 할 수 있는 구조가 만들어져서 관리 편의성이 증대 되었습니다 .
추가로 Wooga 나 Zynga 의 경우 어떤 구조인지 찾아보았는데 저희와 비슷하게 웹 서버가 게임 로직과 결합해 있고 DB 를 통해 동기화하는 구조로 이루어져 있었습니다 . Wooga 쪽은 로드 밸런서와 웹서버로 이루어져있고 웹서버에서 DB(mysql) 와 Redis 를 사용하고 있습니다 . Redis 는 단순한 알고리즘을 가지고 있는 메모리 DB 라고 생각하시면 되는데요 . Wooga 는 자주변하는 데이터를 Redis 에 넣어놨고 덜 변하는 데이터를 Mysql 쪽에 넣어두어 부하를 분산했다고 하였습니다 . Zynga 의 경우도 클라이언트와 웹서버가 통신하고 웹에서 DB, 캐시에 접근하는 구조로 되어있습니다 . 다른 게임의 경우도 웹서버에 모든 로직을 담고 DB 로 동기화 하고 부하 분산을 위해 DB 를 scale-out 한것을 알 수 있습니다 .
마지막으로 간단하게 정리해보자면요 .
소셜게임의 DB 부하는 캐주얼 게임보다 확실히 많았고 동기화를 DB 로 하면서 잦은 업데이트를 감당하기 위해 NoSQL 을 사용하였습니다 . 소셜 게임은 브로드 캐스트 부하는 없는 대신 소셜 요소를 고려해야 합니다 . 다른 액션들과 다르게 다른 유저의 데이터에 영향을 끼치므로 기획에 맞는 적절한 솔루션을 찾아야 합니다 .