하이브리드 Matchmaking 엔지니어링: Call of Duty의 Queue 분할로 본 현대 게임 Matchmaking Architecture
핵심 요약
Call of Duty: Black Ops 7의 Queue 분할 사례를 통해 현대 게임 Matchmaking Architecture의 핵심인 Latency, Skill Delta, Queue Duration 간의 트레이드오프와 동적 완화 공식을 분석합니다. C# 기반의 동적 규칙 확장 엔진 구현과 함께 분산 Ticket Locking, Server Allocation 오케스트레이션 등 백엔드 인프라 구축 시 발생하는 주요 기술적 난제를 다룹니다. 클라이언트 Ping 측정, Pool 파편화 방지, 비동기 프로비저닝 등 대규모 동시 접속자를 안정적으로 처리하기 위한 5가지 실무 아키텍처 Best Practice를 제시합니다.
Activision이 Call of Duty: Black Ops 7에서 플레이어베이스를 SBMM(Skill-Based Matchmaking), Classic Connection-Based, Hybrid의 세 가지 Matchmaking Queue로 분할한다고 발표했을 때, 게임 개발계의 오랜 Backend 엔지니어링 논쟁이 다시 수면 위로 떠올랐습니다. 경쟁형 타이틀에서 플레이어를 어떻게 매칭할 것인가의 문제는 단순한 게임 디자인 선호도의 문제가 아닙니다. 이는 서브 밀리초(sub-millisecond) 단위의 네트워크 제약, 수학적 스킬 분산(Skill Variance), Pool 파편화, Cloud Compute 비용의 균형을 맞추어야 하는 복잡한 game matchmaking architecture 문제입니다.
Matchmaking 시스템을 여러 개의 독립된 Queue로 나누는 것은 표면적으로는 단순한 플레이어 옵션 기능처럼 보입니다. 하지만 실제로는 Backend 인프라의 엔지니어링 오버헤드를 2배, 3배로 증가시킵니다. 동시 접속 플레이어(CCU)를 여러 Queue로 나누면 Ticket 밀도가 급격히 떨어지고, 밀도가 낮은 지역에서는 Queue 대기 시간이 기하급수적으로 늘어나며, Server Allocation 알고리즘의 Churn 현상이 심화됩니다.
본 아티클에서는 SBMM과 Connection-First Matchmaking의 기술적 트레이드오프를 분석하고, 동적 하이브리드 Queue 확장 공식의 수학적 원리를 파헤치며, Ticket 처리를 위한 실제 Backend C# 코드를 살펴봅니다. 그리고 유연하게 Scale되는 회복 탄력성 높은 Matchmaking Pool 구축 방법을 알아보겠습니다.
Matchmaking의 불변 트릴레마 (The Immutable Matchmaking Trilemma)
모든 현대 게임 Matchmaking Architecture는 서로 상충하는 세 가지 변수에 의해 제약되는 최적화 문제를 해결해야 합니다.
- Latency (RTT): 플레이어 클라이언트와 할당된 Dedicated Server 인스턴스 간의 왕복 시간(밀리초 단위).
- Skill Delta ($\Delta$MMR): 특정 로비 내 플레이어 간 스킬 격차(MMR, Elo, TrueSkill 등의 수학적 수치).
- Queue Duration ($T_{queue}$): 유효한 Match Ticket이 활성화된 Server Allocation으로 전환되기 전까지 플레이어가 Queue에서 대기하는 총 시간.
Latency (RTT)
/ \
/ \
/ Ideal \
/ Match \
/ \
Skill Delta (ΔMMR) --------------- Queue Duration (T_queue)
이 세 가지 변수 중 어느 두 가지는 나머지 하나를 완전히 희생함으로써 쉽게 최적화할 수 있습니다.
- Low Latency + Low Skill Delta: 매칭 엔진이 동일한 Cloud Data Center 근처에 살면서 완벽하게 동일한 실력을 가진 드문 플레이어를 찾아야 하므로 Queue 시간이 길어집니다.
- Low Queue Time + Low Skill Delta: Matchmaker가 동일한 실력의 상대방을 찾기 위해 전 세계로 지리적 탐색 반경을 넓혀야 하므로 Latency가 높아집니다.
- Low Queue Time + Low Latency: Matchmaker가 실력 지표와 상관없이 가장 가까운 클라이언트를 즉시 매칭하므로 스킬 편차가 커집니다(전형적인 "Connection-First" 공공 매치 방식).
Black Ops 7과 같은 타이틀이 세 가지 독립된 Queue 모드를 도입하면, 하위 Matchmaking Architecture는 파편화된 메모리 Pool 상에서 세 개의 병렬 규칙 평가 루프를 유지해야 합니다.
만약 특정 지역(예: 새벽 4시의 남아메리카 지역)의 동시 접속자 수(CCU)가 2,000명 이하로 떨어진다면, 이 플레이어들을 세 개의 Pool로 분할할 경우 각 Queue의 지역 밀도는 고작 수백 명 수준으로 축소됩니다. 그 결과, Connection-First Queue는 Low-Ping Dedicated Server를 찾지 못하고, SBMM Queue는 대기 상태에 머물게 됩니다.
SBMM vs Ping-First vs Hybrid Queue 구조 해부
수백만 개의 Match Ticket을 처리할 수 있는 Backend를 구축하려면, 각 아키텍처 모델이 내부적으로 어떻게 작동하는지 이해해야 합니다.
1. Connection-Based (Ping-First) Architecture
Connection-First 엔진에서는 스킬 매트릭스가 이차적인 요소이거나 완전히 무시됩니다. 핵심 목표는 네트워크 저하(Jitter, Packet Loss, 높은 RTT)를 최소화하는 것입니다.
- Client Ping Probing: Queue에 진입할 때, 게임 클라이언트는 지역 Edge Gateway(예:
us-east-1,eu-central-1,ap-southeast-1)로 ICMP 또는 UDP Ping 비콘을 전송합니다. - Ping Vector Generation: 클라이언트는
[ us-east: 24ms, us-west: 78ms, eu-central: 142ms ]와 같은 Latency Vector를 생성하여 Matchmaking Payload에 첨부합니다. - Spatial Indexing: Matchmaker는 허용 가능한 Latency 임계값(예: $RTT < 50ms$)을 기준으로 플레이어를 특정 지역 해시에 버킷팅합니다.
네트워크 토폴로지가 매치 생성을 결정하므로, 플레이어 Search Bucket을 예측할 수 있어 단순한 FIFO(First-In, First-Out) 공간 Queue를 사용해 $O(1)$ 시간 복잡도로 Ticket을 처리할 수 있습니다.
2. Skill-Based Matchmaking (SBMM) Architecture
SBMM은 다차원 가우시안 분포(예: TrueSkill 2)나 커스텀 Elo 변형 알고리즘을 사용해 플레이어의 실력을 모델링함으로써 매치의 공정성을 최우선으로 합니다. 주요 입력값에는 승/패 비율, 킬/데스 비율, 분당 데미지, 최근 성적 트렌드 등이 포함됩니다.
- Distance Evaluation: Matchmaker는 $N$차원 스킬 공간에서 후보 플레이어 Vector 간의 유클리드 거리(Euclidean Distance) 또는 마하트라노비스 거리(Mahalanobis Distance)를 계산합니다.
- Sorting Cost: 단순 FIFO Queue에 의존할 수 없습니다. 허용 가능한 스킬 분산 $\sigma$ 내의 후보를 빠르게 찾기 위해 Ticket 프로필의 Sorted Set이나 Spatial Tree(예: KD-tree)를 유지해야 합니다.
- Search Space Contraction: 플레이어의 실력이 높아질수록(예: 상위 0.5% 플레이어) 매칭 가능한 후보 Pool이 급격히 줄어듭니다. 이로 인해 시스템은 Ticket을 무한정 대기시키거나 스킬 기준 엄격도 매개변수를 완화해야 합니다.
3. Dynamic Hybrid Architecture
플레이어에게 고정된 Queue 선택을 강제하는 대신, 최근의 Production Backend는 Dynamic Hybrid 모델을 주로 구현합니다. 이 구조에서는 모든 Match Ticket이 엄격한 SBMM 및 Low Latency 조건으로 시작합니다. $T_{queue}$가 증가함에 따라, 규칙 감쇄(Rule Decay) 함수가 허용 가능한 Skill Delta($\Delta MMR$) 및 Latency 한계($RTT_{max}$)를 지속적으로 확장합니다.
$$\Delta MMR_{allowed}(t) = \Delta MMR_{base} + \alpha \cdot t^{\gamma}$$
$$RTT_{allowed}(t) = \min\left(RTT_{max_cap}, RTT_{base} + \beta \cdot \lfloor t / \Delta t_{step} \rfloor\right)$$
여기서 $\alpha$와 $\beta$는 확장 계수이고, $\gamma$는 지수 곡선의 기울기를 제어하며, $t$는 경과된 Queue 시간(초)입니다.
이러한 동적 완화 방식을 활용하면 무한 Queue 대기 현상을 방지하면서도 피크 타임 CCU 구간에서 높은 매치 퀄리티를 유지할 수 있습니다.
코드 구현: Dynamic Rule Expansion Engine
다음은 현장에서 검증된 Dynamic Matchmaking Rule Expansion Engine의 C# 구현체입니다. 이 서비스는 유입되는 Ticket을 활성화된 Queue Pool과 비교 평가하여 실시간 Ping 호환성 매트릭스와 동적 MMR 변산성 제한을 계산합니다.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Horizon.Matchmaking.Engine
{
public class MatchmakingTicket
{
public string TicketId { get; set; } = Guid.NewGuid().ToString();
public string PlayerId { get; set; }
public double SkillRating { get; set; } // Elo/MMR 수치
public Dictionary<string, int> RegionalPingMap { get; set; } = new(); // 예: "us-east": 28
public DateTime EnqueuedAtUtc { get; set; }
}
public class DynamicMatchRules
{
public double MaxAllowedMmrDelta { get; set; }
public int MaxAllowedPingMs { get; set; }
}
public class MatchmakingEvaluator
{
private const double BaseMmrDelta = 50.0;
private const double MaxMmrCap = 600.0;
private const int BasePingMs = 35;
private const int AbsoluteMaxPingMs = 180;
private const double PingStepIntervalSeconds = 4.0;
/// <summary>
/// 경과된 Queue 시간에 따라 Ticket의 확장된 매칭 기준을 계산합니다.
/// </summary>
public DynamicMatchRules GetRelaxedRules(MatchmakingTicket ticket, DateTime currentUtc)
{
double elapsedTime = (currentUtc - ticket.EnqueuedAtUtc).TotalSeconds;
// 고실력 플레이어도 매칭될 수 있도록 스킬 허용 범위를 지수적으로 확장
double mmrExpansion = Math.Pow(elapsedTime, 1.35) * 4.5;
double calculatedMmrDelta = Math.Min(MaxMmrCap, BaseMmrDelta + mmrExpansion);
// Latency 허용 범위를 이단계(Step-wise)로 분산 확장 (잦은 서버 이동 방지)
int pingSteps = (int)Math.Floor(elapsedTime / PingStepIntervalSeconds);
int calculatedPingLimit = Math.Min(AbsoluteMaxPingMs, BasePingMs + (pingSteps * 15));
return new DynamicMatchRules
{
MaxAllowedMmrDelta = calculatedMmrDelta,
MaxAllowedPingMs = calculatedPingLimit
};
}
/// <summary>
/// 두 Ticket을 하나의 매치 세션으로 성립시킬 수 있는지 평가합니다.
/// </summary>
public bool CanMatchTickets(MatchmakingTicket ticketA, MatchmakingTicket ticketB, DateTime currentUtc, out string selectedRegion)
{
selectedRegion = null;
DynamicMatchRules rulesA = GetRelaxedRules(ticketA, currentUtc);
DynamicMatchRules rulesB = GetRelaxedRules(ticketB, currentUtc);
// 1. Skill Delta 평가
double actualMmrDelta = Math.Abs(ticketA.SkillRating - ticketB.SkillRating);
if (actualMmrDelta > rulesA.MaxAllowedMmrDelta || actualMmrDelta > rulesB.MaxAllowedMmrDelta)
{
return false; // 현재 Queue 대기 시간에 비해 스킬 격차가 너무 큼
}
// 2. 공통 Data Center Ping 호환성 평가
int lowestCombinedPing = int.MaxValue;
foreach (var (region, pingA) in ticketA.RegionalPingMap)
{
if (ticketB.RegionalPingMap.TryGetValue(region, out int pingB))
{
// 매칭은 두 플레이어 모두의 동적 Ping 제한 조건을 만족해야 함
if (pingA <= rulesA.MaxAllowedPingMs && pingB <= rulesB.MaxAllowedPingMs)
{
int combinedPing = pingA + pingB;
if (combinedPing < lowestCombinedPing)
{
lowestCombinedPing = combinedPing;
selectedRegion = region;
}
}
}
}
return selectedRegion != null;
}
}
}
이 구현의 주요 기술적 특징:
- 비대칭적 규칙 충족 (Asymmetric Rule Satisfaction): 이 메서드는 두 플레이어 모두의 확장 조건이 충족되는지 확인합니다(
pingA <= rulesA.MaxAllowedPingMs && pingB <= rulesB.MaxAllowedPingMs). 90초 동안 대기한 다른 플레이어 때문에 Queue에 들어온 지 2초밖에 안 된 신규 플레이어가 150ms Ping 서버로 끌려가는 현상을 방지합니다. - 이단계 Ping 스텝 (Discrete Ping Stepping): 연속 곡선 대신 이산적인 시간 단계(
PingStepIntervalSeconds)를 사용하여 Latency 제한을 확장합니다. 이를 통해 매 틱 루프마다 불필요하게 Edge Router가 재할당되는 것을 방지합니다. - 공간 교집합 (Spatial Intersection): 지역 Map 간의 Dictionary Key 교집합을 기반으로 두 플레이어의 합산 왕복 Latency가 가장 낮은 Data Center를 선택합니다.
Backend Infrastructure Challenges: 동시성, Lock 경합 및 Dedicated Server 프로비저닝
Matchmaking 알고리즘을 단독으로 작성하는 것은 간단합니다. 진짜 엔지니어링 난관은 수십만 개의 동시 처리 Ticket을 다루는 분산 노드 클러스터 환경에서 이 시스템을 운영할 때 발생합니다.
[Player Clients]
│ (WebSockets / Low Latency)
▼
[Ingress Load Balancers]
│
▼
[Distributed Ticket Pool (e.g., Redis Cluster / Memory Grid)]
│
┌────┴────────────────────────┬────────────────────────┐
▼ ▼ ▼
[Worker Node 1] [Worker Node 2] [Worker Node 3]
│ │ │
└────┬────────────────────────┴────────────────────────┘
│ (Atomic Claim / Lua Mutex Lock)
▼
[Server Orchestration API] ──► Agones / Fleet 인스턴스 할당
1. 분산 Ticket Lock 경합 (Distributed Ticket Lock Contention)
여러 개의 병렬 Matchmaker 프로세스가 동일한 중앙 Ticket Pool을 스캔할 때 Race Condition이 필연적으로 발생합니다. 서로 다른 두 개의 Worker Thread가 동시에 Ticket #1042를 평가하고 완전히 다른 두 개의 로비로 매칭을 시도할 수 있습니다.
이를 해결하기 위해 개발자는 매치 할당을 발행하기 전에 분산 원시 구조(예: Redis Lua 스크립트 또는 Memory Grid Atomic 연산)를 사용해 원자적(Atomic) Lock 점유를 실행해야 합니다. Ticket이 다른 Match Worker에 의해 Lock 상태가 되면, 해당 Thread는 즉시 상태를 해제하고 백트래킹합니다.
2. 고빈도 실시간 통신 (High-Frequency Real-Time Communication)
Matchmaking 상태 업데이트는 단순 HTTP Polling 방식으로는 불필요한 연결 핸드셰이크가 발생하여 막대한 Compute 자원을 소모하게 됩니다. 예상 Queue 시간과 동적 Ping 탐색 상태를 클라이언트에 전달하려면 Backend에서 지속적인 이중 채널 WebSocket 또는 gRPC Stream을 유지해야 합니다.
Multiplayer 상태 관리에 비효율적인 Polling 루프를 사용하고 있다면, 실시간 Backend 환경에서 HTTP Polling 대신 Unreal Engine WebSocket을 도입하는 방법 가이드를 참고하시기 바랍니다.
3. Server Allocation Handshake & Fleet Provisioning
플레이어를 매칭하는 것은 전체 과정의 절반에 불과합니다. 유효한 Ticket 그룹이 형성되면 다음과 같은 절차가 진행됩니다.
- Matchmaker가 Dedicated Server Orchestration Layer(예: Agones, 커스텀 Kubernetes Controller)에 요청을 보냅니다.
- 지정된 시간 제한(보통 $< 1500ms$) 내에 선택된 Data Center에서 유효한 게임 서버 인스턴스를 확보하거나 할당해야 합니다.
- 서버가 구동되어 UDP Listening Port를 바인딩하고 IP/Port 주소 Payload를 반환합니다.
- Matchmaker가 해당 접속 정보를 모든 클라이언트의 WebSocket으로 전송합니다.
분산 Ticket Pool을 구축하고, Lock 경합을 처리하며, 지역별 Socket 클러스터를 관리하고, Dedicated Server 인프라의 라이프사이클을 수동으로 오케스트레이션하려면 수개월의 인프라 개발 시간이 소요됩니다.
바로 이 지점에서 horizOn은 엔지니어링 오버헤드를 대폭 줄여줍니다. Redis Ticket Store를 직접 구성하거나, 커스텀 Agones 클러스터 래퍼를 작성하고, Server Fleet 스케일링 스크립트를 관리할 필요 없이 horizOn은 완전 관리형 초저지연 Matchmaking Queue와 Server Fleet Orchestration을 즉시 제공합니다. 매칭 규칙 세트만 작성하면, horizOn이 전 세계 분산 처리, 원자적 Ticket Locking, 자동 Server Allocation을 매끄럽게 처리합니다.
현대적인 Game Matchmaking Architecture 구축을 위한 5가지 Best Practice
경쟁형 슈팅 게임을 개발하든 인디 캐주얼 아케이드 타이틀을 제작하든, 검증된 아키텍처 원칙을 준수해야 합니다.
1. Ticket 제출 전 Client Ping Vector 수집 의무화
Data Center와의 근접성을 판단할 때 절대 클라이언트 IP 기반 Geo-IP 조회에 의존하지 마세요. Geo-IP 데이터베이스는 Edge Routing 면에서 부정확하며 실시간 ISP 병목을 반영하지 못합니다. Enqueue 엔드포인트를 호출하기 전에 게임 클라이언트가 모든 지역 엔드포인트로 UDP Ping을 직접 측정하도록 강제해야 합니다.
2. Pool 파편화 방지
동속 접속자 수(CCU)가 충분히 보장되지 않는다면 소규모 게임 모드를 위해 Queue를 세분화하지 마세요. 게임 모드, 맵 선호도, Matchmaking 엄격도에 따라 플레이어베이스를 나누면 Pool의 질이 급격히 저하됩니다. 특정 지역의 Queue당 active CCU가 1,000명 이하로 떨어지면 동적 단일 Queue Fallback 모드로 자동 전환하세요.
3. Server Provisioning과 Match Evaluation의 디커플링
Matchmaker Thread가 Fleet Orchestration Layer와 비동기로 작동하도록 설계하세요. 가상 서버 인스턴스가 부팅되는 동안 Matchmaker Worker 루프를 Block 상태로 대기시키면 안 됩니다. Non-blocking Pub/Sub Message Queue를 활용해 서버 할당을 요청하고, 인스턴스의 정상 상태가 확인되면 접속 Payload를 전달하세요.
4. 스마트 절전(Hibernation) 기법으로 대기 서버 비용 최적화
Matchmaking 수요는 피크 타임에 예측 불가능하게 급증하고 오프 피크 타임에는 급격히 감소합니다. 빈 상태로 대기하는 수백 개의 게임 서버 인스턴스는 막대한 운영 비용 손실을 발생시킵니다. 동적 Fleet Warm-up 및 Server Hibernation 패턴을 도입하세요. 대기 서버 비용 최적화에 대한 기술 분석은 비용 낭비 없는 서버 구축 및 Fortnite 서버 최적화 제안 분석 글을 참고하세요.
5. 높은 Latency 환경에서의 Netcode 및 Replication 벤치마크
아무리 뛰어난 Matchmaking Architecture라도 오프 피크 시간대에는 중등도 Latency($100-120ms$) 조건에서 플레이어를 매칭해야 할 때가 있습니다. 서버 Netcode가 클라이언트 예측(Client Prediction), Lag Compensation, State Reconciliation을 철저히 수행하여 패킷 지연을 유연하게 처리할 수 있는지 확인하세요. 높은 Ping 환경에서 플레이어 위치가 어긋나거나 순간 이동하는 현상이 발생한다면 Unreal Engine Multiplayer에서 플레이어 위치 Desync 문제 해결 방법 가이드를 확인하세요.
요약 및 향후 과제
Call of Duty: Black Ops 7에서 SBMM, Connection-First, Hybrid Queue를 선택할 수 있게 한 Activision의 결정은 Matchmaking Architecture가 플레이어 만족도에 얼마나 중요한지를 보여줍니다. 그러나 Queue를 분할하려면 압도적인 플레이어 밀도, 저지연 Socket Networking, 동적 규칙 감쇄 알고리즘, 원자적 Ticket 처리가 필수적입니다.
Multiplayer 게임을 개발 중이라면 Backend 인프라, Socket Server, Fleet Allocation 로직을 처음부터 작성하느라 수개월을 허비하지 마세요. horizOn을 통해 확장 가능한 Multiplayer Game Backend, 자동화된 Matchmaking, Server Orchestration을 단 몇 분 만에 배포하는 방법을 확인해 보세요. 지금 horizOn을 무료로 체험하거나 horizOn 문서를 둘러보고 Backend 워크플로우를 가속화하세요.