이 글은 연잇 프로젝트(온라인 끝말잇기 게임 플랫폼)에서 프로토타입 플랫폼이라고 할 수 있는 ‘끄투’의 문제점을 고쳐나가면서 나온 고민 중 하나입니다. 그리고 이 고민의 시작은 매치메이킹을 통해서 ‘끄투’의 언밸런스한 게임 플레이를 해결하기 위함에서 나왔습니다.


랭킹 시스템과 랭킹 알고리즘

매치메이킹을 그냥 사용자가 들어오는대로 잡아줄 수도 있었을겁니다. 하지만 이번 경우에는 부합합니다. 왜냐하면 기존 ‘끄투’와는 달리 매치메이킹을 통해서 플레이어를 수준별로 분리해 게임을 진행할 계획이기 때문입니다. 그래서 매치메이킹을 하기 전에 먼저 플레이어를 분리해야 합니다. 대표적으로는 2가지 알고리즘이 존재합니다.

  • Microsoft의 TrueSkill
  • Elo 알고리즘

스포일러를 하자면 연잇에는 Elo 알고리즘이 사용될 계획입니다. 물론 TrueSkill도 Elo에 기반을 두고 있습니다. 그러나 인터넷의 여러 곳에서 많은 글을 본 결과는 Elo가 더 적합하다고 판단했습니다. 그 이유는 단순합니다. 2가지 알고리즘에는 각각에 적합한 상황이 있습니다. TrueSkill은 팀 끼리 경쟁을 해야 할 때 가장 적합합니다. 하지만 Elo는 1 vs 1 매치메이킹에서 더 좋은 성능을 냅니다.

끝말잇기를 팀 경쟁이 아닌 개인 경쟁으로 본 이유는 단순합니다. 끝말잇기는 ‘개인’의 턴(차례)가 돌아오기 때문입니다. 팀을 구성한 뒤 플레이해도 똑같습니다. 결과적으로 개인의 팀 기여를 개인 기여로 삼을 수 있게 될 겁니다.

매치메이킹

이제 드디어 제목에 나온 ‘매치메이킹’에 관한 이야기를 풀겁니다. 사실 공개는 하지 않았지만 개인적으로는 매치메이킹을 계속 테스트하고 있습니다. 사실 정말로 쉽지는 않았습니다. 매치메이킹 뿐만이 아닌 병렬 컴퓨팅 문제에 대해서도 신경을 써야했기 때문입니다. 대표적으로 한 대의 서버가 아닐 경우에는 어떻게 해야 하는가에 대한 문제가 있습니다.

사실 이 부분은 글을 초기에 계획할 때와 많이 달라졌습니다. 그래서 시점 차이가 발생할 수 있음을 미리 알려드립니다.

서버가 하나의 프로세스로 실행되고 있다면 걱정하지 않아도 됩니다. 그러나 프로세스가 여러 개가 되고 물리적으로 서버가 분리된다면 어떻게 될까요? 이제 저는 매치메이킹 서버를 분리해야 했습니다. 그 이유는 동일한 플레이어의 중복에 대한 대응과 잘못된 매치 큐에서 비롯되었습니다.

먼저 동일한 플레이어가 중복하여 들어갈 수 있다는 것부터 이야기하겠습니다. 이는 Express의 세션과 Node.JS의 클러스터에서도 발생합니다. 세션이 공유되지 않아 작동을 하지 못하는 상황이 발생된다는 것입니다. 그렇기 때문에 Redis 데이터베이스를 세션 데이터베이스로 사용합니다. 매치메이킹도 동일합니다. 플레이어가 새로고침을 했을 때 흔히 발생할 수 있습니다. 클러스터 1에서 매치메이킹을 시작하고 새로고침을 했을 때 클러스터 2에 작업이 할당된 경우입니다. 이 경우에는 클러스터 2의 경우에는 해당 플레이어는 완전히 새로운 플레이어의 상태입니다. 그렇게 동일한 사람임에도 불구하고 큐에 다시 한 번 할당되는 경우가 생깁니다.

위의 경우는 그래도 Key-value 스토리지 형태의 큐를 다시 확인해보므로써 막을 수 있을 것입니다. 하지만 이는 물리적으로 서버가 달라졌을 때 다시 말이 달라집니다. 그렇기 때문에 최종적으로 결정한 것은 ‘매치메이킹 서버’를 따로 만드는 것이었습니다. 그렇게 되면 ‘매치메이킹 서버’의 매니저가 모든 작업을 동시에 따로 처리할 수 있게 되어 대부분의 스택 병목은 사라질 것입니다.

GitHub 등에 검색을 하면 대표적으로 Google의 Open Match가 등장합니다. 그러나 Golang을 사용하는 등 Node.JS와 중복하여 사용하면 뭔가 찜찜합니다. 그래서 결국 앞으로 새로운 리포지토리를 만들지 않을까 생각합니다. 처음부터 크게 하면 어렵습니다. 그리고 그 사실을 잘 알고 있습니다. 하지만 규모에 따른 이슈에 대해서 유연하려면 꼭 해야 하기에 지금 먼저 시간이 되는대로 커밋을 올리려고 합니다.