비슷한 실력의 이용자들을 묶으면 좋은 매칭이 될까. 그러려면 우선 무엇을 실력으로 볼지부터 정해야 한다. 승패로 추정한 점수 하나로 충분한지, 서로 다른 능력을 여러 값으로 표현해야 하는지에 따라 비슷한 실력의 상대를 찾는 방법도 달라진다.

실력을 정의한 뒤에도 질문은 남는다. 두 팀의 실력을 비슷하게 맞춘 경기가 이용자에게도 즐거운 경기일까. 점수 차이가 조금 있더라도 역할이 잘 맞거나 선호하는 방식으로 플레이할 수 있는 조합이 더 나을 가능성은 없을까. 이런 가능성을 살피려면 실력 외에 어떤 요소를 매칭에 반영할지도 검토해야 한다.

여러 게임 팀과 매칭 조건을 정하고, 데이터 분석가와 함께 평가 모델을 서비스에 적용하는 과정에서 이런 질문들을 다뤘다. 평가에 필요한 데이터를 연결하고, 서로 다른 계산을 같은 엔진에서 사용할 수 있도록 구현했다. 적용 대상과 설정을 나눠 기존 방식과 비교하고, 매칭 이후의 기록을 확인할 수 있도록 운영 기능도 보완했다.

01 / 실력과 조합 평가

실력과 좋은 매칭의 기준

우선 승패를 바탕으로 실력을 추정하는 경우를 살펴보자. 점수가 같더라도 경기를 충분히 치른 이용자와 이제 몇 경기만 치른 이용자의 추정치를 똑같이 신뢰하기는 어렵다. 예를 들어 트루스킬(TrueSkill)은 실력 추정치와 그 불확실성을 함께 표현하고, 경기 결과가 들어올 때 두 값을 갱신한다.

Microsoft Research · TrueSkill의 실력 추정치와 불확실성

… the “expected player skill” and the “uncertainty” associated with that assessment of their skill.

… 이용자의 실력 추정치와 그 추정에 따르는 불확실성.

실력 추정의 불확실성과 별개로, 어떤 능력들을 평가할지도 정해야 한다. 예를 들어 상대를 정확히 겨냥하는 능력과 팀의 상황을 판단하는 능력을 따로 평가하는 경우를 생각해 보자. 한쪽에 강한 이용자와 다른 쪽에 강한 이용자를 종합 점수만으로 비교하면, 각자 어떤 역할에서 기여할 수 있는지는 드러나지 않을 수 있다. 여러 값을 유지한다면 어떤 능력을 기준으로 상대를 비교할지, 팀을 구성할 때 각 능력을 얼마나 반영할지도 정해야 한다.

캐릭터가 성장하는 게임이라면 이용자의 숙련도가 비슷해도 캐릭터의 능력에 따라 결과가 달라질 수 있다. 승패로 추정한 실력과 캐릭터의 능력값은 서로 다른 정보를 담는다. 어느 쪽을 사용할지, 함께 쓴다면 각각 얼마나 반영할지에 따라 실력을 나타내는 방식도 달라진다.

실력이 비슷한 이용자들을 찾았다고 해서 매칭 상대가 바로 정해지는 것은 아니다. 파티 구성이나 행동 특성에 따라 조합을 다르게 평가할 수 있고, 플랫폼 호환처럼 반드시 충족해야 하는 조건도 있다. 이를 구현할 때는 개인의 실력 추정, 후보 조합의 평가, 매칭 조건을 나눠 다뤘다.

  • 실력 추정: 이용자의 경기 수행 능력을 값으로 나타낸다.
  • 조합 평가: 후보 이용자들을 특정 팀에 배치했을 때, 그 구성이 얼마나 적절한지 계산한다.
  • 매칭 조건: 매칭할 수 있는 상대의 조건과, 기다리는 동안 완화할 수 있는 기준을 정한다.

개인의 실력 점수가 정해져도 팀을 어떻게 평가할지는 따로 정해야 한다. 두 팀의 평균을 맞추는 것이 한 가지 방법이지만, 평균이 같다고 팀 안의 구성까지 비슷한 것은 아니다.

