# 서버 브라우저

**Edgegap Server Browser OPEN BETA에 오신 것을 환영합니다.** 새로운 서비스를 미리 체험해 보시고, Discord의 라운드테이블 토론을 통해 앞으로의 방향을 함께 만들어 가는 기회를 즐기시길 바랍니다.

Server Browser는 다음을 위한 관리형 서비스입니다 [#match-bound](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/deployments#match-bound "mention") 및 [영구](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/persistence) 서버:

* **플레이어가 적합한 서버를 검색하고 참여하도록 돕고** 용량, 지연 시간 또는 게임 매개변수를 기준으로;
* **새 서버를 미리 예열하여** 전 세계 사용자를 대규모로 지원하고 답답한 대기열을 방지하며;
* **서버 운영을 간소화합니다** 업데이트, 재시작, 영속성, 메시싱 등을 포함합니다.

{% hint style="success" %}
서버 선택을 허용하지 않으면서 엄격한 규칙에 따라 플레이어를 매칭하려고 하시나요? 다음을 고려해 보세요 [matchmaking](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking "mention").
{% endhint %}

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FwKrq9tLaamRoM6vSLXZu%2Fimage.png?alt=media&#x26;token=83756c6f-d413-4ac1-988e-b90e7fa7a0a6" alt=""><figcaption></figcaption></figure>

## ✔️ 준비

### 흐름과 계층

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fnwlt2Ot2ahlyLvI7kdGx%2Fimage.png?alt=media&#x26;token=14b5a6c8-48c8-4f23-a50a-0783acab14e3" alt=""><figcaption><p>Server Browser: 흐름과 계층</p></figcaption></figure>

Server Browser는 두 가지 주요 기능을 제공합니다:

[#start-browsing](#start-browsing "mention") 게임 클라이언트와 함께 다음을 수행합니다:

* 적합한 서버 인스턴스를 검색 및 찾고, 슬롯을 확인하고, 사용 가능한 용량을 예약합니다.
* 인스턴스 슬롯에 자리를 예약하고, 연결 정보를 가져와 서버에 연결합니다.
* 다음을 사용하여 배포에서 오는 플레이어 연결을 인증합니다 [연합 신원](#user-content-fn-1)[^1].
* 인스턴스 슬롯의 사용 가능한 용량 및/또는 메타데이터를 업데이트하여 검색 기준을 수정합니다.

[#automated-scaling](#automated-scaling "mention") (선택 사항) 스케일링 정책과 함께 다음을 수행합니다:

* 지역 및/또는 기타 기준별로 사용 가능한 서버 인스턴스, 슬롯, 용량을 모니터링합니다.
* 예열 또는 즉시 스케일링으로 용량을 늘리기 위해 서버를 배포합니다.
* 데모, 업데이트, 테스트, QA, 토너먼트 등을 위한 특수 정책으로 운영을 자동화합니다.

{% hint style="info" %}
출시 후, **서버 브라우저는 24시간 365일 실행되어야 합니다** 전 세계의 플레이어가 서버에 참여할 수 있도록 보장하기 위해.
{% endhint %}

## ▶️ 브라우징 시작

효율적인 서버 사용을 보장하기 위해 서버/플레이어 수명 주기와 각자의 책임에 대해 알아보세요.

### 인증

Server Browser는 두 가지 유형의 토큰을 자동으로 생성합니다:

* **서버 토큰** - 다음에 필요 [서버 API](#server-lifecycle) 메서드에 사용되며 [앱 버전 변수로 주입될 수 있습니다](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/application-and-versions#injected-variables).
  * 모든 API 메서드에 대한 액세스를 부여하며, 테스트, DevOps 또는 맞춤 오케스트레이션에 유용합니다.
* **클라이언트 토큰** - 다음에 필요 [모니터 API 및 좌석 예약 API](#player-lifecycle) 게임 클라이언트에서 사용됩니다.
  * 토큰 순환을 더 쉽게 하기 위해 이 토큰은 제3자 비밀 저장소에 보관하는 것을 권장합니다.

### 인스턴스 검색

**새로 생성** [deployments](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/deployments "mention") **초기화될 때 최소한 하나의 슬롯이 있는 새 인스턴스를 생성해야 합니다.**

{% hint style="info" %}
다음을 참조하세요 [#automated-scaling](#automated-scaling "mention") 스케일링 정책에 대해 알아보고 배포를 자동으로 시작합니다.
{% endhint %}

**선택적 사용자 정의 메타데이터 매개변수** 플레이어 필터링, 정렬 및 탐색용입니다.

예시:

* 슬롯 정보 - 팀 용량 및 팀별 메타데이터(예: 팀 이름),
* 이름 및 태그 - 사용자 정의 가능하고 고유하며 사람이 읽을 수 있고 검색 가능한 레이블;
* 연결 정보 - URL, IP, 외부 포트 또는 기타 매개변수;
* 호환성 데이터 - 서버 버전 또는 지원되는 클라이언트 버전;
* 지연 시간 식별자 - 도시 및 지역 식별자와 할당된 [ping-beacons](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/ping-beacons "mention") 세부 정보;
* 게임 매개변수 - 레벨/씬/맵, 게임 모드, 난이도, 사용된 모드;
* 플레이어가 적합한 서버를 필터링하고 찾는 데 도움이 되는 기타 모든 사용자 정의 매개변수.

{% hint style="info" %}
위의 메타데이터 매개변수는 예시일 뿐이며, 위의 항목을 포함해 어떤 매개변수든 정의할 수 있습니다. 모든 메타데이터 매개변수는 선택 사항이며, 일부 인스턴스는 모든 매개변수를 정의할 필요가 없을 수 있습니다.
{% endhint %}

메타데이터는 문자열 키와 문자열, 숫자, 불리언 또는 문자열 배열 값을 지원합니다.

{% hint style="success" %}
중첩된 객체를 직렬화하려면 키에 접근자 경로를 다음과 같이 인코딩해 보세요 `"object.child.property"`.
{% endhint %}

서버는 **언제든지 인스턴스 또는 슬롯 메타데이터를 업데이트하여** 검색 가능 기준을 수정할 수 있습니다.

**서버 인스턴스는 정기적으로 유지-활성(keep-alive) 하트비트를 보내야 합니다** 지속적인 가용성을 확인하고 플레이어가 충돌했거나 오프라인인 서버에 참여하는 것을 방지하기 위해서입니다. 설정된 만료 기간 동안 하트비트가 누락되면 인스턴스와 보류 중인 좌석 예약이 자동으로 삭제됩니다.

{% hint style="info" %}
다음을 참조하세요 [persistence](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/persistence "mention") 영구 월드 상태 관리용 및 [#active-caching](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/application-and-versions#active-caching "mention") 더 빠른 배포용입니다.
{% endhint %}

### 검색 및 탐색

플레이어는 서버 인스턴스를 나열하고 [결과를 페이지 단위로 탐색하여](#pagination) 참여하고 싶은 서버를 찾을 수 있습니다. 핑(지연 시간) 데이터를 표시하려면 각 인스턴스의 [ping-beacons](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/ping-beacons "mention") 세부 정보를 읽고 [지연 시간을 측정하세요](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/ping-beacons#measuring-round-trip-time).

인스턴스와 슬롯은 참여 가능한 좌석 수 또는 [인덱싱된 메타데이터 매개변수로 필터링할 수 있습니다](#configuration).

<table><thead><tr><th width="170">매개변수</th><th width="135">연산자</th><th>예시 필터(간단한 예시 기반)</th></tr></thead><tbody><tr><td><code>"joinable_seats"</code></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  또는 <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>lt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-7"><code>le</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-8"><code>gt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-9"><code>ge</code></a></p></td><td><pre><code>?filter=<a data-footnote-ref href="#user-content-fn-3">joinable_seats gt 0</a>
&#x26;orderby=<a data-footnote-ref href="#user-content-fn-5">joinable_seats desc</a>
</code></pre></td></tr><tr><td><code>"string"</code><br>(메타데이터)</td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  또는 <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>lt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-7"><code>le</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-8"><code>gt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-9"><code>ge</code></a>  또는<br><code>포함</code></p></td><td><pre><code>?filter=metadata.custom_name contains 'my game'
and metadata.server_version le '1.1.0'
and metadata.server_version ge '1.0.0'
&#x26;orderby=metadata.custom_name asc
</code></pre></td></tr><tr><td><p><code>"int"</code> 또는 <code>"float"</code></p><p>(메타데이터)</p></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  또는 <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>lt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-7"><code>le</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-8"><code>gt</code></a>  또는 <a data-footnote-ref href="#user-content-fn-9"><code>ge</code></a>  </p></td><td><pre><code>?filter=metadata.xp_multiplier gt 1.0
&#x26;orderby=metadata.xp_multiplier desc
</code></pre></td></tr><tr><td><code>"bool"</code><br>(메타데이터)</td><td><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  또는 <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a></td><td><pre><code>?filter=metadata.allows_new_connections eq true
</code></pre></td></tr></tbody></table>

{% hint style="success" %}
서버에 대한 지연 시간을 측정하기 전에 지역 및/또는 도시로 필터링하여 선택 범위를 좁힙니다.
{% endhint %}

{% hint style="info" %}
커서 기반 [#pagination](#pagination "mention") 에 대해 알아보고 사용자가 더 많은 결과를 가져올 수 있도록 하세요.
{% endhint %}

### 좌석 예약

서버에 참여하기 전에, 인스턴스가 충분한 사용 가능 용량을 제공하는지 보장하기 위해 좌석 예약이 필요합니다. 예약에는 플레이어 그룹 또는 단독 개인이 포함될 수 있습니다.

**슬롯의 참여 가능 좌석 용량을 초과하는 예약은 자동으로 거부됩니다** ([409 충돌](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/409)). 참여 가능 좌석은 아직 다른 플레이어에 의해 예약되지 않은 사용 가능한 좌석입니다.

연합 신원: 플레이어는 예약 시 고유한 제3자 플레이어 ID를 제공해야 합니다. 동일한 ID를 보내면 [#connect-to-server](#connect-to-server "mention") 서버가 신원을 검증할 수 있습니다.

예약이 성공적으로 완료되면([200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/200)), 플레이어는 즉시 연결을 시도해야 합니다. 보류 중인 **예약은 서버에서 확인되지 않으면 30초 후 만료됩니다** .

{% hint style="info" %}
서버는 임의로 어떤 슬롯의 용량을 변경하거나, 어떤 슬롯이든 추가, 삭제 또는 업데이트할 수 있습니다. **보류 중인 예약이 새 사용 가능한 슬롯 용량을 초과하면 해당 슬롯의 모든 예약이 제거됩니다.**
{% endhint %}

### 서버에 연결

플레이어가 적합한 인스턴스를 찾으면, **메타데이터에서 필요한 연결 정보를 가져올 수 있습니다** (URL, IP, [외부 포트](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/application-and-versions#port-mapping)). 좌석 예약이 완료되는 즉시, **플레이어는 배포의 게임 서버에 연결을 진행하고 플레이어 ID를 전달할 수 있습니다**.

{% tabs %}
{% tab title="Unreal Engine" %}
다음의 경우 **PIE(에디터)에서 연결하려면** 개발 및 테스트 중에 틸드 키를 누르고 `~`  다음과 같이 입력하세요 `open {URL}:{port}` 그리고 에디터가 맵을 로드할 때까지 기다리세요.

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

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

* **배포** **URL** 서버의 IP를 가리키며, 보통 `NetworkManager`  컴포넌트에 있습니다.
* **외부 포트** 에 매핑되며 [서버의 내부 수신 포트](https://docs.edgegap.com/learn/advanced-features/application-and-versions#port-mapping)로 연결됩니다. 보통 Transport 컴포넌트에 있습니다.

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

새 연결을 인증하려면, **서버는 모든 새 플레이어 ID를 포함한 일괄 예약 확인** 요청을 보내고, 확인 응답에서 다음 정보를 받아야 합니다:

* 수락된 플레이어 예약을 선호 슬롯에 할당,
* 만료된 플레이어 예약을 선호 슬롯에 할당,
* 알 수 없는 플레이어 ID 목록.

귀하의 **서버는 각 플레이어 그룹을 어떻게 처리할지** 그리고 만료되었거나 거부된 사용자를 허용할지 / 추방·차단할지 결정할 수 있습니다. 각 **인스턴스의 슬롯은 새 사용 가능 좌석 수로 즉시 업데이트되어야 합니다** 새 예약이 용량을 초과하지 않도록 하기 위해서입니다.

### 서버 이탈

플레이어가 떠나면 서버는 할당된 슬롯을 업데이트하여 새로운 사용 가능 좌석 용량을 반영해야 합니다.

{% hint style="success" %}
게임 설계상 재연결 기간을 허용한다면, 서버는 좌석을 해제하기 전에 잠시 기다릴 수 있습니다.
{% endhint %}

호스팅 비용 최적화를 위해 플레이어가 없는 서버는 중지하는 것을 권장합니다. 그렇게 하기 전에 몇 분 정도 기다리면 짧은 유휴 기간 동안 재시작 횟수를 줄일 수 있습니다.

다음을 읽어 보세요 [#recovery-objectives](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/persistence#recovery-objectives "mention") 답답한 영구 서버 롤백을 방지하기 위해.

## 🚀 자동 스케일링

Server Browser는 여러 가지 자동 확장 방법과 호환됩니다:

* **사전 예열 방식** - Server Browser 스케일링 정책만으로 엄격하게 서버 시작,
* **즉시 실행 방식** - 다음을 통해 시작 [matchmaking](https://docs.edgegap.com/docs.edgegap.com-ko/learn/matchmaking "mention") 및 [Server Browser로 채우기](#start-browsing),
* **사용자 정의 오토스케일러** - 사용자 정의 게임 백엔드와 [Server Browser로 채우기](#start-browsing).

다음 가이드는 다음에 초점을 맞춥니다 **스케일링 정책을 통한 사전 예열** 을 주요 방식으로 삼습니다.

{% hint style="success" %}
에서 배포를 중지하는 방법을 알아보세요 [Unreal Engine](https://docs.edgegap.com/docs.edgegap.com-ko/unreal-engine#stop-deployments), [Unity](https://docs.edgegap.com/docs.edgegap.com-ko/unity#stop-deployments)또는 [API와 함께](https://docs.edgegap.com/docs.edgegap.com-ko/docs/api/dedicated-servers#delete-v1-self-stop-request_id-access_point_id) 수명 주기를 안정적으로 관리하기 위해.
{% endhint %}

### 용량 모니터링

스케일링 정책은 서버 인스턴스(검색된 배포) 목록을 지속적으로 갱신하며, [`monitoring_interval`](#user-content-fn-10)[^10] . 각 정책에는 동일한 [필터링 구문](#search-and-browse) 을 사용한 필터를 포함할 수 있으며, 플레이어가 인스턴스를 검색할 때와 같습니다 - 지역, 용량 또는 기타 기준별로.

구성된 [`minimum_active_instances`](#user-content-fn-11)[^11]  수량은 다음 중 하나로 취급될 수 있습니다:

* **고정 용량** 항상 실행 상태로 유지하고 싶은 배포
* **예열 대기** 배포 버퍼로, 초기화 지연을 숨깁니다.

#### 고정 용량

특히 다음과 같은 게임에서 고정된 수의 서버를 유지하는 것은 유용할 수 있습니다 [persistence](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/persistence "mention"), 특히 이러한 게임이 플레이어에게 임대를 제공할 때 [#community-servers](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/persistence#community-servers "mention").

이 유형의 정책 구성은 품질 보증, 토너먼트, 비공개 알파, 퍼블리셔 데모 또는 기타 제한 용량 이벤트 및 운영에서도 때때로 사용됩니다.

{% hint style="info" %}
스케일링 정책은 충돌했거나 중지된 서버를 자동으로 즉시 재시작하고 재활용하는 데 도움이 됩니다.
{% endhint %}

#### 예열 대기

플레이어 수요보다 먼저 서버를 시작하는 것은 다음과 같은 경우 유리할 수 있습니다:

* 대규모 릴리스나 업데이트를 출시하고 짧은 시간 내에 플레이어 유입이 급증할 것으로 예상할 때,
* 또는 서버 초기화에 30초 이상이 걸릴 때(배포 시간 제외),
* 또는 게임이 복잡하거나 순환적인 네트워크 의존성을 요구하는 메시싱 전략을 구현할 때.

{% hint style="info" %}
매치메이킹을 사용한다면, [#backfill-match](https://docs.edgegap.com/docs.edgegap.com-ko/matchmaking/matchmaker-in-depth#backfill-match "mention") 새 배포를 시작하기 전에 이 용량을 활용해야 합니다.
{% endhint %}

### 서버 배포

모니터링 중인 서버 인스턴스 수가 구성된 최소 활성 인스턴스 수보다 낮아지면 새 배포가 자동으로 시작됩니다. 모든 배포는 즉시 요청되며 다음 이후 무한히 재시도됩니다 [`deployment_registration_period`](#user-content-fn-10)[^10]  가 경과한 후.

{% hint style="warning" %}
새 배포가 [자동 검색을 수행하고 인스턴스를 생성하는지 확인하세요](#discover-instance) 정책 필터와 정확히 일치하도록, 아니면 **정책이 무한 루프에 빠져 많은 수의 사용되지 않는 배포를 생성할 수 있습니다**!&#x20;
{% endhint %}

정책에 대한 배포 요청을 정의할 때, 우리는 Private Fleets(Cloud 오버플로우 포함) 또는 Cloud에 직접 배포할 수 있도록 하는 표준 배포 매개변수를 사용합니다:

* [**애플리케이션 및 버전**](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/application-and-versions) - 빌드 버전, 리소스 및 기타 오케스트레이션 매개변수,
* **사용자** - 선호하는 단일 좌표 세트 [서버 배치](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/deployments#regional-standby),
* [**개인 호스트 ID**](https://docs.edgegap.com/docs.edgegap.com-ko/learn/orchestration/private-fleets) - Cloud의 경우 비워 두거나, 원하는 지역 내 호스트를 지정합니다,
* [**태그**](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/deployments#dashboard-monitoring) - 나중에 이 정책으로 시작된 배포를 찾을 수 있도록 정책 이름 태그를 추가합니다,
* [**환경 변수**](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/deployments#custom-variables) - 사용자 정의 매개변수와 비밀을 서버에 전달합니다,
* [**웹훅**](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/deployments#webhooks-and-postbacks) - 게임 백엔드(또는 매치메이커)에 배포 수명 주기 이벤트를 알립니다,
* [**캐시된 위치 필요**](https://docs.edgegap.com/docs.edgegap.com-ko/orchestration/application-and-versions#active-caching) - 캐시된 위치에서만 더 빠른 배포를 선호하는 경우.

### 예시 정책

필요에 따라 이 정책들을 테스트하고 수정하세요. 대부분의 게임은 여러 정책을 사용하게 됩니다.

<details>

<summary>🍀 품질 보증 풀(최소 예시)</summary>

테스트용으로 항상 하나의 서버가 배포되도록 유지하는 간단한 정책입니다.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-qa-pool",
  <a data-footnote-ref href="#user-content-fn-12">"filter"</a>: "metadata.policy_name eq 'sb-qa-pool'",
  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
          "latitude": 41.881832,
          "longitude": -87.623177
        }
      }
    ],
    "tags": ["sb-qa-pool"],
    "environment_variables": [
      {
        "key": "SB_POLICY_NAME",
        "value": "sb-qa-pool",
        "is_hidden": false
      }
    ]
  },
  "minimum_active_instances": 1
}
</code></pre>

</details>

<details>

<summary>🌡️ 지역별 사전 예열 출시</summary>

각 지역은 수요를 예상하여 출시 전에 배포를 시작합니다.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-v1.0.0-chicago",
  <a data-footnote-ref href="#user-content-fn-16">"filter"</a>: "joinable_seats gt 0 and metadata.policy_name eq 'sb-v1.0.0-chicago'",
  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
          "latitude": 41.881832,
          "longitude": -87.623177
        }
      }
    ],
    "tags": ["sb-v1.0.0-chicago"],
    "environment_variables": [
      {
        "key": "SB_POLICY_NAME",
        "value": "sb-v1.0.0-chicago",
        "is_hidden": false
      }
    ]
  },
  <a data-footnote-ref href="#user-content-fn-17">"minimum_active_instances"</a>: 10
}
</code></pre>

</details>

<details>

<summary>❄️ 서버 메시싱 그룹</summary>

서버 그룹당 하나의 정책이며, 게임 백엔드가 각 그룹마다 새 정책을 추가합니다.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-meshgroup-pqyt8sxcb",
  <a data-footnote-ref href="#user-content-fn-12">"filter"</a>: "metadata.policy_name eq 'sb-meshgroup-pqyt8sxcb'",
  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
          "latitude": 41.881832,
          "longitude": -87.623177
        }
      }
    ],
    "tags": ["sb-meshgroup-pqyt8sxcb"],
    "environment_variables": [
      {
        "key": "SB_POLICY_NAME",
        "value": "sb-meshgroup-pqyt8sxcb",
        "is_hidden": false
      }
    ],
    <a data-footnote-ref href="#user-content-fn-18">"webhook_on_ready"</a>: {
      "url": "https://my-webhook.com"
    },
    <a data-footnote-ref href="#user-content-fn-19">"webhook_on_terminated"</a>: {
      "url": "https://my-webhook.com"
    }
  },
  <a data-footnote-ref href="#user-content-fn-20">"minimum_active_instances"</a>: 9
}
</code></pre>

</details>

<details>

<summary>🔑 커뮤니티 서버</summary>

서버 소유자당 하나의 정책이며, 서버 인증에 사용되는 사용자 정의 비밀번호를 전달합니다.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-owner-jnjnc8mid",
  <a data-footnote-ref href="#user-content-fn-21">"filter"</a>: "metadata.policy_name eq 'sb-owner-jnjnc8mid'",
  "deployment_request": {
    <a data-footnote-ref href="#user-content-fn-22">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
          "latitude": 41.881832,
          "longitude": -87.623177
        }
      }
    ],
    "tags": ["community", "sb-owner-jnjnc8mid"],
    "environment_variables": [
      {
        "key": "SB_POLICY_NAME",
        "value": "sb-owner-jnjnc8mid",
        "is_hidden": false
      },
      {
        "key": "SB_SERVER_PASSWORD",
        "value": "password1234",
        "is_hidden": false
      }
    ],
    <a data-footnote-ref href="#user-content-fn-18">"webhook_on_ready"</a>: {
      "url": "https://my-webhook.com"
    },
    <a data-footnote-ref href="#user-content-fn-23">"webhook_on_error"</a>: {
      "url": "https://my-webhook.com"
    },
    <a data-footnote-ref href="#user-content-fn-24">"webhook_on_terminated"</a>: {
      "url": "https://my-webhook.com"
    }
  },
  "minimum_active_instances": 1
}
</code></pre>

</details>

<details>

<summary>🔒 지역 잠금 MMO</summary>

각 지역은 사용 가능한 용량이 임계값 아래로 떨어질 때 배포를 추가합니다.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-mmo-chicago",
  <a data-footnote-ref href="#user-content-fn-25">"filter"</a>: "joinable_seats gt 5 and metadata.policy_name eq 'sb-mmo-chicago'",
  "deployment_request": {
    <a data-footnote-ref href="#user-content-fn-22">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
          "latitude": 41.881832,
          "longitude": -87.623177
        }
      }
    ],
    "tags": ["sb-mmo-chicago"],
    "environment_variables": [
      {
        "key": "SB_POLICY_NAME",
        "value": "sb-mmo-chicago",
        "is_hidden": false
      }
    ],
    <a data-footnote-ref href="#user-content-fn-24">"webhook_on_terminated"</a>: {
      "url": "https://my-webhook.com"
    }
  },
  "minimum_active_instances": 3
}
</code></pre>

</details>

## ⚙️ 구성

Server Browser API는 새 Server Browser를 생성할 때 지정한 JSON 구성에서 생성됩니다. 서버 및 슬롯 만료, 그리고 사용자 정의 메타데이터를 지정할 수 있습니다:

{% tabs %}
{% tab title="🍀 간단한 예시" %}

<pre class="language-json" data-title="sb-simple-example-v0-0-5.json"><code class="lang-json">{
	"version": "0.0.5",
	"server_instances": {
		"expiration_period": "1m",
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"policy_name": "string",
			"name": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {}
	},
	"seat_reservations": {
		"expiration_period": "1m"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "1m"
	}
}
</code></pre>

{% endtab %}

{% tab title="🎈 소셜 게임" %}

<pre class="language-json" data-title="sb-social-example-v0-0-5.json"><code class="lang-json">{
	"version": "0.0.5",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"seed": "string",
			"max_players": "int",
			"app_version": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_latency": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	}
}
</code></pre>

{% endtab %}

{% tab title="🤝 협동 게임" %}

<pre class="language-json" data-title="sb-cooperative-example-v0-0-5.json"><code class="lang-json">{
	"version": "0.0.5",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"avg_rank": "int",
			"max_players": "int",
			"app_version": "string",
			"tags": "string",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	}
}
</code></pre>

{% endtab %}

{% tab title="⚔️ 경쟁 게임" %}

<pre class="language-json" data-title="sb-competitive-example-v0-0-5.json"><code class="lang-json">{
	"version": "0.0.5",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"avg_rank": "int",
			"max_players": "int",
			"is_ranked": "bool",
			"app_version": "string",
			"cpu_frequency": "int",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-26">인덱스</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_rank": "int",
			"avg_latency": "int"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "15s"
	}
}
</code></pre>

{% endtab %}
{% endtabs %}

{% hint style="info" %}
최상의 성능을 위해 필터링이나 정렬에 사용되지 않는 메타데이터에 대해 인덱스를 지정하지 마세요. 인덱싱되지 않은 매개변수도 서버 인스턴스 또는 슬롯 세부 정보 API 메서드로 설정하고 읽을 수 있습니다. 다음을 참조하세요 [#api](#api "mention").
{% endhint %}

## ☁️ 호스팅 클러스터

Server Browser는 Edgegap에 의해 24시간 365일 편리하게 호스팅 및 관리됩니다.

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

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

한 번의 클릭으로 프라이빗 클러스터로 업그레이드하여 공개 출시 게임을 위한 24시간 라이브 지원과 함께 Edgegap 팀이 관리하는 고가용성 호스팅의 혜택을 누리세요.

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

* **플레이어 수** - 플레이어가 많을수록 API 요청이 더 많아집니다,
* **플레이어당 요청 수** - 재시도 속도가 빠를수록 서비스 부하가 증가하고 리소스를 소모합니다,
* **서버 수** - 서버가 많을수록 저장되는 데이터와 API 요청이 더 많아집니다,
* **클라이언트 재시도 폴백 로직** - 지터가 있는 백오프로 재시도하면 트래픽 급증을 분산하는 데 도움이 됩니다,
* **평균 매치 지속 시간** - 세션이 짧을수록 서버 브라우저와 더 자주 상호작용해야 합니다.

## 📗 API

게임 클라이언트와 전용 서버는 수명 주기 내내 Server Browser로 API 요청을 보냅니다.

{% file src="<https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2F0auyzkkQfLfNRgzKbWMn%2Fedgegap-server-browser-005.yaml?alt=media&token=84669896-e7b9-4415-8d66-131badb3fff5>" %}

API 사양을 가져와 다음에서 [Scalar API 웹 클라이언트](https://client.scalar.com/workspace/default/request/default) 또는 [Swagger Editor](https://editor.swagger.io/) 에서 세부 정보를 확인하세요.

### 페이지네이션

**Server Browser는 특정 순서로 필터링된 데이터를 점진적으로 가져오기 위한 커서 페이지네이션을 제공합니다.** 이 방식은 전통적인 limit-offset 페이지네이션과 달리, 더 많은 결과를 가져올 때마다 커서(시작점)와 페이지 크기(응답 항목 수)를 보내야 합니다.

{% hint style="info" %}
게임 서버 메타데이터를 위해 개발된 자체 데이터베이스 인덱싱 시스템과 결합하면, 커서 페이지네이션은 매우 동적인 데이터를 필터링할 때 빠르고 일관되며 유연한 사용자 경험을 제공합니다.
{% endhint %}

우리의 목표는 사용자가 첫 페이지에서 적합한 서버를 찾게 하는 것입니다. 최상의 경험을 위해 이전 페이지의 캐시된 결과를 표시하고, 사용자가 검색을 클릭할 때만 결과를 새로 고침하는 것을 권장합니다.

## 🔖 변경 내역

{% hint style="info" %}
**서버 브라우저의 최신 버전은 `0.0.5`** 입니다. 업데이트와 공지에 주목해 주세요.
{% endhint %}

#### 0.0.5 (2026년 3월 18일)

* 소개 [#automated-scaling](#automated-scaling "mention") 및 [#example-policies](#example-policies "mention").
* 더 많은 항목 추가 [#configuration](#configuration "mention") 영감을 위한 예시입니다.
* 개선된 [#flow-and-hierarchy](#flow-and-hierarchy "mention") 더 빠르게 시작할 수 있도록 다이어그램.

#### 0.0.4 (2026년 1월 5일)

* 오픈 베타에 진입하며, [서버 인스턴스와 슬롯에 대한 필터링 및 정렬](#search-and-browse)!

#### 0.0.3 (2025년 11월 28일)

* 서버 브라우저 서비스의 초기 버전이 클로즈드 베타로 출시되었습니다.
* 서버를 목록화하고, 용량을 관리하며, 연결 정보를 가져오세요.
* 클라우드 배포를 통한 매치 세션 및 Private Fleets와의 항상 온라인 지원.

[^1]: 제3자 플레이어 식별자

[^2]: 같음

[^3]: 사용 가능한 좌석이 있는 인스턴스를 찾습니다

[^4]: 같지 않음

[^5]: 가득 찬 인스턴스를 먼저 표시합니다

[^6]: 작음

[^7]: 작거나 같음

[^8]: 큼

[^9]: 크거나 같음

[^10]: 를 반복합니다 구성 참조

[^11]: 예시 정책 참조

[^12]: * 고정 용량
    * 주입된 변수가 메타데이터에 정책 이름을 제공한다고 가정합니다

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

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

[^15]: 시카고 좌표

[^16]: * 참여 가능한 인스턴스가 10개 미만일 때 배포
    * 주입된 변수가 메타데이터에 정책 이름을 제공한다고 가정합니다

[^17]: 시카고 지역에 최소 10개의 배포가 있다고 예상합니다

[^18]: 준비되면 게임 백엔드에 알립니다

[^19]: 중지되면 게임 백엔드에 알립니다

[^20]: 3x3 그리드 = 월드당 9개 서버

[^21]: * 용량을 모니터링하지 않음
    * 주입된 변수가 메타데이터에 정책 이름을 제공한다고 가정합니다

[^22]: 용량이 있으면 private fleet 선호

[^23]: 배포 실패 시 게임 백엔드에 알립니다

[^24]: 서버가 재시작될 때 게임 백엔드에 알립니다

[^25]: * 참여 가능 좌석이 5개 이하인 인스턴스가 3개 미만일 때 배포
    * 주입된 변수가 메타데이터에 정책 이름을 제공한다고 가정합니다

[^26]: 인덱스에는 필터링 또는 정렬에 사용되는 사용자 정의 메타데이터 매개변수가 포함됩니다
