MongoDB 모바일 게임 개발에 사용

7,597 views

Published on

Published in: Technology

MongoDB 모바일 게임 개발에 사용

  1. 1. MongoDB를 모바일 게임 개발에 사용 티쓰리엔터테인먼트 모바일 1팀 공통 기술 개발팀 최흥배 과장
  2. 2.  일본의 사이버에이전트 사의 사례 http://www.cyberagent.co.jp/ http://ameblo.jp/principia-ca/entry-10983188853.html  아메바 블로그로 유명 http://www.ameba.jp/
  3. 3. MongoDB를 사용한 이유  개발 효율 향상 모바일 게임은 단 기간에 개발해야 한다. 그러나 게임은 특성상 자주 변경이 발생한다. 스키마레스의 MongoDB는 데이터 구조 변경에 유연하게 대응 할 수 있다.  신기능, 변경 릴리스 대응 모바일 게임은 주에 3,4회 릴리즈 하는 경우가 대다수이다. 그러나 컬럼 추가나 인덱스 추가를 온라인 상태에서 할 수 없으므로 점검이 필 요하게 된다. MongoDB를 사용하면 점검이 하지 않고 추가가 가능하다.  유연한 쿼리, 인덱스 계층 구조화한 문서 내부에도 인덱스를 확장할 수 있다. KVS로도 이용 할 수 있어서 유연한 쿼리 검색을 할 수 있어서 매력적이다.  초기 비용이 작고, 확장성을 보장 ReplicaSets(비동기 레플리케이션)과 Sharding(자동 데이터 분산)을 제공하고 있 음.
  4. 4. 시스템 구성 서버 구성은 Web-App 서버 2대, token이나 정보 캐시용 memcached 2대, Mon goDB 3대로 총 7대. MongoDB는 ReplicaSets 구성으로 primary에 쓰기를 하고, 2대의 secondary에 서 읽기.
  5. 5. Sharding을 하지 않은 이유  서버 대수가 필요하게 되어 비용이 증가하기 때문  ReplicaSets을 3세스(3X3대), mongos 서버, config 서버가 필요하기 때문에 총 11대 필요하게 된다 만약 여유분까지 생각하면 더 필요하다  미리 준비하는 것 보다 상황을 봐서 필요하게 될 때 투입하는 것이 좋다고 판단
  6. 6. 문서 설계  RDBMS와 달리 NoSQL에서는 정규화는 추천 되지 않는다  데이터를 분할하지 않고 문서로 보존하는 쪽이 데이터가 같은 장소에 보존 되어 서버간 통신 횟수도 줄여준다  문서 설계가 가장 중요하고, 가장 힘들다  문서 설계에서는 'modifier 오퍼레이션'과 '데이터 배열에 의한 유지'를 유효하게 사용할 수 있는 설계로 변경한다  또 이미지 바이너리 데이터의 캐시를 MongoDB에 하여 데이터 획득과 캐시 획 득을 한번 하도록 한다
  7. 7. modifier 오퍼레이션  모바일 게임에서는 레벨업이나 경험치 증가 등 increment 조작이 빈번하게 일어 난다  이것을 modifier 오퍼레이션을 이용하여 쉽게 대응할 수 있다
  8. 8. db.userStatus.findOne({"userId" : 2013001}) { "_id" : ObjectId("4d82e95a7a92571409f258dd"), "battery" : 80, "point" : 10000, "smile" : 82, "sumModel" : 41, "sumPicture" : 22451, "sumSales" : 1250, "userId" : 2013001 }
  9. 9. db.userStatus.findOne({"userId" : 2013001}) { "_id" : ObjectId("4d82e95a7a92571409f258dd"), "battery" : 70, "point" : 10000, "smile" : 82, "sumModel" : 41, "sumPicture" : 22452, "sumSales" : 1250, "userId" : 2013001 } 밧데리를 10 소비하고 사진 촬영을 한 경우 -> db.userStatus.update({"userId" : 2013001},{$inc : {"battery" : - 10,"sumPicture":1}})
  10. 10. modifier 오퍼레이션은 계층구조라도 atomic한 조작을 할 수 있다 area2의 퀘스트를 완료하여 레벨이 올라가서 'questlevel'과 'area2'의 숫자를 증 가하는 경우는 아래와 같다 db.user.quest.findOne() { "_id" : ObjectId("4e42208e97ed78c7a7f2f738"), "userId" : 2013001, "questLevel" : 4, "quest" : { "area1" : 3, "area2" : 1, "area3" : 2 } } db.user.quest.update({userId:2013001},{$inc : {questLevel:1,"quest.area2":1}}) db.user.quest.findOne() { "_id" : ObjectId("4e42208e97ed78c7a7f2f738"), "userId" : 2013001, "questLevel" : 5, "quest" : { "area1" : 3, "area2" : 2, "area3" : 2 } }
  11. 11. 데이터를 배열로 유지  유저가 모델 촬영을 한 정보를 가지는 컬렉션을 만든다  1명의 모델(modelId)가 복수의 area에 출현하기 때문에 모델의 상태(mcId)에 의 해 컴플리트 한지(compFlg), 거들떠 보았는지(talkFlg)를 배열로 유지한다  이 데이터는 참조가 많기 때문에 userId와modelId를 key로서 얻을 수 있는 것이 장점이 된다
  12. 12. 새로운 area에서 modelId:180 이라는 사람과 만난 경우 modelDetails 배열에 데 이터를 추가한다 db.user.model.update({"userId" : 1022962,"modelId" : 180},{$push : {"modelDetails" : {"compFlg" : 0,"talkFlg" : 0,"mcId" : 200}}}) { "_id" : ObjectId("4d7dcbe97ccbb19ad8ac09b9"), "modelId" : 180, "modelDetails" : [ { "compFlg" : 0, "talkFlg" : 1, "mcId" : 188 }, { "compFlg" : 0, "talkFlg" : 1, "mcId" : 189 }, { "compFlg" : 0, "talkFlg" : 0, "mcId" : 200 } ], "userId" : 1022962, "telFlg" : 0, "status" : 0 }
  13. 13. 이미지 바이너리 데이터 보존  게임 내에서 만들어진 잡지는 유저가 조작한 타이틀 이미지와 촬영한 모델 이미 지를 합성하여 만든다  이미지를 읽을 때 발생하는 오버헤드를 줄이기 위해서 MongoDB에 이미지 바 이너리 데이터를 보존한다. 한번의 요청으로 필요한 데이터를 얻을 수 있다
  14. 14. db.user.edit.find({userId:3}) { "_id" : ObjectId("4d8c77694ca814174e7e3854"), "color" : "RED", "companyDetailId" : NumberLong(0), "companyId" : NumberLong(0), "coverId" : "4d8c7ebd4ca85714cc7e3854", "font" : 1, "imgData" : BinData(2,"AAAAAA=="), "mcId" : 184, "nextVolImgData" : BinData(2,"YgYAAIlQTkc--省略-- AAElFTkSuQmCC"), "picId" : 7, "scl" : 100, "status" : 2, "time" : "Thu Jan 01 1970 09:00:00 GMT+0900 (JST)", "titleImg" : BinData(2,"CwoAAIlQTkcNChoKA--省略-- AAAAAABJRU5ErkJggg=="), "userEditDetailList" : [ ], "userId" : 3, "x" : 0, "y" : 0 }

×