평균만으로 구분할 수 없는 두 구성

표를 좌우로 밀어 비교할 수 있습니다.

구성팀 A팀 B
팀 안의 차이가 큰 경우1300 + 1700 → 평균 15001300 + 1700 → 평균 1500
팀 안의 차이가 없는 경우1500 + 1500 → 평균 15001500 + 1500 → 평균 1500

서로 다른 두 후보 집합으로 만든 2인 팀 예시다. 같은 이용자를 재배치한 결과는 아니다.

두 경우 모두 팀의 평균은 1500점이고 상대 팀과의 차이도 없다. 하지만 첫 번째 구성에서는 같은 팀 안에서도 400점의 차이가 난다. 팀 평균의 차이만 계산해서는 이 둘을 구분할 수 없다. 가장 잘하는 이용자 한 명이 경기의 흐름을 크게 바꾸는 게임이라면, 그 이용자의 영향을 평균보다 더 크게 반영할 수도 있다.

팀 간 점수의 균형을 맞춘 뒤에도 이용자가 어떤 경기를 경험하는지는 살펴봐야 한다. 점수 차이가 작은 조합과, 차이는 조금 더 크지만 원하는 역할로 플레이할 수 있는 조합 중 어느 쪽을 이용자가 더 즐겁게 느낄지는 점수만으로 판단하기 어렵다. 여기서 검토할 것은 어느 정도의 실력 차이를 허용할지, 그 대신 어떤 경험을 기대하는지, 실제로 그런 경험으로 이어졌는지다.

이런 기준들을 바꿔 적용할 수 있도록 개인의 점수와 팀 조합을 평가하는 계산을 분리했다. 팀 평균의 차이, 팀 안의 실력 차이, 특정 이용자의 영향을 각각 얼마나 반영할지에 따라 다른 계산기를 구현하고 엔진에 연결했다.

행동 관련 속성을 실력 차이와 함께 평가하거나, 경기 후 이탈 가능성을 조합 평가에 반영하는 시도도 했다. 이탈 예측의 경우에는 준비된 모델을 서비스 코드로 옮기고 후보 이용자들의 속성을 모델 입력으로 변환했다. 예측 결과는 엔진이 후보 조합을 비교하는 데 사용할 품질 값으로 반환했다.

이 계산의 결과는 후보 이용자들을 해당 팀 구성으로 묶었을 때의 평가 값이다. 어떤 정보를 실력으로 표현할지, 그 실력과 다른 속성을 조합 평가에 얼마나 반영할지에 따라 필요한 데이터와 수정할 계산도 달라졌다.

02 / 입력 데이터

평가에 필요한 데이터를 연결하기

계산에 사용하는 값은 경기 기록에 한정되지 않았다. 이용자 특성이나 서비스 이용 이력을 가공한 값도 사용했고, 게임 서버가 매칭 요청에 직접 담아 보내는 정보도 받았다. 이 값들을 매칭에 사용할 수 있도록 자체 저장소를 갖춘 속성 관리 서비스를 구성하고, 속성별로 데이터를 가져올 소스와 계산 방식을 지정했다.

분석 과정에서 값을 만들었다고 곧바로 계산기에 넣을 수 있는 것은 아니었다. 어느 이용자의 값을 조회할지, 어떤 이름과 자료형으로 전달할지부터 맞춰야 했다. 그 값을 개인의 실력 추정에 쓸지, 조합 평가에 쓸지, 매칭 대상을 제한하는 조건으로 쓸지도 정해야 했다.

매칭에 사용할 속성으로는 연승·연패 기록, 최근 플레이한 맵, 캐릭터의 직업군, 매너 점수 등을 고려할 수 있다. 연승·연패나 최근 맵 정보는 플레이 이력을, 직업군은 캐릭터의 역할을, 매너 점수는 행동 특성을 나타낸다. 어떤 속성인지에 따라 계산에 사용하는 방법도 달라진다.

