> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/matchmaker-in-depth.md).

# 심층 살펴보기

Edgegap의 노코드 매치메이커 개념을 자세히 알아보고 필요에 맞게 사용자 지정하세요.

{% hint style="info" %}
도움이 필요하시면 [디스코드를 통해 문의해 주세요](https://discord.gg/MmJf8fWjnt). 실시간 게임 지원은 저희의 [티켓 시스템](https://edgegap.atlassian.net/servicedesk/customer/portal/3).
{% endhint %}

## ✔️ 소개

매치 기반 게임에서 매치메이킹의 일반적인 목표는:

* **다른 플레이어를 찾는 것** 지역, 지연, 실력 또는 게임 매개변수와 같은 기준에 따라;
* **서버를 검색하는 것** 사용 가능한 수용량\[또는 핑, 지역, 실력, 지도, 모드]에 따라 참가하기 위해;
* **새 서버를 시작하는 것** 기존 서버가 가득 찼거나 플레이어 기준을 충족하지 않을 경우.

플레이어 경험을 최우선으로 하며, 우리의 핵심 목표를 정의합니다:

* 높은 매치 채움률과 소셜 기능 통합(그룹으로 친구와 함께 플레이),
* 제어된 매치 품질(낮은 지연, 공유된 선호도)로 빠른 매치,
* 전 세계적으로 이용 가능한 신뢰할 수 있고 예측 가능한 매치메이킹 프로세스.

{% hint style="success" %}
또는 플레이어가 **지속적(항상 온라인) 서버를 선택하도록** 목록에서 [서버 브라우저](/docs.edgegap.com-ko/learn/server-browser.md).
{% endhint %}

**5분 이내에 시작하고 모든 기능을 무료로 테스트하세요. 신용카드는 필요 없습니다.**

더 강력한 전용(전용) 클러스터가 필요할 때 업그레이드하세요. Edgegap과의 기본 통합 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md) 최고 수준의 핑을 제공합니다. 플레이어가 어디에 있든 상관없이.

{% hint style="info" %}
무료 티어는 재시작할 때마다 3시간의 실행 시간을 허용합니다. 매치메이커는 테스트에 적합한 제한된 리소스의 공유 인프라에서 실행됩니다. **공개 출시 후에는 매치메이커가 24시간 연중무휴로 실행되어야 합니다.**
{% endhint %}

각 매치메이커에는 세 가지 필수 개념이 있습니다:

