> 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/server-browser.md).

# Server Browser

Server Browser를 빠르게 시작하고 다양한 장르의 예시 시나리오를 살펴보세요.

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

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

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

## ✔️ 준비

### 기능 및 흐름

<figure><img src="/files/7c2984dc6f2a416a77e05acf68813c4cc306894c" 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시간 연중무휴로 실행되어야 합니다** 전 세계 플레이어가 서버에 참여할 수 있도록 보장하기 위해.
{% endhint %}

## ▶️ 탐색 시작

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

### 인증

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

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

### 인스턴스 검색

{% hint style="warning" %}
**신규** [배포](/docs.edgegap.com-ko/learn/orchestration/deployments.md) **새 인스턴스를 생성해야 합니다** 초기화 시 추가된 용량을 추적하기 위해.
{% endhint %}

{% hint style="info" %}
참조 [#automated-scaling](#automated-scaling "mention") 스케일링 정책을 알아보고 배포를 자동으로 시작하려면.
{% endhint %}

**필수 정보** 각 서버 인스턴스에는 다음이 포함됩니다:

* 인스턴스를 초기화할 때 최소 하나의 슬롯이 정의되어 있어야 하며,
* 서버 연결 정보 - URL, IP, 포트 정보 및 위치.

**선택적 사용자 지정 메타데이터 매개변수** 플레이어 필터링, 정렬 및 탐색용; 예:

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

{% hint style="info" %}
위의 메타데이터 매개변수는 예시일 뿐이며, 필요에 따라 원하는 수의 매개변수를 정의할 수 있습니다.
{% endhint %}

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

서버는 **언제든지 인스턴스 또는 슬롯 메타데이터를 업데이트할 수 있습니다** 검색 가능 기준을 수정하기 위해. 메타데이터를 업데이트할 때는 모든 인덱싱된 키에 유효한 값이 제공되어야 합니다(수정되지 않았더라도).

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

{% hint style="info" %}
참조 [지속성](/docs.edgegap.com-ko/learn/orchestration/persistence.md) 영구적인 월드 상태를 관리하고 [앱 및 버전](/docs.edgegap.com-ko/learn/orchestration/application-and-versions.md#active-caching) 더 빠른 배포를 위해.
{% endhint %}

### 용량 할당

인스턴스 및 슬롯 용량은 두 가지 방식으로 할당할 수 있으며, 개별적으로 또는 결합하여 사용할 수 있습니다:

* [#auto-assigned-reservation](#auto-assigned-reservation "mention") 특정 스케일링 정책으로 시작된 서버를 선택하려면,
* [#search-and-browse](#search-and-browse "mention") 플레이어가 필터를 정의하고 선택할 수 있는 적합한 서버를 탐색하게 하려면.

{% hint style="success" %}
다음으로 시작할 것을 권장합니다 [#auto-assigned-reservation](#auto-assigned-reservation "mention") 가 더 간단한 옵션입니다.
{% endhint %}

#### 자동 할당 예약

{% hint style="info" %}
다음을 원한다면 이 기능을 구현하세요 **서버를 자동으로 선택**지역 용량을 기준으로.
{% endhint %}

플레이어는 플레이어 ID와 스케일링 정책 이름만 제공하여 자동 할당 예약을 만들 수 있습니다. Server Browser는 참여 가능한 용량이 충분한 슬롯이 있는 인스턴스를 자동으로 찾아 좌석을 예약하고, 인스턴스 연결 정보를 즉시 응답합니다.

이 예약에 적합한 인스턴스 슬롯이 없으면, 응답:

* **상태 코드는 정책이 확장 중인지 여부를 나타냅니다** 그리고 더 많은 용량이 추가될 예정이며,
* **헤더 `Retry-After`  재시도 전에 대기 기간(초)을 나타냅니다**재시도 가능한 경우.

예약이 완료되면 다음으로 건너뛸 수 있습니다 [#connect-to-server](#connect-to-server "mention").

#### 검색 및 탐색

{% hint style="info" %}
다음을 원한다면 이 기능을 구현하세요 **사용자에게 서버 목록을 보여주고 사용자 지정 예약을 허용합니다**.
{% endhint %}

플레이어는 서버 인스턴스를 나열하고 [결과를 페이지 단위로 검색하여](#pagination) 참여하고 싶은 서버를 찾을 수 있습니다.

인스턴스와 슬롯은 내장 매개변수 또는 [인덱싱된 메타데이터로 필터링하고 정렬할 수 있습니다](#configuration):

<table><thead><tr><th width="400">속성</th><th width="140">데이터 형식</th><th width="105">인스턴스</th><th width="105">슬롯</th></tr></thead><tbody><tr><td><code>요청 ID</code></td><td><code>문자열</code></td><td>✅</td><td>❌</td></tr><tr><td><code>총 참여 가능 좌석 수</code>, <code>총 사용 가능 좌석 수</code></td><td><code>정수</code></td><td>✅</td><td>❌</td></tr><tr><td><code>이름</code></td><td><code>문자열</code></td><td>❌</td><td>✅</td></tr><tr><td><code>사용 가능 좌석 수</code>, <code>예약된 좌석 수</code></td><td><code>정수</code></td><td>❌</td><td>✅</td></tr><tr><td><code>생성 시각</code>, <code>수정 시각</code></td><td><code>문자열</code></td><td>✅</td><td>✅</td></tr><tr><td><code>메타데이터.{index}</code> (사용자 지정)</td><td><code>문자열</code>, <code>정수</code>, <code>실수</code>, <code>불리언</code></td><td>✅</td><td>✅</td></tr></tbody></table>

사용 가능한 필터링 연산자는 필터링된 속성의 데이터 형식에 따라 다릅니다:

<table><thead><tr><th width="125">매개변수</th><th width="135">연산자</th><th>예시 필터(간단한 예시 기준)</th></tr></thead><tbody><tr><td><code>문자열</code></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>같음</code></a>  또는 <a data-footnote-ref href="#user-content-fn-3"><code>같지 않음</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-4"><code>미만</code></a>  또는 <a data-footnote-ref href="#user-content-fn-5"><code>이하</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>초과</code></a>  또는 <a data-footnote-ref href="#user-content-fn-7"><code>이상</code></a>  또는<br><code>포함</code></p></td><td><pre><code>?$filter=metadata.custom_name contains '내 게임'
and metadata.server_version le '1.1.0'
and metadata.server_version ge '1.0.0'
&#x26;$order=metadata.custom_name asc
</code></pre></td></tr><tr><td><code>정수</code>, <code>실수</code></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>같음</code></a>  또는 <a data-footnote-ref href="#user-content-fn-3"><code>같지 않음</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-4"><code>미만</code></a>  또는 <a data-footnote-ref href="#user-content-fn-5"><code>이하</code></a> 또는 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>초과</code></a>  또는 <a data-footnote-ref href="#user-content-fn-7"><code>이상</code></a>  </p></td><td><pre><code>?$filter=metadata.xp_multiplier gt 1.0
&#x26;$order=metadata.xp_multiplier desc
</code></pre></td></tr><tr><td><code>불리언</code></td><td><a data-footnote-ref href="#user-content-fn-2"><code>같음</code></a>  또는 <a data-footnote-ref href="#user-content-fn-3"><code>같지 않음</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 %}

#### 좌석 예약

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

연합 신원: 플레이어는 예약 시 고유한 타사 플레이어 ID를 제공해야 합니다. 그 ID를 다시 보내면 [#connect-to-server](#connect-to-server "mention") 서버가 해당 신원을 확인할 수 있게 됩니다.

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

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

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

### 서버에 연결

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

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

{% hint style="success" %}
연결 실패 또는 검은 화면이 발생하면 다음을 참조하세요: [문제 해결 가이드](/docs.edgegap.com-ko/unreal-engine.md#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" %}
연결 시간 초과 또는 기타 문제가 발생하면 다음을 참조하세요: [문제 해결 가이드](/docs.edgegap.com-ko/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

새 연결을 인증하려면, **서버는 대량 예약 확인** 요청에 모든 새 플레이어의 ID를 포함해야 하며, 확인 응답에서 다음 정보를 받습니다:

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

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

### 서버 포기

플레이어가 떠나면 서버는 할당된 슬롯의 사용 가능 좌석 용량을 늘려야 합니다.

{% hint style="success" %}
게임 디자인이 재연결 기간을 허용한다면 서버는 슬롯을 업데이트하기 전에 기다릴 수 있습니다.
{% endhint %}

다음을 읽어보세요 [지속성](/docs.edgegap.com-ko/learn/orchestration/persistence.md#recovery-objectives) 성가신 영구 서버 롤백을 방지하려면.

## 🚀 자동 스케일링

Server Browser는 여러 가지 자동 스케일링 방식과 호환됩니다:

* **사전 예열 방식** - 서버를 오직 Server Browser 스케일링 정책으로만 시작,
* **적시 방식** - 다음을 통해 시작 [매치메이킹](/docs.edgegap.com-ko/learn/matchmaking.md) 및 [Server Browser로 채우기](#allocate-capacity),
* **맞춤 자동 스케일러** - 맞춤 게임 백엔드를 통해 시작하고 [Server Browser로 채우기](#allocate-capacity).

다음 가이드는 **스케일링 정책을 사용한 사전 예열에** 을 주요 방법으로 다룹니다.

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

### 용량 모니터링

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

구성한 [`minimum_active_instances`](#user-content-fn-9)[^9]  수는 다음 중 하나로 간주할 수 있습니다:

* **고정 용량** 항상 실행 상태로 유지하고 싶은 배포 수,
* **사전 예열 대기** 초기화 지연을 숨기기 위한 배포 버퍼.

#### 고정 용량

다음과 같은 게임을 위해 활성 서버 수를 고정으로 유지하세요 [지속성](/docs.edgegap.com-ko/learn/orchestration/persistence.md)항상 실행 상태로 유지하고 싶은 배포 수, [지속성](/docs.edgegap.com-ko/learn/orchestration/persistence.md#community-servers).

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

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

#### 사전 예열 대기

다음 경우 플레이어 수요보다 먼저 서버를 시작하세요:

* 대규모 출시를 진행 중이며 짧은 시간에 플레이어가 급격히 유입될 것으로 예상되거나,
* 또는 서버 초기화에 30초 이상이 걸리고([배포 시간 제외](#user-content-fn-10)[^10]),
* 또는 게임이 계층형 또는 순환형 네트워크 종속성을 요구하는 메시싱 전략을 구현하는 경우.

### 서버 배포

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

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

정책은 배포를 다음 방식으로 시작합니다 [프라이빗 플릿](/docs.edgegap.com-ko/learn/orchestration/private-fleets.md) (Overflow to Cloud를 사용하거나) 또는 직접 Cloud로.

사용 가능한 매개변수에는 다음이 포함됩니다 ([API 사양을 참조하세요](/docs.edgegap.com-ko/docs/api/dedicated-servers.md#private-fleets)):

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

### 예시 정책

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

{% tabs %}
{% tab title="🍀 QA 풀" %}
항상 테스트용 서버 하나를 배포 상태로 유지하는 간단한 정책입니다.

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

{% endtab %}

{% tab title="🌡️ 사전 워밍" %}
출시 전에 수요를 대비해 10배 규모의 배포를 시작합니다. 각 지역별로 복사하세요.

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

{% endtab %}

{% tab title="🔒 MMO" %}
각 지역은 사용 가능한 용량이 임계값 아래로 떨어질 때 배포를 추가합니다.

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

{% endtab %}

{% tab title="🔑 커뮤니티" %}
각 서버 소유자당 하나의 정책으로, 서버 인증에 사용되는 사용자 지정 비밀번호를 전달합니다.

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

{% endtab %}

{% tab title="❄️ 메쉬 그룹" %}
서버 그룹당 하나의 정책입니다. 게임 백엔드는 기본 노드를 시작하고, 기본 노드는 복제본을 생성합니다. 각 노드는 주입된 메쉬 그룹 ID를 읽고 네트워크를 구성할 다른 노드를 검색합니다.

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

{% endtab %}
{% endtabs %}

## ⚙️ 구성

Server Browser API는 새 Server Browser를 생성할 때(또는 빠르게 재시작할 때) 지정하는 JSON 구성에서 생성됩니다. 서버 및 슬롯 만료와 사용자 지정 메타데이터를 지정할 수 있습니다:

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

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

{% endtab %}

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

<pre class="language-json" data-title="sb-social-example-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"policy_name": "string",
			"name": "문자열",
			"third_party_id": "문자열",
			"level": "문자열",
			"mode": "문자열",
			"difficulty": "문자열",
			"seed": "문자열",
			"max_players": "정수",
			"app_version": "문자열",
			"location.city": "문자열"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"third_party_id": "문자열",
			"max_players": "정수",
			"avg_latency": "정수",
			"player_ids": "문자열"
		}
	},
	"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-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"policy_name": "string",
			"name": "문자열",
			"third_party_id": "문자열",
			"level": "문자열",
			"mode": "문자열",
			"difficulty": "문자열",
			"avg_rank": "정수",
			"max_players": "정수",
			"app_version": "문자열",
			"tags": "문자열",
			"match_id": "문자열",
			"location.city": "문자열"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"third_party_id": "문자열",
			"max_players": "정수",
			"player_ids": "문자열"
		}
	},
	"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-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"policy_name": "string",
			"name": "문자열",
			"third_party_id": "문자열",
			"avg_rank": "정수",
			"max_players": "정수",
			"is_ranked": "불리언",
			"app_version": "문자열",
			"cpu_frequency": "정수",
			"match_id": "문자열",
			"location.city": "문자열"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">인덱스</a>": {
			"third_party_id": "문자열",
			"max_players": "정수",
			"avg_rank": "정수",
			"avg_latency": "정수"
		}
	},
	"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 %}

## ☁️ 호스팅 클러스터

서버 브라우저는 Edgegap이 24시간 연중무휴로 편리하게 호스팅하고 관리합니다.

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

### 프라이빗 클러스터 등급

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

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

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

## 📗 API

**다음을 위해 저희 SDK 사용을 고려해 보세요** [**언리얼 엔진**](/docs.edgegap.com-ko/unreal-engine/developer-tools.md) **또는** [**Unity**](/docs.edgegap.com-ko/unity/server-browser.md) **미리 만들어진 예제로 빠르게 시작하세요.**

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

{% file src="/files/1c6d459a27e33e6f5e83c155e1922ea959dd475c" %}

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" %}
**Server Browser의 최신 버전은 `1.0.0`** . 다음 사항을 주의 깊게 살펴보세요 [업데이트 및 공지](/docs.edgegap.com-ko/docs/release-notes.md).
{% endhint %}

[^1]: 타사 플레이어 식별자

[^2]: 같음

[^3]: 같지 않음

[^4]: 보다 작음

[^5]: 작거나 같음

[^6]: 보다 큼

[^7]: 크거나 같음

[^8]: 설정 참조

[^9]: 예시 정책 참조

[^10]: 활성 캐싱을 사용하여 배포 시간을 쉽게 줄일 수 있거나

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

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

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

[^14]: 시카고 좌표

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

[^16]: 시카고 지역에서 최소 10개의 배포가 필요합니다

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

[^18]: 용량이 있으면 프라이빗 플릿을 우선 사용

[^19]: 서버가 재시작되면 게임 백엔드에 알립니다

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

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

[^22]: 배포가 실패하면 게임 백엔드에 알립니다

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

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

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/docs.edgegap.com-ko/learn/server-browser.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