현재 연승 횟수를 조합 평가에 사용한다면, 값을 조회해 0을 받았을 때는 연승 중이 아닌 것으로 평가할 수 있다. 하지만 저장된 값이 없거나 조회에 실패했다면 연승 여부를 알 수 없다. 이 경우까지 모두 0으로 바꾸면, 기록을 확인하지 못한 이용자도 연승 중이 아닌 이용자로 평가하게 된다. 따라서 실제 값이 0인 경우와 값을 확인하지 못한 경우를 구분해야 한다. 값이 저장돼 있지 않은 경우와 조회에 실패한 경우도 각각 어떻게 처리할지 정해야 한다.

값이 언제 만들어졌는지도 중요했다. 데이터웨어하우스의 데이터는 원천 기록을 추출·변환·적재하는 ETL 파이프라인을 거치므로, 게임에서 발생한 변화가 조회 가능한 값에 반영되기까지 시간이 걸린다. 미리 가공한 값을 사용하면 매칭 요청마다 계산을 반복할 필요는 없지만, 다음 갱신까지는 이전 상태를 기준으로 평가하게 된다.

게임 클라이언트의 리전별 레이턴시와 접속 플랫폼은 매칭 요청 시점의 값이 필요하므로 게임 서버에서 직접 전달받았다. 특히 접속 플랫폼은 같은 이용자라도 접속할 때마다 달라질 수 있다. 따라서 이전에 수집한 값을 재사용하지 않고, 매 요청에 현재 접속 정보를 담아 보내도록 해야 했다.

플랫폼이나 컨트롤러 유형은 실력을 평가하는 기준에도 사용할 수 있다. 같은 이용자라도 어떤 플랫폼과 컨트롤러를 사용하는지에 따라 다른 실력 기준을 적용할 수 있고, 함께 플레이할 상대의 범위를 제한할 수도 있다. 예를 들어 이용자가 다른 플랫폼이나 리전의 상대를 제외하는 옵션을 선택하도록 하거나, 게임 기획에 따라 허용할 조합을 정할 수 있다.

ETL의 갱신 간격보다 빠르게 변화를 반영해야 하는 속성은 게임 서버가 현재 값을 직접 전달하거나, 전달받은 경기 결과로 속성 관리 서비스가 값을 갱신하도록 했다. 예를 들어 방금 끝난 경기로 연승 횟수가 바뀌었다면, 다음 매칭에서 이 변화를 바로 반영해야 할 수 있다. 데이터웨어하우스의 갱신을 기다리는 동안 이전 연승 횟수를 사용하는 것보다 현재 상태를 더 세밀하게 반영할 수 있다. 따라서 속성마다 어떤 값을 사용할지와 함께, 얼마만큼의 갱신 지연을 허용할지도 정해야 했다.

속성 관리 서비스에서는 각 속성을 어디서 가져올지 설정으로 지정했다. 게임 서버가 보내는 현재 상태와 경기 결과, 데이터웨어하우스 등에서 가공한 데이터, 자체 저장소에 보관한 값을 연결하고, 필요한 속성을 불러와 계산에 사용하도록 구성했다.

경기 결과가 들어오면 자체 저장소의 기존 값을 읽고, 새 결과를 반영해 실력 추정치와 관련 속성을 갱신했다. 계산한 결과는 다시 저장해 이후의 조회와 계산에서 사용했다. 조회 시점에 계산할 항목은 저장소에서 불러온 값과 요청에 담긴 속성에 설정된 식을 적용해 반환했다.

매칭 엔진은 속성 관리 서비스에서 받은 값을 후보 탐색과 조합 평가에 사용했다. 원천 데이터의 조회와 자체 저장소의 값 갱신은 속성 관리 서비스가 담당했다. 새 속성이 필요하면 이 서비스에 데이터 소스와 계산 방식을 연결하고, 매칭 쪽에서는 그 값을 어떤 평가나 조건에 사용할지 정했다. 이때 속성의 의미와 기본값, 갱신 시점도 함께 정의해야 했다.

03 / 평가 모델과 엔진

서로 다른 평가 방식을 같은 엔진에 연결하기