* [#hosting-cluster](#hosting-cluster "mention") - Edgegap이 완전 관리 및 운영하는 기본 서버 인프라.
* [#configuration](#configuration "mention") - 매치메이커의 작동 방식을 정의하는 규칙 및 설정의 집합.
* 🌐 서비스 인스턴스 **-** 클러스터에서 24시간 연중무휴로 실행되는 실시간 매치메이킹 서비스로, Configuration을 사용해 플레이어를 서로 매칭하고 배포(서버) 할당을 생성합니다.

{% hint style="success" %}
[매치메이커 버전을 자주 업데이트하세요](#changelog) 하여 **새로운 기능과 버그 수정을 활용하세요.**
{% endhint %}

## ▶️ 매치메이킹 시작

**빠르게 시작하세요 - SDK 시작 샘플을 게임에 추가하세요**:

* 언리얼 엔진 [개발자 도구](/docs.edgegap.com-ko/unreal-engine/developer-tools.md#integration-kit):
  * [문서를 읽어보세요](https://egik.betide.studio/) Betide Studios 제공,
  * [Fab 마켓플레이스에서 설치](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) (개인 용도는 무료),
  * [간단한 예제 블루프린트 가져오기](https://blueprintue.com/blueprint/m33u1okj/) (매치메이킹)을 자신의 필요에 맞게 커스터마이즈하세요.
* Unity [개발자 도구](/docs.edgegap.com-ko/unity/developer-tools.md#software-development-kit):
  * [Unity 패키지 관리자를 사용하여 무료로 패키지 설치](https://github.com/edgegap/edgegap-unity-sdk),
  * [시작 가이드와 완전한 예제를 살펴보세요](/docs.edgegap.com-ko/unity/matchmaking.md).

게임 통합을 사용자 지정하고, 문제를 해결하며, 최적화하는 데 도움이 되도록 매치메이킹 프로세스를 알아보세요:

<figure><img src="/files/4d7ce3eff4a2b9dba9597685ccf5a209fe2243df" alt=""><figcaption><p>매치메이킹 순서</p></figcaption></figure>

1. [플레이어 인증](#authenticate) - 해적판 복제품이 온라인으로 플레이하는 것을 방지합니다,
2. [로비 생성](#create-group) - 친구들과 함께 참여하고 플레이어/매치 선호 사항을 공유합니다,
3. [**그룹 구성**](#group-up) **- 로비를 매치메이킹 그룹으로 등록합니다,**
4. [**매치 찾기**](#find-match) **- 준비를 마치고 매치(새 매치 또는 기존 매치)를 찾기 시작합니다,**
   1. 서버 할당 및 티켓 주입 - 서버는 몇 초 후 자동으로 할당됩니다,
5. [**연결 및 인증**](#connect-to-server) **- 게임 서버에 보안 연결을 시도합니다,**
   1. 신원 확인 - 서버가 타사 토큰을 사용해 게임 클라이언트의 신원을 검증합니다,
   2. 플레이어 허용 또는 추방 - 서버가 플레이어의 참가 허용 여부를 결정합니다.

### 인증

모든 요청은 다음을 전송해야 합니다 `Authorization`  HTTP 헤더에 비밀 **인증 토큰:**

<pre><code>Authorization: <a data-footnote-ref href="#user-content-fn-1">xxxxxxxx-e458-4592-b607-c2c28afd8b62</a>
</code></pre>

{% hint style="warning" %}
**토큰은 비밀로 안전하게 보관하세요! Edgegap 직원은 절대 토큰을 요청하지 않습니다.**
{% endhint %}

{% hint style="success" %}
**이 토큰은 Edgegap API 접근 권한을 부여하지 않으므로 게임 클라이언트에 안전하게 포함할 수 있습니다.**
{% endhint %}

개별 플레이어는 클라이언트와 서버에서 사용할 수 있는 티켓 ID로 식별할 수 있습니다. 선택적으로 다음을 사용하여 사용자 지정 프록시로 사용자 지정 인증이나 제한을 추가하세요. [#server-to-server-api](#server-to-server-api "mention") API.

### 그룹 구성

그룹(파티)을 생성하면 플레이어가 친구들과 같은 팀과 서버에 참여하도록 보장할 수 있습니다.

{% hint style="success" %}
준비됨으로 표시된 그룹을 생성하여 [#find-match](#find-match "mention") 신속하게 **그룹 구성원이 없는 솔로 플레이어로**.
{% endhint %}

<figure><img src="/files/f4ffbbfe25dbe62e3b5df41bd9bc323ec500fdfd" alt=""><figcaption><p>그룹 수명 주기 활동 다이어그램</p></figcaption></figure>

#### 로비 및 그룹

게임 디자인에 플레이어가 제어하는 매치메이킹 선호 사항(예: 캐릭터 선택, 난이도, 맵 등)을 설정하는 로비 서비스가 필요하다면 사용하세요. 플레이어가 로비에 들어오고 나가면서 나중에 매치를 찾을 준비를 위해 매치메이킹 그룹도 업데이트합니다.

{% hint style="success" %}
**로비 서비스에 시간을 들일 수 없나요?** 플레이어가 Discord나 DM을 통해 그룹 ID를 공유하도록 안내하세요.
{% endhint %}

<table><thead><tr><th width="390">게임 디자인 - 기능 / 요구사항</th><th>매치 전 로비</th><th>매치메이커 그룹</th></tr></thead><tbody><tr><td><a data-footnote-ref href="#user-content-fn-2">친구를 초대해 나와 함께 플레이</a></td><td>✅</td><td>✅</td></tr><tr><td>내 플레이어/매치 선호 사항 수정</td><td>✅</td><td>❌</td></tr><tr><td>다른 로비 멤버의 선호 사항 보기</td><td>✅</td><td>❌</td></tr><tr><td>사용자 지정 키-값 데이터를 저장하고 관리</td><td>✅</td><td>❌</td></tr><tr><td>내가 플레이할 준비가 되었음을 그룹 구성원에게 알림</td><td>❌</td><td>✅</td></tr><tr><td>매치메이킹 진행 상황을 표시하고 매치를 찾기</td><td>❌</td><td>✅</td></tr><tr><td>플레이어/그룹에 대한 팀 할당을 가져오기</td><td>❌</td><td>✅</td></tr><tr><td>게임 서버 연결 세부 정보를 가져오기</td><td>❌</td><td>✅</td></tr></tbody></table>

우리의 크로스플랫폼 매치메이커는 모든 상용 및 사용자 지정 로비 서비스를 지원합니다:

<table><thead><tr><th>로비 서비스(서드파티)</th><th width="120" data-type="checkbox">언리얼 엔진</th><th width="75" data-type="checkbox">유니티</th><th width="50" data-type="checkbox">PC</th><th width="90" data-type="checkbox">콘솔</th><th width="65" data-type="checkbox">VR/XR</th><th width="100" data-type="checkbox">모바일</th></tr></thead><tbody><tr><td><a href="https://dev.epicgames.com/docs/game-services/lobbies-and-sessions/lobbies/lobbies-intro">Epic Online Services 로비</a><br>(Epic Games)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://partner.steamgames.com/doc/features/multiplayer/matchmaking#friends">Steamworks 로비</a><br>(Valve Corporation)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://heroiclabs.com/docs/nakama/concepts/groups/">Nakama 그룹</a><br>(Heroic Labs)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://learn.microsoft.com/en-us/gaming/playfab/community/associations/groups/quickstart">PlayFab 로비</a><br>(Microsoft)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://docs.braincloudservers.com/learn/key-concepts/multiplayer/lobbies/#lobby-experience">brainCloud 로비</a><br>(bitHeads)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://developer.apple.com/documentation/gamekit/connecting-players-with-their-friends-in-your-game">Gamekit Friends</a><br>(Apple)</td><td>true</td><td>true</td><td>false</td><td>false</td><td>false</td><td>true</td></tr><tr><td>사용자 지정 로비<br>(귀사)</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr></tbody></table>

로비 소유자(초대를 보내는 플레이어)는 매치메이킹 그룹도 생성해야 합니다.

**공유 로비 데이터에 그룹 ID를 저장하세요**, 그러면 다른 로비 멤버가 타사 로비와 연결된 매치메이킹 그룹을 쉽게 찾고 참여할 수 있습니다. 그룹에 초대된 플레이어는 그룹 ID를 사용하여 **멤버십(참여)을 생성하고**, 또한 **안전하게 저장합니다** [**매치메이킹 속성**](#matchmaking-rules)**.**

{% hint style="warning" %}
**그룹이 매치메이킹을 시작하면 참여할 수 없습니다.** [#abandon-queue](#abandon-queue "mention") 그리고 새 그룹을 생성해야 합니다.
{% endhint %}

#### 핑 최적화

만약 [#configuration](#configuration "mention") 포함한다면 [`지연 시간` 규칙](#rule-example-elo_rating) 모든 그룹 멤버가 자신의 [핑 비콘](/docs.edgegap.com-ko/learn/orchestration/ping-beacons.md) 측정값을 **먼 지역의 플레이어가 매칭되는 것을 방지하고** 또는 훨씬 더 높거나 낮은 핑(지연 시간)을 방지합니다.

{% code title="예시 게임 클라이언트 핑 측정값(밀리초)" %}

```json
{
  "Chicago": 224.4,
  "Frankfurt": 23.2,
  "Tokyo": 167.4
}
```

{% endcode %}

#### **대기열 이탈**

그룹 소유자는 그룹을 삭제할 수 있으며, 그러면 모든 그룹 멤버십이 자동으로 삭제됩니다. 매치메이킹 시작 후 그룹을 삭제하면 모든 멤버십이 취소되고, 잠시 후 삭제됩니다.

그룹 멤버(소유자 제외)는 이전까지 언제든지 자신의 멤버십을 삭제(그룹 탈퇴)할 수 있습니다 [#find-match](#find-match "mention"). 이후 멤버십을 삭제하면 전체 그룹의 매치메이킹이 취소됩니다.

{% hint style="info" %}
매치메이킹이 취소되면 멤버는 [자동으로 매치메이킹에서 제거되고](#matchmaking-profiles) 멤버십을 통해 알림을 받습니다 `status:CANCELLED`  다음 상태 폴링 응답에서.
{% endhint %}

취소된 후 그룹이 매치메이킹을 다시 시작하려면 그룹 소유자가 그룹을 다시 생성하고, 새 그룹 ID를 멤버에게 공유한 뒤, 멤버들이 멤버십을 다시 생성하도록 해야 합니다.

**매치를 찾으면 그룹은 삭제할 수 없습니다** (`409 충돌`), 그리고 [자동으로 제거됩니다](#connect-to-server). 플레이어가 연결할 시간을 어느 정도(예: 60초) 허용한 뒤에야 플레이어 이탈로 간주해야 합니다.

서버가 플레이어를 이탈자로 표시하면, 다음을 할 수 있습니다:

* 이탈자를 AI 캐릭터로 대체하여 즉시 매치를 시작하거나,
* 또는 [백필](#backfill-match) 을 생성하여 이탈자를 대체할 새 플레이어를 찾거나,
* 또는 게임 디자인이 가변 플레이어 수를 허용한다면 이탈자를 대체하지 않고 진행합니다.

### 매치 찾기

매치를 찾기 시작하려면 모든 멤버와 소유자가 자신을 준비됨으로 표시해야 합니다.

{% hint style="success" %}
그룹 소유자가 **즉시 매치메이킹을 시작하도록 하려면 생성 시 멤버십을 준비됨으로 표시하세요**. 소유자가 자신을 준비됨으로 표시하면 모두가 준비되었으므로 매치메이킹이 시작됩니다.
{% endhint %}

{% hint style="info" %}
최상의 경험을 위해, **게임 내 UI를 사용하여 플레이어에게 상태 업데이트를 제공하세요**.
{% endhint %}

**모든 플레이어는 정기적인 간격으로 자신의 멤버십을 폴링해야 합니다** (권장 3\~5초) 매치메이킹 시작 시점을 감지하고, 게임 내 UI를 통해 매치메이킹 진행 상황을 전달하기 위해.

플레이어는 **자신의 멤버십과 그룹 ID를 영구적으로 저장해야 합니다**, 게임 클라이언트 충돌 시에도 게임을 다시 시작하고 매치메이킹 진행 상황을 잃지 않고 재개할 수 있도록 합니다.

다음 조건을 준수하면서 같은 팀에 배치할 수 있는 충분한 플레이어를 찾으면, [#matchmaking-rules](#matchmaking-rules "mention"), 플레이어는 멤버십 응답에서 다음으로 알림을 받습니다 `status:TEAM_FOUND`.

이 단계에서 멤버십을 삭제하면 모든 그룹 멤버십이 취소되고 같은 팀에 할당된 다른 모든 그룹은 `status:SEARCHING` .

팀은 그룹 간 겹치는 값(또는 `number_difference` 의 경우 평균)을 사용하여 다른 팀과 계속 매치메이킹하며, 충분한 팀이 구성될 때까지 진행됩니다. 멤버십은 응답으로 이를 표시합니다  `status:MATCH_FOUND` , 이는 [배포가 시작되고 있음을 의미합니다](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment).

**매치메이커는 매치 충원율을 최대화하는 것을 목표로 하며, 다음까지는 `MATCH_FOUND` 로 진행하지 않습니다:**

1. 구성된 최대 팀 크기로 충분한 팀이 매칭되었거나,
2. 또는 [#rule-expansion](#rule-expansion "mention") 정의된 AND 확장 시간이 도달했으며, AND 구성된 최소 팀 크기로 충분한 팀이 매칭된 경우,
3. 또는 구성된 티켓 만료 시간이 경과했고 구성된 최소 팀 크기로 충분한 팀이 매칭된 경우.

구성된 티켓 만료 전까지 어느 시나리오도 성공하지 못하면 그룹과 티켓이 취소됩니다.

{% hint style="info" %}
테스트 중 대기 시간이 길게 느껴지거나 덜 인기 있는 지역의 플레이어와 함께하나요? 더 짧은 티켓 만료 기간(예: 30초)을 설정하고 만료 시 클라이언트 측에서 그룹(또는 티켓)을 다시 생성하세요.
{% endhint %}

티켓 만료는 그룹(또는 플레이어)이 팀에 매칭될 때마다 자동으로 초기화됩니다.

{% hint style="success" %}
저장 `team_id`  및 `match_id` 를 게임 백엔드에 저장해 게임 내에서 팀 멤버 정보를 표시하세요.
{% endhint %}

{% hint style="info" %}
모든 플레이어는 **고유한 티켓 ID를 받으며, 이를 사용하여** [#authenticate](#authenticate "mention") **게임 서버에서 사용할 수 있습니다.**
{% endhint %}

플레이어가 매칭되어 게임 서버에 할당되면 해당 티켓은 자동으로 삭제됩니다. 이후 대기열을 이탈한 플레이어는 `status:HOST_ASSIGNED`  다음으로 대체될 수 있습니다 [백필](#backfill-match).

플레이어가 받으면 `status:HOST_ASSIGNED`  다음으로 진행합니다 [#connect-to-server](#connect-to-server "mention").

### 서버에 연결

매치를 찾은 후 몇 초가 지나면 멤버십은 다음으로 진행됩니다 `status:HOST_ASSIGNED`  이는 귀하의 [배포가 이제 준비되었고 게임 서버가 초기화 중임을 나타냅니다](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-3.-deployment-ready).

각 플레이어는 자신의 `ticket_id`  및  `할당`  그리고 다음을 사용하여 연결을 시도합니다 [**FQDN**](#user-content-fn-3)[^3] **(배포 URL)** 그리고 **외부 포트**. 이 시점에는 게임 서버가 아직 초기화 중일 수 있으므로 **플레이어는 연결을 여러 번 다시 시도해야 합니다**, 일반적인 서버 초기화 시간을 넘길 때까지:

{% tabs %}
{% tab title="언리얼 엔진" %}
하려면 **PIE(에디터)에서 연결** 개발 및 테스트 중에는 틸드 키를 누르고 `~`  그리고 다음을 입력하세요 `open {URL}:{port}`  그리고 에디터가 맵을 로드할 때까지 기다립니다.

하려면 **게임 클라이언트 빌드에서 연결** (실제 운영 환경에서는) 다음을 시도하세요

* 언리얼 엔진 [⚡ 통합 키트](https://docs.edgegap.com/learn/unreal-engine-games/developer-tools#integration-kit):
  * [Fab 마켓플레이스에서 설치](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) (개인용은 무료),
  * [간단한 예제 블루프린트를 가져와](https://blueprintue.com/blueprint/m33u1okj/) 필요에 맞게 사용자 지정하세요.

{% hint style="success" %}
연결 실패 또는 검은 화면이 발생한 경우 다음을 참고하세요 [문제 해결 가이드](/docs.edgegap.com-ko/unreal-engine.md#troubleshooting-and-faq).
{% endhint %}
{% endtab %}

{% tab title="유니티" %}
하려면 **Unity 에디터를 연결하세요** 또는 **게임 클라이언트** 클라우드 배포에 다음을 입력하세요:

* **배포** **URL** 서버 IP를 가리키며, 보통 다음에 있습니다 `NetworkManager` 컴포넌트.
* **외부 포트** 다음에 매핑되며 [서버의 내부 리슨 포트](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md#port-mapping), 보통 Transport 컴포넌트에 있습니다.

{% hint style="success" %}
연결 시간 초과 또는 기타 문제가 발생하면 다음을 참고하세요 [문제 해결 가이드](/docs.edgegap.com-ko/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
저희는 플레이어에게 매치 확인을 요구하지 않습니다. 가능한 한 짧은 시간 안에 게임플레이에 진입하고, 높은 매치 충원율을 제공하며, 큐 회피와 매치 취소를 최소화하는 것을 목표로 하기 때문입니다.
{% endhint %}

게임 클라이언트는 **게임 재시작 사이에 할당 ID를 영구적으로 저장해야 하며**, 게임 클라이언트가 충돌한 경우 연결 정보를 가져와 재연결을 시도할 수 있도록 해야 합니다.

### 백필 매치

선택적으로, 일부 게임에는 다음과 같은 특수 매치메이킹 요구 사항이 있을 수 있습니다:

* 새로운 플레이어가 진행 중인 게임에 참여할 수 있도록 허용(친구 또는 "랜덤"),
* 서버 시작 후 이탈한 플레이어(이탈자)를 교체하여 매치를 다시 시작하지 않도록 함,
* 관전자가 토너먼트나 친구의 경기(e스포츠)에 참가하여 관전할 수 있도록 허용,
* 더 큰 서버에 플레이어를 집중시켜 더 많은 사회적 상호작용을 제공(MMO).

백필은 **현재 서버에 연결된 플레이어를 나타내는 서버 소유 티켓입니다.** 이를 통해 새로 추가된 플레이어가 현재 플레이어와 매칭될 때 매치메이킹 규칙을 준수하게 됩니다.

{% hint style="warning" %}
[심층 살펴보기](/docs.edgegap.com-ko/learn/matchmaking/matchmaker-in-depth.md#backfill-match) Seat/Match 세션을 대체하기 위해. Matchmaker는 Default 세션만 지원합니다.
{% endhint %}

<figure><img src="/files/47837c533d96b73ac8e1e55fc7d20b934d50dfe4" alt=""><figcaption><p>백필 시나리오 시각화</p></figcaption></figure>

{% hint style="success" %}
**백필은 무시합니다** `player_count`  **규칙을 적용하지 않으며, 항상 정확히 하나의 그룹과 매칭합니다**. `backfill_group_size`  라운드 로빈 전략으로 팀 수용 인원을 제어하여, 팀을 균등하고 통제된 방식으로 채웁니다.
{% endhint %}

**성공적인 백필을 완료하는 단계는 다음과 같습니다:**

1. 서버는 플레이어가 부족한 각 팀마다 하나의 백필을 생성하며, 다음 값들을 사용합니다:
   * 실제 `할당`  에서 가져온 데이터 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#injected-environment-variables) (배포).
   * 현재 연결된 플레이어의 `티켓`:
     * 에서 [심층 살펴보기](/docs.edgegap.com-ko/learn/matchmaking/matchmaker-in-depth.md#injected-variables) (매치메이커), 이전 백필의 `assigned_ticket` 응답, 또는 특정 플레이어에 맞게 조작된 모의 데이터,
     * 교체 `backfill_group_size`  값을 가능한 그룹 크기로 [사용 가능한 수용 인원까지](#user-content-fn-4)[^4],
2. 게임 클라이언트는 새 티켓(멤버십)을 생성하고 다음을 포함합니다 `backfill_group_size`  값:
   * `"1"`  플레이어가 혼자 매치메이킹하는 경우.
   * [`"2"`  플레이어가 총 2x명으로 구성된 매치메이킹 그룹의 일부인 경우](#user-content-fn-5)[^5].
   * `"new"`  플레이어가 진행 중인 게임에 참여하는 것 외에도 새 게임 시작을 활성화한 경우.
3. 게임 클라이언트는 계속해서 [심층 살펴보기](/docs.edgegap.com-ko/learn/matchmaking/matchmaker-in-depth.md#find-match) 그리고 플레이어를 일치하는 백필과 매칭합니다.
4. 백필된 그룹이 팀을 완전히 채우지 못하면, 서버는 새로 백필된 플레이어의 티켓으로 이 과정을 반복하여 더 많은 플레이어를 추가하고 원하는 팀 규모에 도달할 수 있습니다.

{% hint style="success" %}
백필은 팀 크기 규칙을 무시하며 항상 1x 백필과 1x 그룹을 매칭합니다. **백필하고만 매칭하고 대기열의 다른 플레이어와의 매칭을 비활성화하려면 다음을 설정하세요 `min_team_size: 999999` .**
{% endhint %}

<details>

<summary>🥛 백필 예시 (백필 쇼케이스)</summary>

```json
{
  "profile": "backfill-example",
  "attributes": {
    "할당": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "몬트리올",
        "country": "캐나다",
        "continent": "북아메리카",
        "administrative_division": "퀘벡",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "attributes": {
        "beacons": {
          "뉴욕": 12.2,
          "로스앤젤레스": 45.3,
          "파리": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "attributes": {
        "beacons": {
          "뉴욕": 21.0,
          "로스앤젤레스": 30.2,
          "파리": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": null
}
```

</details>

<details>

<summary>🥛 백필 할당 예시 (백필 쇼케이스)</summary>

```json
{
  "profile": "backfill-example",
  "attributes": {
    "할당": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "몬트리올",
        "country": "캐나다",
        "continent": "북아메리카",
        "administrative_division": "퀘벡",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "attributes": {
        "beacons": {
          "뉴욕": 12.2,
          "로스앤젤레스": 45.3,
          "파리": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "attributes": {
        "beacons": {
          "뉴욕": 21.0,
          "로스앤젤레스": 30.2,
          "파리": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": {
    "profile": "backfill-example",
    "player_ip": "244.13.201.244",
    "attributes": {
      "beacons": {
        "뉴욕": 30.2,
        "로스앤젤레스": 10.5,
        "파리": 123.9
      },
      "backfill_group_size": [
        "new",
        "1"
      ]
    },
    "id": "cqg0bg550h7uujd77khg",
    "group_id": "e0cf41c0-f88f-456e-a032-03b1d6821a9a",
    "created_at": "2024-08-20T13:38:08.251393+00:00",
    "status": "HOST_ASSIGNED"
  }
}
```

</details>

{% hint style="info" %}
를 참고하세요 [미러 좌석 관리](https://docs.edgegap.com/docs/sample-projects/mirror-on-edgegap#bonus-seat-sessions-management) 및 [FishNet 좌석 관리](https://docs.edgegap.com/docs/sample-projects/fishnet-on-edgegap#bonus-seat-sessions-management) 용 **플레이어 연결 모니터링**.
{% endhint %}

게임 서버 초기화가 완료되면, **서버는 다음을 해야 합니다**:

* **각 새 플레이어에 대해 이탈 타이머를 시작합니다.** 로딩 장면/레벨로 연결된 플레이어에게 로딩 진행 상황을 표시하는 것을 권장합니다. 완전한 3D 장면, 로비와 유사한 소셜 UI, 또는 진행 표시줄이 있는 로딩 화면이 될 수 있습니다.
* **새 플레이어 연결이나 기존 플레이어의 이탈을 시간에 따라 추적하세요**:
  1. 새 플레이어는 인증을 위해, 그리고 자신의 연결을 매치메이커에 매핑하기 위해 서버에 티켓 ID를 알려야 합니다 [#injected-variables](#injected-variables "mention") 또는 `assigned_ticket` (백필된 경우).
  2. 서버 수명 전반에 걸쳐 사용되지 않은 플레이어 용량(이탈자)을 위한 새 백필을 생성하세요.
  3. 만료된 백필은 `ticket_expiration_period`.
* **남아 있는 백필을 정리(삭제)하세요** 한 번 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-5.-deployment-stopped](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-5.-deployment-stopped "mention"):
  * Unity - [`OnApplicationQuit`](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/MonoBehaviour.OnApplicationQuit.html) 콜백 또는 사용자 지정 게임 종료 콜백,
  * Unreal Engine - [`OnWorldDestroyed`](https://forums.unrealengine.com/t/call-function-before-quit-game/344954/2) , [`PreExit`](https://forums.unrealengine.com/t/event-on-close/298087/2) , 또는 사용자 지정 게임 종료 콜백.

{% hint style="info" %}
)과 각 내부 포트에 대한 외부 포트가 할당됩니다. [C#의 GetEnvironmentVariable](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getenvironmentvariable?view=net-8.0) 또는 [C++의 GetEnvironmentVariable](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/GenericPlatform/FGenericPlatformMisc/GetEnvironmentVariable) 변수 값을 얻기 위해.
{% endhint %}

유효한 서버 할당과 최소 하나의 티켓이 제공되기만 하면 어떤 프로필이든 백필에 사용할 수 있습니다. 최소 예시는 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md#backfill-showcase) 를 참고하세요.

## ⚙️ 구성

매치메이커 API는 새 매치메이커(또는 빠른 재시작)를 만들 때 지정한 JSON 구성에서 생성됩니다. 다양한 규칙과 확장을 가진 여러 프로필을 지정할 수 있습니다:

{% hint style="success" %}
를 참고하세요 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md) SDK와 자세한 예시 시나리오는
{% endhint %}

<details>

<summary>🍀 간단한 예시 (최소 권장 설정)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "simple-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "<a data-footnote-ref href="#user-content-fn-6">my-game-server</a>",
        "version": "<a data-footnote-ref href="#user-content-fn-7">2024.01.30-16.23.00-UTC</a>"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 2
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
</code></pre>

</details>

<details>

<summary>🏁 고급 예제 (완전한 예제 구성)</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "allowed_cors_origins": [
    "https://*.my-game-server.com"
  ],
  "profiles": {
    "advanced-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 125
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          },
          "selected_game_mode": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "elo_rating": {
              "max_difference": 150
            },
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "60": {
            "elo_rating": {
              "max_difference": 200
            }
          },
          "180": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            },
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f95b">🥛</span> 백필 구성 예시</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "backfill-example": {
      "ticket_expiration_period": "30s",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
```

</details>

<details>

<summary>⚔️ 경쟁 게임 예시</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "casual-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "180": {
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    },
    "competitive-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "versus_ranks": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    },
    "challenger-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🤝 협동 게임 예시</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "cooperative-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_difficulty": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "player_level": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 10
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "player_level": {
              "max_difference": 20
            }
          },
          "60": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 4
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🎈 소셜 게임 예제</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "social-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "attributes": {
              "team_count": 1,
              "min_team_size": 50,
              "max_team_size": 50
            },
            "type": "player_count"
          },
          "beacons": {
            "attributes": {
              "difference": 125,
              "max_latency": 150
            },
            "type": "latencies"
          },
          "selected_mode": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "15": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "match_size": {
              "team_count": 1,
              "min_team_size": 20,
              "max_team_size": 50
            }
          },
          "30": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 10,
              "max_team_size": 50
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 50
            }
          }
        }
      }
    }
  }
}
```

</details>

{% hint style="warning" %}
실행 중인 매치메이커를 편집하면 **빠른 재로드가 트리거되며**, 모든 티켓이 삭제되고 짧은 다운타임이 발생합니다.
{% endhint %}

<details>

<summary><code>애플리케이션 구성은 프로필 XYZ에 대해 유효하지 않습니다.</code></summary>

* 다음을 찾을 수 없습니다 [앱 및 버전](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md)를 확인해 주세요 `애플리케이션`  값들.

</details>

<details>

<summary><code>'2024.01.30-16.23.00-UTC'용 Docker 이미지가 캐시되어 있지 않습니다.</code></summary>

[**🌟 종량제 요금제로 업그레이드하기**](https://app.edgegap.com/user-settings?tab=memberships) **잠금 해제하려면** [**캐싱을 통한 즉시 배포**](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment)**.**

* 4GB 이상의 캐시되지 않은 이미지는 배포에 더 오랜 시간이 걸릴 수 있으며, 그로 인해 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-4.-deployment-error](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-4.-deployment-error "mention")입니다. 서버 이미지 크기 최적화를 고려하세요 ([언리얼 엔진](/docs.edgegap.com-ko/unreal-engine.md#optimize-server-build-size) / [Unity](/docs.edgegap.com-ko/unity.md#optimize-server-build-size)).
* 어쨌든 진행할 수 있으나 배포 시간을 테스트할 것을 권장합니다.

</details>

### 프로필(대기열) <a href="#matchmaking-profiles" id="matchmaking-profiles"></a>

프로필은 동일한 매치메이커 버전을 공유하는 완전히 분리된 매치메이킹 대기열을 나타냅니다. 각 매치메이커에 대해 **원하는 수의 프로필을 구성할 수 있습니다.** 플레이어 기반을 여러 프로필로 분리하면 플레이어의 대기 시간이 더 길어질 수 있습니다.

각 매치메이커 프로필은 [앱 버전](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md) 을 템플릿으로 사용해 새 배포(서버)를 시작합니다.

{% hint style="success" %}
일부 게임 모드에는 더 많은 vCPU/RAM이 필요할 수 있으며, 특히 더 많은 플레이어 수를 지원하는 경우 그렇습니다. 각 **매치메이커는 여러 프로필을 포함할 수 있으며**, 각 프로필은 조정된 리소스를 가진 앱 버전과 연결됩니다.
{% endhint %}

### 규칙 <a href="#matchmaking-rules" id="matchmaking-rules"></a>

모든 플레이어와 그룹은 매치메이킹 대기열에 참여하고  `초기` 규칙을 먼저 사용해 매치를 찾습니다.

경로 `.rules.initial` 의 각 항목은 규칙을 나타내며, 여기서:

* **key** 는 규칙의 이름을 원하는 대로 지정하는 문자열 값입니다. 예: `match_size` 및
* **value** 는 표준 규칙 세트를 따르는, 규칙의 유형과 속성을 정의하는 객체입니다.

{% hint style="info" %}
호스트 할당을 시작하고 배포를 시작하거나 찾으려면 모든 규칙이 동시에 충족되어야 합니다.
{% endhint %}

**연산자(규칙 유형)**

**`player_count`** 는 할당을 시작하기 위해 매칭되어야 하는 플레이어 수를 정의하는 특수 규칙입니다.

{% hint style="warning" %}
규칙 `player_count`  **은 필수이며 한 번만 정의할 수 있습니다** 초기 구성 규칙에서.
{% endhint %}

매치메이커는 항상 지정된 `max_team_size` :

1. 까지 매치 충원율을 최대화하려고 하며, 최대 팀 크기에 도달하면 즉시 매치가 만들어집니다,
2. 그렇지 않으면 플레이어는 대기열에서 [확장](#rule-expansion) (또는 만료)가 임박할 때까지 매치를 채우기 위해 기다립니다,
3. 직전 [확장](#rule-expansion) (또는 만료) 시점에, 부분 매치가 가능하다면(≥ min 및 < max 팀 크기), 이 매치는 같은 확장 단계의 모든 플레이어로 만들어집니다(다른 규칙이 통과한다는 가정하에).

{% hint style="success" %}
협동, 자유 대전, 또는 비대칭 팀 크기 게임 모드의 경우, `"team_count": 1` .
{% endhint %}

팀 수는 경쟁 게임을 위해 여러 개의 균형 잡힌 팀을 구성하도록 설정할 수 있습니다:

* **그룹 속성은 평균/겹침으로 계산됩니다** 그룹의 **플레이어 속성의,**
* **팀 속성은 평균/겹침으로 계산됩니다** 팀의 **그룹 속성의.**

각 팀 크기가 4명으로 고정되었다고 가정하면:

<figure><img src="/files/8ca9a5f55034ebaed5de71c81fe50e2ba9d033c1" alt=""><figcaption><p>예시 매치 시나리오</p></figcaption></figure>

{% hint style="info" %}
**그룹은 넘치지 않게 팀으로 매칭되며,** 팀에 전체 그룹을 수용할 충분한 용량이 있는 경우에만 그렇습니다.
{% endhint %}

**`string_equality`** 는 정확히 같은 문자열 값을 가진 플레이어를 매칭합니다.

<details>

<summary>규칙 예시: <code>selected_game_mode</code></summary>

`selected_game_mode`  규칙은 플레이어를 대소문자를 구분하여 매칭합니다:

:white\_check\_mark: Alice + Bob + Dave는 매칭될 수 있지만,

:x: Alice + Erin, 또는 Charlie + Frank는 절대 매칭되지 않습니다.

| "Free For All" | "Capture The Flag" | "capture the flag" |
| -------------- | ------------------ | ------------------ |
| 앨리스            | 에린                 | 프랭크                |
| 밥              | 찰리                 |                    |
| 데이브            |                    |                    |

</details>

**`number_difference`** 서로 간 절대 수치 차이가 있는 플레이어를 매칭합니다.

<details>

<summary>규칙 예시: <code>elo_rating</code></summary>

`elo_rating`  위 규칙은 `"max_difference": 50` 처음에:

:white\_check\_mark: Alice + Bob은 매칭될 수 있거나, Bob + Charlie는 매칭될 수 있지만,

:x: Alice + Bob + Charlie는 절대 매칭되지 않습니다.

<figure><img src="/files/ead9e6bbe196d6c5b5f83fe030751e2807e35bf9" alt=""><figcaption></figcaption></figure>

</details>

**`지연 시간`** 플레이어 매치의 핑을 최적화하는 특별한 규칙입니다:

* 지연 시간이 높은 지역(임계값 초과)을 제거하여 클라이언트-서버 지연 시간을 줄이고,
* 지연 시간이 비슷한 플레이어를 그룹화하여 매치 공정성을 향상시킵니다(차이 이하).

<details>

<summary>규칙 예시: <code>비콘</code></summary>

`비콘` 다음으로 구성된 규칙 `"difference": 100, "max_latency": 200`  은 다음과 매칭됩니다:

:white\_check\_mark: Alice와 Bob은 매칭될 수 있습니다:

* Tokyo는 제외됩니다(>200 ms),
* Chicago의 지연 시간은 절대 차이 100 ms 이내입니다.

<table><thead><tr><th width="180">비콘 도시</th><th width="80">매치</th><th width="132">abs(A - B) [ms]</th><th width="164">Alice [ms]</th><th width="164">Bob [ms]</th></tr></thead><tbody><tr><td>Chicago</td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td>75.0</td><td>12.3</td><td>87.3</td></tr><tr><td>Los Angeles</td><td><span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-8">113.2</a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>145.6</td><td>32.4</td></tr><tr><td><del>Tokyo</del></td><td>해당 없음</td><td>해당 없음</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-9"><del>253.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr></tbody></table>

:x: Alice와 Charlie는 절대 매칭되지 않습니다:

* 두 플레이어 모두에 대해 < 200 ms 지연 시간을 가진 비콘이 없습니다,
* Alice는 북아메리카 - 일리노이주에 살고,
* Charlie는 아시아 - 일본에 삽니다.

<table><thead><tr><th width="180">비콘 도시</th><th width="80">매치</th><th width="132">abs(A - B) [ms]</th><th width="164">Alice [ms]</th><th width="164">Charlie [ms]</th></tr></thead><tbody><tr><td><del>Chicago</del></td><td>해당 없음</td><td>해당 없음</td><td>12.3</td><td><a data-footnote-ref href="#user-content-fn-9"><del>215.6</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>Los Angeles</del></td><td>해당 없음</td><td>해당 없음</td><td>145.6</td><td><a data-footnote-ref href="#user-content-fn-9"><del>238.3</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>Tokyo</del></td><td>해당 없음</td><td>해당 없음</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>24.2</td></tr></tbody></table>

</details>

{% hint style="warning" %}
규칙 `지연 시간`  입니다 **선택 사항이며 초기 구성에서 한 번만 정의할 수 있습니다** 규칙.
{% endhint %}

모든 비콘에 대해 핑이 높은 일부 플레이어는 다음과 같은 이유로 인해 ISP[^10] 문제나 느린 연결(예: 무선/모바일)로 인해 지연이 발생하고 다른 사람들의 게임 경험을 저하시킬 수 있습니다. 이 문제를 완화하려면:

* 허용 지연 최대값과 차이를 점진적으로 확장하십시오(참조 [고급 예제 구성](/docs.edgegap.com-ko/learn/matchmaking.md#advanced-example)),
  * 핑이 높은 플레이어는 매치를 찾는 데 평소보다 더 오래 기다려야 할 수 있습니다.
* 또는 플레이어가 수동으로 지역을 선택하여 측정을 재정의하도록 허용하고, 선택한 지역에 대해서만 가짜 핑 값을 전송하도록 할 수 있습니다(예: 빠른 매치를 위해 25ms),
  * 이것은 플레이어의 팀원 및 상대방의 플레이어 경험에 부정적인 영향을 미칠 수 있습니다.

{% hint style="info" %}
**높은 비콘 핑이 항상 높은 서버 핑으로 이어지는 것은 아닙니다**배포는 비콘보다 더 많은 위치에서 이용 가능합니다. 비콘은 글로벌 커버리지와 신뢰성을 우선으로 실시간으로 오케스트레이션됩니다.
{% endhint %}

{% hint style="success" %}
보기 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md) 위해 **우리의 SDK를 사용한 자동 핑 측정**.
{% endhint %}

{% hint style="danger" %}
비콘은 실시간으로 자동 재조정되며 기존 비콘을 추가/제거/교체합니다. 클라이언트와 백엔드는 이를 고려하고 **매치메이킹 라운드마다 비콘 목록을 다시 불러와야 합니다**.
{% endhint %}

**`교집합`** 하나 이상의 겹치는 문자열 값을 가진 플레이어를 대소문자를 구분하여 매칭합니다.

<details>

<summary>규칙 예시: <code>selected_map</code></summary>

`selected_map` 위 규칙은 `"overlap": 1`  다음과 매칭됩니다:

:white\_check\_mark: Alice + Bob + Charlie는 매칭될 수 있거나, Alice + Bob + Dave는 매칭될 수 있지만,

:x: Alice + Bob + Charlie + Dave는 절대 매칭되지 않습니다.

<figure><img src="/files/b973337811b4f5fd90de3153bbb15fcf1fcad2a8" alt=""><figcaption></figcaption></figure>

</details>

#### 규칙 확장

선택적으로, **`확장은`**  대기열에서 보낸 일정 시간이 지난 후 규칙의 속성을 수정하여 제한을 완화하고 매칭될 수 있는 플레이어 풀을 확장하며, **그 결과 더 빠른 매치를 생성합니다**.

<details>

<summary>예시 시나리오: 확장</summary>

[처음에는 정확히 4명으로 구성된 1개 팀이 필요합니다(그룹으로 나뉠 수 있음)](/docs.edgegap.com-ko/learn/matchmaking.md#advanced-example) 다음과 함께:

* 같은(임의의 하나의) 비콘에 대해 최대 125ms의 지연 시간,
* 같은 비콘에 대해 최저/최고 값 사이의 지연 시간 차이가 125ms 이하,
* 최저 및 최고 랭킹 플레이어 간 실력 점수 차이가 50점 이하,
* 정확히 같은(대소문자 구분) 선택된 게임 모드,
* 플레이어들 사이에 최소 하나의 일치하는 맵 선택(대소문자 구분),
* 최소 하나의 일치하는 [백필 그룹 크기](#backfill-match) 값이 플레이어들 사이에 존재합니다.

위 예시에서는, **속성을 수정하여 검색 범위를 확장합니다** 이후:

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>30초:</td><td><ul><li>4명</li><li><strong>150 스킬 점수 범위</strong></li><li><strong>최대 250ms 지연</strong></li></ul></td></tr><tr><td>60초:</td><td><ul><li>4명</li><li><strong>200 스킬 점수 범위</strong></li><li>최대 250ms 지연</li></ul></td></tr><tr><td>3분(180초):</td><td><ul><li><strong>1~4명 플레이어</strong></li><li>200 스킬 점수 범위</li><li><strong>지연 무관</strong></li></ul></td></tr></tbody></table>

</details>

{% hint style="info" %}
어떤 규칙의 속성 확장도 **이전 값을 덮어씁니다** 해당 속성의.
{% endhint %}

{% hint style="success" %}
[**매치메이킹의 일반적인 함정에 대해 알아보세요**](https://edgegap.com/blog/how-session-fill-rate-affects-your-multiplayer-hosting-costs)**및** [**가이드를 통해 매치 채움률을 최적화하세요**](https://edgegap.com/blog/how-to-optimize-session-fill-rate-in-your-matchmaker)**.**
{% endhint %}

## 📌 주입된 변수

서버는 플레이어에 대한 세부 정보를 알아야 할 수 있습니다. 플레이어 속성, 결정된 매치 값 및 기타 값은 일반적인 항목과 함께 배포에 주입됩니다 [앱 및 버전](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md#injected-variables).

서식 없는 미리보기 **🏁 고급 예시 변수:**

```
MM_MATCH_PROFILE=advanced-example
MM_EXPANSION=initial
MM_TICKET_IDS=["cusfn10msflc73beiik0","cusfn18msflc73beiil0"]
MM_TICKET_cusfn10msflc73beiik0={"id":"cusfn10msflc73beiik0","created_at":"2025-02-21T22:17:42.3886970Z","player_ip":"174.93.233.25","group_id":"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":12.3,"LosAngeles":145.6,"Tokyo":233.2},"elo_rating":1337,"selected_game_mode":"quickplay","selected_map":["DustII","Airport","BankVault"],"backfill_group_size":["new","1"]}}
MM_TICKET_cusfn18msflc73beiil0={"id":"cusfn18msflc73beiil0","created_at":"2025-02-21T22:17:42.2548390Z","player_ip":"174.93.233.23","group_id":"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":87.3,"LosAngeles":32.4,"Tokyo":253.2},"elo_rating":1339,"selected_game_mode":"quickplay","selected_map":["Island","Airport"],"backfill_group_size":["new","1"]}}
MM_GROUPS={"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1":["cusfn10msflc73beiik0"],"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f":["cusfn18msflc73beiil0"]}
MM_TEAMS={"cusfn1gmsflc73beiim0":["b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","015d4dc8-6c79-4b5c-bbc6-f309b9787c8f"]}
MM_MATCH_ID=advanced-example_initial-2025-02-21T22:17:43.3886970Z
MM_INTERSECTION={"selected_map":["Airport"],"backfill_group_size":["new","1"]}
MM_EQUALITY={"selected_game_mode":"quickplay"}
```

{% hint style="info" %}
환경 변수는 **문자열화된 JSON으로 저장됩니다**, SDK 또는 사용자 지정 방법을 사용해 파싱하세요.
{% endhint %}

{% hint style="success" %}
**서버는 플레이어 연결을 그룹과 속성에 매핑할 수 있습니다** 플레이어가 서버에 티켓 ID를 전송한 후.
{% endhint %}

## 🧵 플레이어 추적

플레이어에게 문제가 발생하면, 서버 로그까지의 경로를 추적하는 것이 도움이 될 수 있습니다. 각 Matchmaker **배포** **는 할당된 플레이어 티켓 ID로 태그됩니다** 따라서 쉽게 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#filter-deployments) 및 찾을 수 있습니다 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#container-logs) 문제 해결에 도움이 되도록.

{% hint style="success" %}
**클라이언트 매치 기록 UI에 티켓 ID와 배포 ID를 표시하세요** 문제 해결 시 플레이어를 추적하기 위해.
{% endhint %}

{% hint style="info" %}
를 참고하세요 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#connection-quality) 배포 문제 해결에 대해 알아보세요.
{% endhint %}

## 👀 분석

코드나 설정 없이 매치메이커의 부하와 성능에 대한 인사이트를 얻으세요.

🌟 [**Matchmaker를 엔터프라이즈 티어로 업그레이드**](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list) **하여 매치메이킹 지표와 인사이트를 잠금 해제하세요:**

<figure><img src="/files/b89a3f1e78255f9052a239b97eb040eccddb6986" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/1f0532148f6d293835df42b949764a2791fd70cc" alt=""><figcaption></figcaption></figure>

## ☁️ 호스팅 클러스터

Matchmaker는 Edgegap이 24시간 연중무휴로 편리하게 호스팅하고 관리합니다.

목표에 가장 적합한 호스팅 옵션을 선택하세요:

* **무료 클러스터(공유)** 모든 기능을 테스트하고 디자인과의 시너지를 탐색하려면,
  * 3시간 후 자동으로 종료되며 테스트를 계속하려면 재시작이 필요합니다.
* **프라이빗 클러스터** **(전용)** 프로덕션 요구에 맞는 안정적인 환경을 보장하려면,
  * 지역을 선택하고 24시간 연중무휴 라이브 게임 지원을 받아 안심하고 출시하세요.

#### 프라이빗 클러스터 티어

현재 다음을 제공합니다 [3개의 프라이빗 클러스터 요금제](https://edgegap.com/resources/pricing#managed-infrastructure) 모두의 필요에 맞추기 위해:

<table><thead><tr><th width="160">요금제</th><th align="right">취미용 요금제</th><th align="right">스튜디오 요금제</th><th align="right">엔터프라이즈 요금제</th></tr></thead><tbody><tr><td>가장 적합한 대상</td><td align="right">애호가,<br>개인 개발자</td><td align="right">상업용 출시</td><td align="right">대규모 트래픽 출시</td></tr><tr><td>리소스</td><td align="right">1 vCPU + 2GB RAM</td><td align="right">6 vCPU + 12GB RAM</td><td align="right">18 vCPU + 48GB RAM</td></tr><tr><td>이중화</td><td align="right">가상 노드 1개</td><td align="right">가상 노드 3개</td><td align="right">가상 노드 3개</td></tr><tr><td>요청 제한(req/s)</td><td align="right">200</td><td align="right">750</td><td align="right">2,000</td></tr><tr><td>가격, 시간당</td><td align="right">$0.0312</td><td align="right"> $0.146</td><td align="right">$0.548</td></tr><tr><td><strong>가격, 30일</strong><br>(중단 없는 사용)</td><td align="right"><strong>$22.464</strong></td><td align="right"><strong>$105.12</strong></td><td align="right"><strong>$394.56</strong></td></tr></tbody></table>

한 번의 클릭으로 프라이빗 클러스터로 업그레이드하세요. 출시 후에도 플레이어 다운타임 없이 Private Cluster Tier를 변경할 수 있으며, [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention"). 관리형 클러스터는 공개 출시된 게임을 위해 Edgegap이 유지 관리하는 고가용성 서비스 호스팅과 24/7 실시간 지원을 제공합니다.

인스턴스의 리소스 요구 사항은 다음 요인에 따라 달라집니다:

* **플레이어 수** - 플레이어가 많을수록 티켓과 API 요청이 증가합니다,
* **플레이어당 요청 수** - 재시도가 빠를수록 서비스 부하가 증가하고 리소스를 소모합니다,
* **구성 복잡성** - 교차 규칙과 확장은 특히 부담이 큽니다,
* **평균 매치 지속 시간** - 세션이 짧을수록 플레이어가 매치메이킹에 더 자주 다시 참여하게 됩니다,
* **만료 및 제거 기간** - 오래된 티켓은 시간이 지남에 따라 쌓여 리소스를 소모합니다,
* **클라이언트 재시도 폴백 로직** - 지터가 있는 백오프로 재시도하면 트래픽 버스트 피크를 분산하는 데 도움이 됩니다.

{% hint style="warning" %}
**성공을 준비하고 출시 후 최적화하여, 출시일에 플레이어가 막히지 않도록 하세요.** 사용하세요 [개발자 도구](/docs.edgegap.com-ko/unity/developer-tools.md#matchmaking-sdk) 또는 **지수적 지터 백오프를 구현하세요** 높은 부하에서 복구하기 위해.
{% endhint %}

{% hint style="info" %}
저희 클러스터는 2.4 - 3.2 GHz의 클럭 속도를 가진 AMD/Intel CPU를 탑재한 클라우드 머신을 사용합니다.
{% endhint %}

## ⏩ 롤링 업데이트 <a href="#rolling-updates-and-ab-tests" id="rolling-updates-and-ab-tests"></a>

서버와 클라이언트 버전 간 호환성을 추적하는 것은 복잡할 수 있습니다. 안정적인 릴리스, 업데이트, 다운타임 또는 호환성 문제 방지를 위한 팁을 따르세요.

**재시작 후에도 Matchmaker URL과 인증 토큰은 항상 동일하게 유지됩니다.**

{% hint style="danger" %}
**개발 및 운영용으로 별도의 matchmaker를 만드세요** 안전하게 실험할 수 있는 환경을 위해.
{% endhint %}

#### ⚠️ **실서비스 전**

미리 matchmaker의 복사본을 여러 개 만들어 둘 것을 권장합니다: `초록`, `파랑` 및 `주황`. 업데이트를 배포할 때 사용 중인 matchmaker를 교체할 수 있습니다([블루/그린 전략](https://en.wikipedia.org/wiki/Blue%E2%80%93green_deployment)).

**다운타임을 방지하기 위해 각 인스턴스에 서로 다른 리전을 선택하세요** 지역별 장애 발생 시.

<figure><img src="/files/fe628ec9cff62dee0aa0d4b79324704a918a28ac" alt=""><figcaption><p>블루/그린 DevOps 환경 예시</p></figcaption></figure>

#### **🔃 클라이언트 + 서버 업데이트**

**사전 요구 사항:** 이 섹션은 다음을 완료했다고 가정합니다 [#before-going-live](#before-going-live "mention").

하기 위해 **게임 클라이언트 + 서버 업데이트를 출시하려면**, 다음을 수행할 수 있습니다:

1. 새 서버 앱 버전 준비 `v1.2.0-rc` Edgegap에서:
   1. 컨테이너 레지스트리에 새 이미지 태그를 푸시합니다 `t1.2.0`,
   2. 새 앱 버전 만들기 `v1.2.0-rc`,
2. 다음으로 개발 테스트를 수행합니다 [새 앱 버전을 배포하여](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. 게임 엔진의 에디터를 제공된 URL + 외부 포트에 연결하고,
3. 사용하지 않는 matchmaker 업데이트 `파랑` 새 이미지 태그에 연결합니다 `t1.2.0`,
   1. 새 앱 버전에 캐싱을 활성화합니다 `v1.2.0-rc` , 이 버전에 캐시를 활성화하면 이미지가 버전에도 캐시되도록 보장합니다 `v-blue`  같은 태그를 참조하므로,
   2. 버전의 캐싱 표시가 `v1.2.0-rc`  에 도달할 때까지 기다립니다 :green\_circle: 초록,
4. 새 게임 클라이언트를 업데이트하세요 `c2` 새 버전을 사용하도록 `v-blue` 티켓을 생성할 때:
   1. 게임 클라이언트의 기본 URL과 Authorization 토큰을 업데이트하고,
5. 새 게임 클라이언트에 대해 QA 테스트와 최종 검증을 수행하세요 `c2`:
   1. 문제를 발견하고 해결했다면, 처음부터 과정을 반복하세요,
   2. matchmaker를 중지한 후 전 세계 ISP에 matchmaker DNS 변경 사항이 전파되도록 3\~7일을 기다리세요(빠른 재시작은 DNS 업데이트나 대기 기간이 필요하지 않습니다),
6. 새 게임 클라이언트 업데이트를 출시하세요 `c2` 게임 배포 플랫폼에서,
7. 새 게임 클라이언트가 `c2` 플레이어 기기에 배포될 시간을 주세요(보통 최대 3\~7일):
   1. 구버전 게임 클라이언트를 모니터링하세요 `c1`  배포를 사용하여 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#analytics),
8. Edgegap 계정의 사용하지 않는 리소스를 정리하세요:
   1. 이미지 태그 삭제 `t1.0.0` 컨테이너 레지스트리 용량을 확보하기 위해,
   2. 이미지 태그 삭제 `t1.1.0` 컨테이너 레지스트리 용량을 확보하기 위해,
   3. 사용 중인 `초록`  matchmaker를 끄면 다음 업데이트까지 청구가 중지됩니다.

{% hint style="success" %}
**다음 업데이트에서는**버전 번호를 올리고 교체하세요 `초록` 및 `파랑` 가이드의 키워드를.
{% endhint %}

#### **⚡ 서버 핫픽스**

**사전 요구 사항:** 이 섹션은 다음을 완료했다고 가정합니다 [#before-going-live](#before-going-live "mention").

하려면 **게임 클라이언트 업데이트 없이 서버 패치를 출시합니다**, 다음을 수행할 수 있습니다:

1. 새 서버 앱 버전 준비 `v1.2.0-rc` Edgegap에서:
   1. 컨테이너 레지스트리에 새 이미지 태그를 푸시합니다 `t1.2.0`,
   2. 새 앱 버전 만들기 `v1.2.0-rc`,
2. 다음으로 테스트와 검증을 수행합니다 [새 앱 버전을 배포하여](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. 게임 엔진의 에디터를 제공된 URL + 외부 포트에 연결하고,
   2. 문제를 발견하고 해결했다면, 처음부터 과정을 반복하세요,
   3. 새 앱 버전에 캐싱을 활성화합니다 `v1.2.0-rc` , 이 버전에 캐시를 활성화하면 이미지가 버전에도 캐시되도록 보장합니다 `v-green`  나중에, 같은 태그를 참조하므로,
   4. 버전의 캐싱 표시가 `v1.2.0-rc`  에 도달할 때까지 기다립니다 :green\_circle: 초록,
3. 버전 업데이트 `v-green`  새 이미지 태그에 연결합니다 `t1.2.0`,
   1. 새 매치는 업데이트된 태그로 자동으로 할당을 시작합니다 `t1.2.0`,
   2. 구버전 게임 클라이언트를 모니터링하세요 `c1`  배포를 사용하여 [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md#analytics),
4. Edgegap 계정의 사용하지 않는 리소스를 정리하세요:
   1. 이미지 태그 삭제 `t1.1.0` 컨테이너 레지스트리 용량을 확보하기 위해.

## 📗 API <a href="#matchmaking-api" id="matchmaking-api"></a>

클라이언트와 서버는 API를 직접 호출하거나 게임 엔진 SDK를 통해 호출할 수 있으며, 또한 다음을 참조하세요 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md).

{% hint style="info" %}
Unity/Android - 고려하세요 [원시 문자열 보간 사용](https://www.c-sharpcorner.com/article/convert-string-to-json-in-c-sharp/) 하드코딩된 JSON의 코드 제거를 방지하기 위해.
{% endhint %}

{% hint style="success" %}
**Swagger 웹 UI**서비스를 배포하면 OpenAPI 명세와 편리한 웹 UI가 생성됩니다. 브라우저에서 해당 URL을 열어 모든 API 엔드포인트를 확인하고 테스트하며 페이로드 예시를 검토하세요.
{% endhint %}

{% tabs fullWidth="false" %}
{% tab title="🍀 간단한 예제" %}
{% file src="/files/14b6ffa3890b93d8ed0e728d53fbdd52cbf89d2c" %}
{% endtab %}

{% tab title="🏁 고급 예제" %}
{% file src="/files/1f47150282ca483b287b4abc35b94c20bfbfc78a" %}
{% endtab %}

{% tab title="🎾 커스텀 로비" %}
{% file src="/files/83b4f884a59d4ddea02a2d55080e8329cbc3a72b" %}
{% endtab %}

{% tab title="🥛 백필 쇼케이스" %}
{% file src="/files/d5795a50d78bc6f2bea9bade7fecc64bf5e58a5b" %}
{% endtab %}

{% tab title="⚔️ 경쟁 게임" %}
{% file src="/files/8dfd24ddc148549052dd960968279664ccf05229" %}
{% endtab %}

{% tab title="🤝 협동 게임" %}
{% file src="/files/ef7a88bb123882b5a07342912092cd6213a73349" %}
{% endtab %}

{% tab title="🎈 소셜 게임" %}
{% file src="/files/2c48ab5797906a4f71bf9d27e796037d8abeaef1" %}
{% endtab %}
{% endtabs %}

API 명세 가져오기 [Scalar API 웹 클라이언트](https://client.scalar.com/workspace/default/request/default) 또는 [Swagger 편집기](https://editor.swagger.io/) 세부 정보를 확인하려면.

### 요청 제한

클러스터가 버스트 용량을 초과해 충돌하는 것을 방지하기 위해, 내부 부하 테스트를 바탕으로 초당 요청 수를 제한합니다 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md#advanced-example) 구성.

<table><thead><tr><th>API 엔드포인트</th><th width="130">무료 티어</th><th width="130">취미 사용자 티어</th><th width="130">스튜디오 티어</th><th width="130">엔터프라이즈 티어</th></tr></thead><tbody><tr><td><strong>전체 제한</strong></td><td><strong>100</strong></td><td><strong>200</strong></td><td><strong>750</strong></td><td><strong>2,000</strong></td></tr><tr><td>배포 만들기</td><td>5</td><td>10</td><td>30</td><td>30</td></tr><tr><td>비컨 목록</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>그룹 만들기<br>+ 티켓 만들기<br>+ 그룹 티켓 만들기</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>멤버십 읽기<br>+ 그룹 읽기<br>+ 티켓 읽기</td><td>10</td><td>120</td><td>450</td><td>1,300</td></tr><tr><td>백필 만들기</td><td>5</td><td>10</td><td>37</td><td>100</td></tr></tbody></table>

요청 제한은 다음 기준으로 표시됩니다 **지정된 API 엔드포인트 집합에 대한 결합된 초당 요청 수**.

{% hint style="warning" %}
게임 클라이언트가 응답을 받았을 때 요청을 재시도하지 않으면 `429 Too Many Requests` **배포에 플레이어가 누락될 수 있습니다** 짧은 버스트와 트래픽 피크 기간 동안.
{% endhint %}

#### 부하 테스트

실서비스와 유사한 환경에서의 부하 테스트에는 배포 호스팅 비용이 발생합니다. 각 등급과 관련된 리소스 및 가격은 [요금제 페이지에서](https://edgegap.com/resources/pricing#matchmaker).

{% hint style="warning" %}
**사용하세요** [**전용 클러스터**](#private-cluster-tiers) **를 스트레스 테스트에.** 무료 인스턴스는 개발 테스트용으로만 엄격히 제한됩니다.
{% endhint %}

부하 테스트를 설계할 때, **현실적인 플레이어 패턴을 고려해 주세요**:

| 현실적인 시나리오                                            | 비현실적인 트래픽 패턴                                     |
| ---------------------------------------------------- | ------------------------------------------------ |
| ✅ 플레이어들이 몇 시간에 걸쳐 점진적으로 게임에 참여하여 req/s가 증가합니다.       | ❌ 모든 플레이어가 협력하여 정확히 같은 초에 API를 호출합니다.            |
| ✅ 플레이어들은 재시도 사이에 점점 더 긴 시간을 기다립니다(예: 1초-5초-10초-10초). | ❌ 모든 플레이어가 `429 요청이 너무 많음`  응답을 받자마자 즉시 재시도합니다.  |
| ✅ 대부분의 플레이어는 짧은 시간(10\~60초) 안에 배정을 받고 폴링을 중단합니다.     | ❌ 모든 플레이어가 배정을 받은 후에도 정해진 시간 동안 계속 폴링합니다.        |
| ✅ 대부분의 플레이어는 새 세션을 시작하기 전에(시간이 걸리며) 게임을 마칩니다.        | ❌ 모든 플레이어가 서버 배정을 받은 직후 즉시 새로 세션을 재시작합니다.        |
| ✅ 피크 트래픽은 하루 약 6시간 동안 유지되며, 이후 일부 시간대에서 트래픽이 줄어듭니다.  | ❌ 피크 트래픽이 하루 24시간 내내 유지되며, 모든 플레이어가 밤낮없이 플레이합니다. |

#### 부하 시 동작

matchmaker가 높은 부하를 겪고 있다면:

* CPU가 스로틀링되면 매치메이킹이 느려질 수 있습니다,
* matchmaker가 메모리를 모두 사용하면 티켓 정보를 잃지 않고 재시작되며, 클라이언트가 지수 백오프를 구현해 버스트가 더 긴 기간에 걸쳐 분산되기를 기대합니다.

#### 교차 출처 리소스 공유(CORS)

제3자 배포 플랫폼(예: [itch.io](http://itch.io/)), 게임 클라이언트에서 Matchmaker로 요청을 보내면 다음이 발생할 수 있습니다 [교차 출처 리소스 공유](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 정책 위반. 대부분의 최신 웹 브라우저는 [사전 요청](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) 백엔드 서비스(Matchmaker)가 게임 클라이언트의 통신을 이해하고 수락하는지 확인합니다.

사전 검사 실패(보안상의 이유로 기본값)는 다음을 초래할 수 있습니다 [여러 CORS 관련 오류 중 하나](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin), 가장 흔하게는 `CORS 헤더 'Access-Control-Allow-Origin' 누락` .

이 오류를 해결하려면 다음을 추가하세요 **`allowed_cors_origin`** 매개변수를 구성에 추가하여 다음 중 하나를 수행하세요:

* 정확한 클라이언트 호스팅 도메인을 허용 목록에 추가합니다:

<details>

<summary>🍀 간단한 예시(특정 도메인 예시)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": [
    "https://dev.my-game-server.com",
    "https://prod.my-game-server.com"
  ],
  "profiles": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

* 또는 와일드카드 도메인(모든 하위 도메인 포함)을 허용 목록에 추가합니다:

<details>

<summary>🍀 간단한 예시(와일드카드 도메인 예시)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": ["https://*.my-game-server.com"],
  "profiles": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

{% hint style="info" %}
**Matchmaker 사전 요청에는 자격 증명이 필요하지 않습니다**, 도메인이 올바르게 구성되어 있다면.
{% endhint %}

### 서버 간 <a href="#server-to-server-api" id="server-to-server-api"></a>

매치메이킹 흐름에 대한 향상되거나 사용자 지정된 제어를 추가하세요 - 다음을 사용해 사용자 지정 프록시를 구현하세요 [관리형 클러스터](/docs.edgegap.com-ko/learn/advanced-features/managed-clusters.md) 또는 어떤 클라우드든 FaaS[^12] 컴퓨팅 플랫폼을 사용하여 다음 중 하나를 달성하세요:

* 치터 플래그, 스킬 레이팅 등 민감한 플레이어 속성을 첨부합니다,
* 게임 내에서 팀 및 매치 컨텍스트를 제공합니다 - 로딩 중에 아군과 상대를 표시합니다,
* 특정 엣지 케이스를 제한합니다 - 예: 한 번에 플레이어당 그룹 1개만 허용합니다,
* 캐싱 또는 API 요청 제한을 추가합니다 - 요청 수와 matchmaker 부하를 줄입니다,
* 로비-그룹 통합을 사용자 지정합니다 - 매치메이킹 전에 비대칭/역할 기반 로비를 생성합니다.

{% hint style="success" %}
**매개변수 포함 `player_ip`  멤버의 공용 IP 주소와 함께** 가능한 가장 낮은 플레이어 지연을 보장하고 다음의 이점을 활용하기 위해 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-server-score-strategy-best-practice](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-server-score-strategy-best-practice "mention").
{% endhint %}

{% hint style="info" %}
게임 클라이언트는 다음을 사용할 수 있습니다 [ipify.org](http://ipify.org/) 무료 서비스로 공용 IP를 찾을 수 있습니다. VPN은 공용 IP 주소를 숨길 수 있습니다.
{% endhint %}

<figure><img src="/files/7b191ec82d71ef9bc6029c9519051a3320890f2a" alt=""><figcaption><p>서버 간 매치메이킹 활동 다이어그램</p></figcaption></figure>

## 🚨 문제 해결

**귀하의 성공이 우리의 최우선입니다.** 맞춤 요청을 보내거나, 누락된 핵심 기능을 요청하거나, 의견을 전달하고 싶다면, [커뮤니티 Discord로 연락해 주세요](https://discord.gg/MmJf8fWjnt).

<details>

<summary><code>애플리케이션 구성은 프로필 XYZ에 대해 유효하지 않습니다.</code></summary>

* 다음을 찾을 수 없습니다 [앱 및 버전](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md)를 확인해 주세요 `애플리케이션`  값들.

</details>

<details>

<summary><code>'2024.01.30-16.23.00-UTC'용 Docker 이미지가 캐시되어 있지 않습니다.</code></summary>

[**🌟 종량제 요금제로 업그레이드하기**](https://app.edgegap.com/user-settings?tab=memberships) **잠금 해제하려면** [**캐싱을 통한 즉시 배포**](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment)**.**

* 4GB 이상의 캐시되지 않은 이미지는 배포에 더 오랜 시간이 걸릴 수 있으며, 그로 인해 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-4.-deployment-error](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-4.-deployment-error "mention")입니다. 서버 이미지 크기 최적화를 고려하세요 ([언리얼 엔진](/docs.edgegap.com-ko/unreal-engine.md#optimize-server-build-size) / [Unity](/docs.edgegap.com-ko/unity.md#optimize-server-build-size)).
* 어쨌든 진행할 수 있으나 배포 시간을 테스트할 것을 권장합니다.

</details>

<details>

<summary>새 matchmaker를 만들려고 할 때 왜 오류가 발생하나요?</summary>

* 오류를 읽어보세요. 식별자, 규칙 또는 연산자를 잘못 입력했을 수 있습니다. - 다음을 사용하세요 [JSONLint](https://jsonlint.com/) JSON 형식을 검증하세요. 쉼표나 괄호를 빠뜨렸을 수 있습니다. - 다음으로 문의하세요 [커뮤니티 Discord](https://discord.gg/MmJf8fWjnt) 도움을 요청해 주세요. 기꺼이 도와드리겠습니다. 🙏

</details>

<details>

<summary>왜 matchmaker가 3시간 후 자동으로 꺼졌나요?</summary>

* 무료 티어의 Matchmaker는 초기 테스트용이며 3시간 후 자동으로 꺼집니다. 테스트를 계속하려면 다음을 할 수 있습니다 [matchmaker를 재시작하세요](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).
* 무제한 실행을 위해 유료 티어로 업그레이드하는 것을 고려하세요.

</details>

<details>

<summary>왜 계정에서 두 번째 배포를 시작할 수 없나요?</summary>

* 무료 티어에서는 동시에 1개의 배포만 실행할 수 있습니다.
* 무제한 배포를 위해 유료 티어로 업그레이드하는 것을 고려해 주세요.

</details>

<details>

<summary>왜 무작위 시점에 할당/배포가 발생하나요, 무시하고 <code>player_count</code>?</summary>

* 귀하 또는 다른 팀원이 이전 테스트 세션에서 할당되지 않은 티켓을 만들었을 수 있습니다. 다음을 확인하세요 [matchmaker를 재시작하세요](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).

</details>

<details>

<summary>내 티켓이 다음 상태에 멈춰 있습니다 <code>SEARCHING</code> .</summary>

* 구성에 맞는 매칭 티켓을 충분히 만들었는지 확인하세요.

</details>

<details>

<summary>내 티켓이 다음 사이를 반복적으로 전환하며 멈춰 있습니다 <code>MATCH_FOUND</code> 및 <code>TEAM_FOUND</code> 반복적으로.</summary>

* 무료 티어 계정은 한 번에 1개 배포로 제한됩니다.
* 업그레이드하거나 현재 배포를 중지한 후 새 배포를 시작하는 것을 고려하세요.

</details>

<details>

<summary>내 티켓이 바로 다음으로 갑니다 <code>CANCELLED</code>.</summary>

* 티켓이 만료되었습니다. 새 티켓을 만들거나 테스트 목적으로 구성의 만료 기간을 늘리세요.

</details>

<details>

<summary>다음을 받습니다 <code>HTTP 404 Not Found</code> 티켓을 확인할 때.</summary>

* 티켓은 DELETE 요청으로 제거되었거나, 제거 기간에 도달해 삭제되었습니다(티켓 만료 후 시작되며, 구성에서 정의됨). 테스트 목적으로 새 티켓을 다시 만들거나 구성의 만료/제거 기간을 늘리세요.

</details>

<details>

<summary>내 matchmaker에 오류가 표시됩니다. 어떻게 해야 하나요?</summary>

* 개발 또는 테스트 인스턴스라면 먼저 matchmaker를 재시작해 보세요. - 문제가 있으면 다음으로 보고해 주세요 [커뮤니티 Discord](https://discord.gg/MmJf8fWjnt).
* 이 문제가 라이브 게임에 영향을 주는 경우, 다음을 생성하세요 [긴급 지원 요청](https://edgegap.atlassian.net/servicedesk/customer/portal/3).

</details>

## 🔖 변경 로그

#### 시맨틱 버전 관리

당사의 개발자 도구와 관리형 서비스는 공식 [시맨틱 버전 관리](https://semver.org/)을 사용하며, 이는 어떤 업데이트가 ✅ 안전한지(마이너, 패치)와 어떤 업데이트에 ⚠️ 호환성을 깨는 변경이 포함될 수 있는지(메이저)를 나타냅니다.

**버전이 출시되면, 절대 수정/변경되지 않습니다**.

구성 파일은 사용된 matchmaker 버전에 따라 검증됩니다. 규칙이 matchmaker 버전의 기능과 일치하는지 확인하세요.

{% hint style="info" %}
**가장 최신 matchmaker 버전은 `3.2.5`**. 이 페이지의 모든 예시는 최신 상태입니다.

다음을 주의 깊게 살펴보세요 [업데이트 및 공지](/docs.edgegap.com-ko/docs/release-notes.md). 또한 다음을 참조하세요 [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention").
{% endhint %}

{% hint style="warning" %}
**matchmaker 버전을 업그레이드하려면 - 중지, 편집, 재시작.** 빠른 재시작은 버전 변경을 적용하지 않습니다.
{% endhint %}

[^1]: 예시 값

[^2]: 게임 클라이언트가 로비에 참여해 매치메이킹 그룹 ID를 가져오고 그룹에 참여합니다

[^3]: 완전 정규화 도메인 이름

[^4]: 예: 3개의 빈 슬롯의 경우 = \["3", "2", "1"]

[^5]: "2"를 실제 그룹 구성원 수로 바꾸세요

[^6]: 자신의 애플리케이션 이름으로 바꾸세요

[^7]: 자신의 애플리케이션 버전으로 바꾸세요

[^8]: 최대 차이 초과

[^9]: 최대 지연 시간 초과

[^10]: 인터넷 서비스 제공업체

[^11]: 다른 예시 보기

[^12]: [서비스형 함수](https://www.ibm.com/think/topics/faas)
