> 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/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" %}
또는 플레이어가 **지속적(항상 온라인) 서버를 선택하도록** 목록에서 [서버 브라우저](/ko/learn/server-browser.md).
{% endhint %}

**5분 안에 시작하고 모든 기능을 무료로 테스트하세요. 신용카드가 필요하지 않습니다.**

더 강력한 전용(독립형) 클러스터가 준비되면 업그레이드하세요. Edgegap과의 기본 통합 [배포](/ko/learn/orchestration/deployments.md) 플레이어가 어디에 있든 최고 수준의 핑을 제공합니다.

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

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

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

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

## ▶️ 매치메이킹 시작

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

* 언리얼 엔진 [개발자 도구](/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 [개발자 도구](/ko/unity/developer-tools.md#software-development-kit):
  * [Unity 패키지 관리자를 사용하여 무료로 패키지 설치](https://github.com/edgegap/edgegap-unity-sdk),
  * [시작 가이드와 완전한 예제를 살펴보세요](/ko/unity/matchmaking.md).

게임 통합을 사용자 지정하고 문제를 해결하며 최적화하기 위해 매치메이킹 프로세스를 알아보세요:

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fm4U4bgwucX6iGEieMISU%2Fimage.png?alt=media&amp;token=39b97619-700b-4062-9dd9-73fa08fb96c2" 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="info" %}
Matchmaker 토큰과 Server Browser 토큰은 Edgegap API 토큰과 별개입니다.
{% endhint %}

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

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

### 그룹 구성

그룹(파티)을 만들면 플레이어가 친구들과 같은 팀과 서버에 참여하게 됩니다.

{% hint style="success" %}
그룹을 준비 완료로 표시하여 [#find-match](#find-match "mention") 빠르게 **그룹 구성원이 없는 솔로 플레이어로서**.
{% endhint %}

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FzPLV5ap16XQn0vYZsnQb%2FUntitled-2024-10-29-1018.png?alt=media&amp;token=aa7165ab-abe1-4f7d-a84e-d2c4af8f36ad" 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">Unreal Engine</th><th width="75" data-type="checkbox">Unity</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) 모든 그룹 구성원이 자신의 [핑 비컨](/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/ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment).

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

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

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

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

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

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

{% hint style="info" %}
모든 플레이어는 **고유한 Ticket 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/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" %}
연결 실패 또는 검은 화면이 발생한 경우 다음을 참고하세요 [문제 해결 가이드](/ko/unreal-engine.md#troubleshooting-and-faq).
{% endhint %}
{% endtab %}

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

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

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

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

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

### 백필 매치

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

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

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

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

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FJhdLAJYga4z2sjxLj6LM%2FUntitled-2024-10-29-1018.png?alt=media&amp;token=279136ba-a15e-46b0-a119-8419b8aca044" alt=""><figcaption><p>백필 시나리오 시각화</p></figcaption></figure>

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

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

1. 서버는 플레이어가 부족한 각 팀마다 하나의 백필을 생성하며, 다음 값들을 사용합니다:
   * 실제 `할당`  에서 가져온 데이터 [배포](/ko/learn/orchestration/deployments.md#injected-environment-variables) (배포).
   * 현재 연결된 플레이어의 `티켓`:
     * 에서 [심층 살펴보기](/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. 게임 클라이언트는 계속해서 [심층 살펴보기](/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. 새 플레이어는 인증을 위해, 그리고 자신의 연결을 매치메이커에 매핑하기 위해 서버에 ticket ID를 알려야 합니다 [#injected-variables](#injected-variables "mention") 또는 `assigned_ticket` (백필된 경우).
  2. 서버 수명 동안 사용되지 않은 플레이어 수용량(이탈자)을 위해 새 백필을 생성하세요.
  3. 만료된 백필을 갱신하세요. 이는 다음 후 삭제됩니다 `ticket_expiration_period`.
* **남아 있는 백필을 정리(삭제)하세요** 일단 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-5.-deployment-stopped](https://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 %}

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

## ⚙️ 구성

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

{% hint style="success" %}
다음을 참조하세요 [매치메이킹](/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>

* 다음을 찾을 수 없습니다 [앱 및 버전](/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/ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment)**.**

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

</details>

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

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

각 매치메이커 프로필은 [앱 버전](/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) (또는 만료되기 직전) 부분 매치가 가능하다면(최소 이상, 최대 미만 팀 크기), 이 매치는 같은 확장 단계의 모든 플레이어와 함께 생성됩니다(다른 규칙이 통과한다고 가정).

{% hint style="success" %}
협동, 자유 경쟁, 또는 비대칭 팀 크기 게임 모드의 경우 다음을 설정하세요 `"team_count": 1` .
{% endhint %}

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

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

팀 크기가 4명으로 고정되어 있다고 가정하면:

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FSFEzBayk3XNEUTIynjNd%2Fimage.png?alt=media&amp;token=11a43fdf-3a99-4caa-8d2b-639e0f3cc06f" 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는 절대 매칭되지 않습니다.

| "자유 경쟁" | "깃발 점령" | "깃발 점령" |
| ------- | ------- | ------- |
| Alice   | Erin    | Frank   |
| Bob     | Charlie |         |
| Dave    |         |         |

</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="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FxtTxZ7TPSa8a8WtnGNAE%2Fimage.png?alt=media&amp;token=c48b843b-c4e5-47bf-9154-07254a788067" 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] 문제나 느린 연결(예: 무선/모바일)로 인해 지연이 발생하고 다른 사람들의 게임 경험을 저하시킬 수 있습니다. 이 문제를 완화하려면:

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

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

{% hint style="success" %}
보기 [매치메이킹](/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="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FcQSUAnRkZKVyuGjFWSYL%2Fimage.png?alt=media&amp;token=bf1a4e28-230a-4c9a-9ef6-a0dea4dbecdb" alt=""><figcaption></figcaption></figure>

</details>

#### 규칙 확장

선택적으로, **`확장`**  확장은 대기열에서 일정 시간이 지난 후 규칙의 속성을 수정해 제한을 완화하고 매칭 가능한 플레이어 풀을 확장합니다, **그 결과 더 빠른 매치가 만들어집니다**.

<details>

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

[초기에는 정확히 4명의 플레이어로 구성된 1개 팀이 필요합니다(그룹으로 나뉠 수 있음)](/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 %}

## 📌 주입된 변수

서버가 플레이어에 대한 세부 정보를 알아야 할 수도 있습니다. 플레이어 속성, 확인된 매치 값 및 기타 값은 일반적인 항목과 함께 배포에 주입됩니다 [앱 및 버전](/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 %}

## 🧵 플레이어 추적

플레이어가 문제를 겪는다면 서버 로그까지의 경로를 추적하는 것이 도움이 될 수 있습니다. 각 매치메이커 **배포는** **할당된 플레이어 티켓 ID로 태그됩니다** 그래서 쉽게 [배포](/ko/learn/orchestration/deployments.md#filter-deployments) 찾고 [배포](/ko/learn/orchestration/deployments.md#container-logs) 문제 해결에 활용할 수 있습니다.

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

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

## 👀 분석

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

🌟 [**매치메이커를 엔터프라이즈 티어로 업그레이드**](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list) **매치메이킹 지표와 인사이트를 사용하려면:**

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fhb8NmB4ELuG7ayGLTeHs%2Fimage.png?alt=media&amp;token=e3e0371e-c33f-48c8-bd15-5c11448dc633" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fl0zTNccJASUTkJfTYxss%2Fimage.png?alt=media&amp;token=0d061320-9524-4b12-83e6-ea9112ef1409" alt=""><figcaption></figcaption></figure>

## ☁️ 호스팅 클러스터

매치메이커는 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 Tiers를 변경하는 것도 가능합니다 [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention"). 관리형 클러스터는 Edgegap이 유지 관리하는 고가용성 서비스 호스팅을 제공하며, 공개 출시 게임을 위해 연중무휴 실시간 지원을 제공합니다.

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

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

{% hint style="warning" %}
**성공을 대비하고 출시 후 최적화하여 출시일에 플레이어가 막히지 않도록 하세요.** 다음을 사용하세요 [개발자 도구](/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>

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

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

{% hint style="danger" %}
**안전하게 실험할 수 있도록 개발 및 프로덕션용 매치메이커를 분리하세요** 환경에서 안전하게 실험할 수 있습니다.
{% endhint %}

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

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

**중단을 방지하려면 각 인스턴스에 서로 다른 리전을 선택하세요** 지역적 장애 발생 중에.

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Flzy4elHYDPBMpjSMG1HS%2Fimage.png?alt=media&amp;token=7da795fc-ae6c-490f-b65c-5f8dda635503" 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. 게임 엔진의 Editor를 제공된 URL + 외부 포트에 연결하고,
3. 사용하지 않는 매치메이커 업데이트 `파랑` 새 이미지 태그에 연결하려면 `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. 매치메이커를 중지한 후, 매치메이커 DNS 변경 사항이 전 세계 ISP에 전파되도록 3\~7일 기다리세요(빠른 재시작은 DNS 업데이트나 대기 기간이 필요하지 않습니다),
6. 새 게임 클라이언트 업데이트를 릴리스 `c2` 게임 배포 플랫폼에서,
7. 새 게임 클라이언트에 시간을 주세요 `c2` 플레이어 기기에 배포되도록(일반적으로 최대 3\~7일):
   1. 오래된 게임 클라이언트를 모니터링 `c1`  배포를 사용하여 [배포](/ko/learn/orchestration/deployments.md#analytics),
8. Edgegap 계정의 사용하지 않는 리소스를 정리하세요:
   1. 이미지 태그 삭제 `t1.0.0` Container Registry 용량을 확보하려면,
   2. 이미지 태그 삭제 `t1.1.0` Container Registry 용량을 확보하려면,
   3. 다음을 끄세요 `초록`  다음 업데이트까지 청구를 일시 중지하려면.

{% 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. 게임 엔진의 Editor를 제공된 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`  배포를 사용하여 [배포](/ko/learn/orchestration/deployments.md#analytics),
4. Edgegap 계정의 사용하지 않는 리소스를 정리하세요:
   1. 이미지 태그 삭제 `t1.1.0` Container Registry 용량을 확보하려면.

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

클라이언트와 서버는 API를 직접 호출하거나 게임 엔진 SDK를 통해 호출할 수 있으며, 또한 다음을 참고하세요 [매치메이킹](/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가 생성되며, 이는 엣지 케이스를 테스트하거나 페이로드 형식을 검증하는 데 유용합니다.
{% 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/) 세부 정보를 확인하려면.

### 속도 제한

버스트 용량을 초과해 충돌하는 것을 방지하기 위해, 우리는 내부 부하 테스트를 바탕으로 초당 요청 수를 제한합니다. 이는 [매치메이킹](/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 요청 과다` **배포에서 플레이어가 누락될 수 있습니다** 짧은 급증이나 트래픽 피크 기간 동안.
{% 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시간 내내 유지되며, 모든 플레이어가 밤낮없이 플레이합니다. |

#### 부하 시 동작

매치메이커에 높은 부하가 걸리면:

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

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

타사 배포 플랫폼에 호스팅된 WebGL 게임의 경우(예. [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>

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

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

{% hint style="success" %}
**매개변수 포함 `player_ip`  멤버의 공개 IP 주소와 함께** 가능한 가장 낮은 플레이어 지연 시간을 보장하고 다음의 이점을 활용하려면 [/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-server-score-strategy-best-practice](https://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="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FzLfA3fEBgwaziGtp2yMO%2Fimage.png?alt=media&amp;token=3d551e74-4a60-47a6-9d79-a506f961663d" alt=""><figcaption><p>서버 간 매치메이킹 활동 다이어그램</p></figcaption></figure>

## 🚨 문제 해결

**여러분의 성공이 우리의 최우선 과제입니다.** 사용자 지정 요청을 보내거나, 누락된 핵심 기능을 요청하거나, 의견을 남기고 싶다면, [커뮤니티 디스코드로 문의해 주세요](https://discord.gg/MmJf8fWjnt).

<details>

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

* 다음을 찾을 수 없습니다 [앱 및 버전](/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/ko/learn/matchmaking/pages/1e75126474c80b6c476cbd5e97b171fce5779d47#id-1.-start-a-deployment)**.**

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

</details>

<details>

<summary>새 매치메이커를 만들려고 할 때 왜 오류가 발생하나요?</summary>

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

</details>

<details>

<summary>왜 제 매치메이커가 3시간 후에 자동으로 꺼졌나요?</summary>

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

</details>

<details>

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

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

</details>

<details>

<summary>왜 무시한 채 임의의 시간에 배정/배포가 발생하나요? <code>player_count</code>?</summary>

* 귀하 또는 다른 팀원이 이전 테스트 세션에서 배정되지 않은 티켓을 생성했을 수 있습니다. 다음을 해 주세요. [매치메이커를 다시 시작](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).

</details>

<details>

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

* 구성에 맞게 충분한 매칭 티켓을 생성했는지 확인하세요.

</details>

<details>

<summary>내 티켓이 다음 사이를 오가며 멈춰 있습니다 <code>MATCH_FOUND</code> 및 <code>팀 발견됨</code> 반복적으로.</summary>

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

</details>

<details>

<summary>내 티켓이 바로 다음으로 이동합니다 <code>취소됨</code>.</summary>

* 티켓의 만료 시점에 도달했습니다. 새 티켓을 만들거나 테스트 목적으로 구성에서 만료 기간을 늘리세요.

</details>

<details>

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

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

</details>

<details>

<summary>내 매치메이커에 오류가 표시되는데, 어떻게 해야 하나요?</summary>

* 개발 또는 테스트 인스턴스라면 먼저 매치메이커를 다시 시작해 보세요. - 문제는 다음을 통해 신고해 주세요 [커뮤니티 디스코드](https://discord.gg/MmJf8fWjnt).
* 이 문제가 실서비스 게임에 영향을 주는 경우, 다음을 생성하세요 [긴급 지원 요청](https://edgegap.atlassian.net/servicedesk/customer/portal/3).

</details>

## 🔖 변경 로그

#### 시맨틱 버전 관리

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

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

사용 중인 매치메이커 버전에 따라 구성 파일이 검증되므로, 규칙이 해당 버전의 기능과 일치하는지 확인하세요.

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

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

{% hint style="warning" %}
**매치메이커 버전을 업그레이드하려면 - 중지, 편집, 재시작.** 빠른 재시작은 버전 변경을 적용하지 않습니다.
{% 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)