게임마다 평가 방식은 달라도 후보를 모으고 팀을 구성하는 과정까지 매번 새로 만들 필요는 없었다. 기존 엔진에서 새 평가 방식을 사용할 수 있도록 계산기를 공통 인터페이스에 맞춰 구현했다. 엔진은 팀·파티 정보와 이용자 속성을 전달하므로, 계산기는 이 정보를 각 모델의 입력 형식에 맞게 변환했다.

계산기를 호출하는 순서는 초기화, 이용자 추가, 품질 계산이다. 새 조합을 평가하기 전에 이전 후보의 데이터를 비우고, 이번 후보들을 차례로 넣은 뒤 조합을 비교할 평가 값을 계산한다. 같은 이용자라도 어느 팀에 배치하느냐에 따라 결과가 달라지므로, 이용자 속성과 함께 팀·파티 정보도 전달했다.

  • 후보 구성: 엔진이 후보 이용자를 모으고 팀 배치를 정한다.
  • 입력 변환: 계산기가 전달받은 팀·파티 정보와 이용자 속성을 읽어 평가에 필요한 입력을 만든다.
  • 품질 계산: 조합의 품질을 하나의 값으로 반환한다. 여러 계산을 결합할 때도 반환값은 하나다.
  • 비교와 수락: 엔진이 조합의 품질을 수락 기준과 비교하고, 탐색 중 평가한 조합들의 품질도 비교한다.

여러 평가 기준을 함께 쓸 때는 계산기들을 묶어 호출하는 결합 계산기를 만들었다. 초기화와 이용자 추가를 각 계산기에 똑같이 전달하고, 반환된 품질 값에 각각의 가중치를 곱해 더했다. 이때 각 가중치를 가중치의 총합으로 나눠 비율로 사용했다. 결합 계산기도 같은 인터페이스를 따르므로, 엔진의 탐색 코드는 그대로 사용할 수 있었다.

다만 가중치를 1:1로 둬도 두 기준이 결과에 미치는 영향까지 같아지는 것은 아니다. 한쪽 계산의 값이 다른 쪽보다 큰 폭으로 변한다면, 두 값을 더한 결과도 그쪽에 더 크게 좌우될 수 있다. 비율을 정하기 전에 각 계산의 값이 어느 범위에서 얼마나 달라지는지 살펴봐야 한다.

기존 평가 기준의 비중만 바꿀 때는 가중치를 조정하면 된다. 새로운 평가식이 필요하면 공통 인터페이스에 맞는 계산기를 추가한다. 준비된 예측 모델을 옮길 때도 이 방식으로 입력 변환과 품질 계산을 연결했다. 여기서 다룬 작업은 모델을 새로 설계하거나 학습하는 것이 아니라, 준비된 모델을 매칭 과정에서 사용할 수 있도록 구현하는 일이었다.

계산기 밖에서 바꿔야 할 부분도 있다. 필요한 속성이 늘면 데이터 정의와 조회를 수정해야 하고, 상대를 찾는 범위나 플랫폼 호환 조건을 바꾸려면 탐색·필터 로직을 수정해야 한다. 계산기가 반환한 품질을 보고 조합을 받아들일지도 엔진에서 판단한다. 계산과 탐색을 분리해 두더라도, 새 평가 방식을 적용할 때는 이 조건들을 함께 확인해야 했다.

04 / 탐색과 빈자리 보충

후보를 찾고 조합을 받아들이는 조건

계산기는 엔진이 구성한 후보 조합을 평가한다. 그러려면 먼저 어떤 이용자를 후보로 찾을지 정해야 한다. 후보를 정렬하는 점수나 탐색 범위가 바뀌면, 계산기로 평가할 조합도 달라진다.

가령 실력 점수의 계산식을 바꾼 뒤 이용자들의 점수가 가운데 구간에 몰리고, 양끝 구간에는 적게 분포하는 경우를 생각해 보자. 같은 폭으로 상대를 찾아도 가운데 구간에서는 후보가 많지만, 양끝에서는 충분한 후보를 찾기 어려울 수 있다. 따라서 탐색 범위를 그대로 유지하더라도 점수 분포에 따라 대기 시간이 달라질 수 있다.

풀은 같은 매칭 설정을 적용할 요청들을 모아 처리하는 단위다. 대기 시간을 추정할 때는 풀 전체가 아닌, 상대를 찾는 점수 구간의 유입량을 사용했다. 해당 구간에서 초당 몇 명이 매칭을 요청하는지 집계하고, 현재 파티 외에 더 필요한 인원을 이 속도로 나눠 대기 시간을 추정했다.

풀마다 탐색 범위와 품질 수락 기준을 정하고, 대기 시간에 따라 기준을 얼마나 완화할지 조정할 수 있도록 했다. 이때 플랫폼 호환처럼 매치가 성립하려면 반드시 지켜야 하는 조건은 완화할 수 있는 기준과 구분했다.

후보를 찾고 평가하는 데 쓸 수 있는 계산량도 한정돼 있다. 가능한 팀 조합을 전부 평가할 수 없으므로 후보 수나 탐색 횟수에 한도를 두고, 실제로 살펴본 조합 중에서 고른다. 평가 방식의 차이를 비교하려면 계산기뿐 아니라 탐색 범위와 한도, 수락 조건도 같았는지 확인해야 했다.

새로 팀을 구성하는 경우와 이미 만들어진 매치의 빈자리를 채우는 경우도 다르게 처리해야 했다. 빈자리 보충(backfill)은 기존 이용자와 팀 배치를 유지한 채 추가할 후보를 찾는다. 후보를 넣은 뒤의 품질뿐 아니라, 넣기 전보다 얼마나 달라지는지도 함께 계산했다.

빈자리가 있는 기존 구성의 품질이 이미 최소 기준보다 낮은 경우를 생각해 보자. 보충 후의 품질이 최소 기준을 충족하는 경우에만 받아들이면, 현재보다 품질이 좋아져도 기준에는 못 미치는 후보를 거절하게 된다. 그래서 보충 전보다 품질이 개선되거나 최소 기준을 충족하면 품질 검사를 통과하도록 구현했다. 반대로 현재보다 품질이 낮아지더라도 최소 기준을 충족하면 통과한다.

보충 전후의 변화와 품질 기준을 함께 보는 예시

표를 좌우로 밀어 비교할 수 있습니다.

보충 전 → 후품질 기준품질 검사 결과
40 → 5060기준 미달이어도 이전보다 좋아져 통과
80 → 7060이전보다 낮아져도 기준을 충족해 통과
40 → 3560개선도 기준 충족도 없어 거절

숫자는 실제 설정값과 무관하며, 값이 높을수록 조합을 좋게 평가한다. 각 행은 별개의 후보 상황이다. 품질 검사 외에 팀 인원과 호환 조건 등도 충족해야 한다.

05 / 설정과 비교

바꾼 매칭 기준을 실제 경기에서 확인하기

팀 간 실력 차이를 작게 만드는 기준을 정했다고 해서, 그 기준이 이용자에게도 더 나은 경기를 만들어 주는지는 아직 알 수 없다. 이를 확인하려면 어떤 경험이 달라지기를 기대하는지 정하고, 바꾼 기준을 실제 매칭에 적용해 봐야 한다.

설명을 위해 팀 평균의 균형을 중시하던 방식에 팀 내부의 실력 차이도 반영하는 경우를 생각해 보자. 같은 팀 안에서 실력 차이가 큰 이용자들을 줄이면 경기 도중 이탈하는 이용자도 줄어들지 살펴볼 수 있다. 반면 좋은 평가를 받는 조합이 줄어 대기 시간이 길어질 수도 있다. 따라서 경기 중 이탈뿐 아니라 매칭을 기다리다가 취소하는 경우도 함께 확인해야 한다.

팀 내부의 실력 차이를 반영하는 비교 예시

표를 좌우로 밀어 비교할 수 있습니다.

항목기존 방식바꾼 방식
조합 평가팀 평균의 차이를 중심으로 평가팀 내부의 실력 차이도 함께 평가
입력 데이터같은 실력 추정치 사용같은 실력 추정치 사용
탐색 조건같은 탐색 범위와 횟수 한도 적용같은 탐색 범위와 횟수 한도 적용

실제 실험 설정이나 결과를 옮긴 것이 아니라, 비교할 변경을 설명하기 위한 예시다.

이 예시에서 비교하려는 것은 조합 평가 기준의 차이다. 실력 추정식이나 탐색 범위까지 함께 바꾸면 결과가 어느 변경 때문에 달라졌는지 구분하기 어려워진다. 따라서 비교하려는 항목을 정하고, 나머지 조건을 맞춰 적용할 수 있어야 했다.

이런 비교를 지원하기 위해 풀 설정과 A/B 테스트를 관리하는 대시보드에 새 매칭 규칙을 추가하고, 입력한 설정을 검증하는 처리를 보완했다. 실험군별로 사용할 데이터와 계산 방식, 탐색·수락 조건을 설정하고 적용 대상을 나눌 수 있어야 했다. 일반 매칭과 빈자리 보충에 각각 어떤 규칙을 적용할 수 있는지도 구분했다.

엔진에서는 요청을 어느 실험군의 풀로 보낼지 정하는 설정과 이력을 읽어 해당 풀을 찾도록 구현했다. 결과를 비교할 때는 각 요청이 어느 풀에서 어떤 설정으로 처리됐는지도 확인해야 했다. 그래야 경기 중 이탈이나 대기 취소 기록을 그 요청에 적용된 매칭 기준과 연결해 볼 수 있다.

요청부터 경기 결과까지 확인하는 데 필요한 로그의 변환·전달과 공통 오류 수집도 보완했다. 예를 들어 한 실험군에서 완료된 경기 수가 적게 나왔다면, 오래 기다리다가 매칭을 취소한 것인지, 상대는 찾았지만 게임 시작에 실패한 것인지부터 구분해야 한다. 게임은 시작했는데 결과 기록이 들어오지 않은 경우도 따로 확인해야 한다. 완료된 경기만 비교하면 매칭을 취소했거나 게임을 시작하지 못한 이용자의 경험은 빠지게 된다.

매칭 기준을 바꾼 뒤에는 개별 경기의 변화와 장기적인 이용 지속 여부를 함께 살펴야 했다. 대기 시간과 매칭 취소, 경기 중 이탈을 살피는 것과 함께, 7일·30일 리텐션처럼 더 긴 기간의 이용 지속 여부도 분석해야 했다. 상대를 찾고 경기를 마치는 과정이 어떻게 달라졌는지에서 나아가, 이후에도 이용자가 게임을 계속 찾는지까지 보는 것이다.

리텐션에는 매치메이킹 외에도 게임 콘텐츠와 업데이트, 이벤트 등이 영향을 줄 수 있다. 따라서 수치가 달라졌다는 것만으로 매칭 기준을 바꾼 효과라고 단정하기는 어렵다. 실험군의 배정 방식과 이용자 구성, 같은 기간에 적용된 콘텐츠 변화 등을 함께 확인해야 한다. 리텐션을 집계하는 기준과 관찰 기간도 맞춰 비교하고, 매치메이킹의 영향과 다른 요인의 영향을 어디까지 구분할 수 있는지 보수적으로 해석해야 한다.

비슷한 실력의 이용자를 묶는다는 출발점에서, 실력을 어떻게 표현할지와 어떤 조합을 좋게 볼지로 질문이 이어졌다. 점수의 균형을 더 중시할 수도 있고, 어느 정도의 차이를 허용하면서 역할 구성이나 행동 특성을 함께 평가할 수도 있다. 어느 기준이 이용자에게 더 나은 경험으로 이어지는지 살피려면 실제 매칭에 적용하고 결과를 비교할 수 있어야 했다. 매치메이킹 시스템을 개발하는 일에는 이런 기준을 바꿔 가며 검토할 수 있도록 데이터와 계산, 설정과 결과 기록을 연결하는 작업도 포함됐다.