> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 서버 백필 티켓 사용 - Multiplayer SDK

> 진행 중인 매치메이킹 게임 세션의 빈 슬롯을 채우기 위해 Multiplayer SDK로 PlayFab 서버 백필 티켓을 만들고 사용하는 방법을 알아봅니다.

서버에서 호스트되는 게임에서는 때때로 추가 플레이어를 검색해야 합니다. 이 상황은 대부분 게임 진행 중에 하나 이상의 플레이어가 연결을 끊었을 때 발생합니다. 서버 백필 티켓을 사용하면 게임 서버가 현재 진행 중인 게임에 맞는 추가 플레이어를 검색할 수 있습니다.

서버 백필 티켓은 다음과 같은 여러 방식에서 일반 매치메이킹 티켓과 다릅니다.

1. 매칭
   * 백필 티켓끼리는 서로 매칭될 수 없습니다.
   * 검색 중에 백필 티켓에 우선순위가 부여되어 플레이어 기반의 분산화가 감소합니다.
2. 계약
   * 백필 티켓은 `ServerDetails` 필드로 만들 수 있습니다. 이를 통해 서버는 매칭된 플레이어가 서버에 연결하는 방식을 나타낼 수 있습니다.
   * 백필 티켓은 팀 할당으로 만들 수 있습니다. 이를 통해 팀이 있는 게임에서 팀 정보를 유지 관리할 수 있습니다.
3. 큐 속성
   * 백필 티켓은 [Multiplayer Server 할당](/services/playfab/multiplayer/matchmaking/multiplayer-servers)을 트리거하지 않습니다.
   * 백필 티켓의 플레이어는 이미 게임을 플레이하고 있어 대기 시간을 부정확하게 왜곡하므로 [큐 통계](/services/playfab/multiplayer/matchmaking/display-statistics)에 반영되지 않습니다.
4. 소유권
   * 백필 티켓은 사용자가 아니라 게임 서버가 소유합니다. 사용자는 어떤 방식으로든 백필 티켓을 보거나 상호 작용할 수 없습니다.

## 필수 구성 요소

* PlayFab Multiplayer SDK에 대한 기본 지식. 자세한 내용은 [Matchmaking SDK 빠른 시작](/services/playfab/multiplayer/matchmaking/quickstart-client-sdk)을 참조하세요.
* 매치메이킹 헤더를 포함하기 전에 `PFMULTIPLAYER_INCLUDE_SERVER_APIS`를 정의합니다. 예를 들면 다음과 같습니다.

```cpp theme={null}
#define PFMULTIPLAYER_INCLUDE_SERVER_APIS
#include <PFMatchmaking.h>
```

## 서버 백필 티켓 구성

필요한 세부 정보로 [PFMatchmakingServerBackfillTicketConfiguration](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingserverbackfillticketconfiguration) 구조체를 만들고 채웁니다.

* **`timeoutInSeconds`**: 티켓을 채우기 위해 시도할 시간(초)입니다.

* **`queueName`**: 매치 큐의 이름입니다.

* **`memberCount`**: 매치에 현재 있는 멤버 수입니다.

* **`members`**: 매치에 현재 있는 [PFMatchmakingMatchMember](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingmatchmember) 멤버입니다.

* **`serverDetails`**(선택 사항): 클라이언트에 제공되는 서버 정보(FQDN, IP 주소, 포트, 지역)로 [PFMultiplayerServerDetails](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails)를 채웁니다.

<Note>
  `PFMultiplayerServerDetails::ipv4Address` 필드는 유효성이 검증되지 않으며 클라이언트에 임의의 연결 문자열 정보를 제공하는 데 사용될 수 있습니다.
</Note>

```cpp theme={null}
// Define the server port configuration.
PFMultiplayerPort serverPorts[] = {
    { "portname", 12345, PFMultiplayerProtocolType::Udp }
};

// Populate the server details.
PFMultiplayerServerDetails serverDetails = {};
serverDetails.fqdn = "your.server.fqdn.com";
serverDetails.ipv4Address = "123.234.123.234";
serverDetails.ports = serverPorts;
serverDetails.portCount = sizeof(serverPorts) / sizeof(serverPorts[0]);
serverDetails.region = "EastUS";

// Set up the backfill ticket configuration.
PFMatchmakingServerBackfillTicketConfiguration backfillConfig = {};
backfillConfig.timeoutInSeconds = 60;                 // Try for 60 seconds
backfillConfig.queueName = "YourQueueName";
backfillConfig.memberCount = currentMatchMemberCount; // e.g., 4
backfillConfig.members = currentMatchMembers;         // Pointer to an array of PFMatchmakingMatchMember
backfillConfig.serverDetails = &serverDetails;        // Optional; can be nullptr if not needed
```

## 서버 백필 티켓 만들기

서버 백필 티켓을 만들기 위해 [PFMultiplayerCreateServerBackfillTicket](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayercreateserverbackfillticket)을 사용할 때는 이전 단계에서 만든 백필 구성과 함께 게임 서버의 엔터티([PFEntityKey](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayer/pfentitykey_clientsdk) 형태)를 전달해야 합니다.

```cpp theme={null}
PFMatchmakingTicketHandle backfillTicket = nullptr;
HRESULT hr = PFMultiplayerCreateServerBackfillTicket(
    multiplayerHandle,            // The handle of the PFMultiplayer API instance.
    &serverEntity,                // PFEntityKey for your game server entity
    &backfillConfig,              // The backfill ticket configuration.
    nullptr,                      // Optional async context
    &backfillTicket               // The resulting ticket object.
);

if (FAILED(hr))
{
    // handle ticket creation failure
}
```

## 매치메이킹 티켓 상태 확인

[PFMultiplayerStartProcessingMatchmakingStateChanges](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges)를 호출하여 상태 변경 사항을 수신한 다음, 해당 상태 변경 사항 처리가 완료되면 [PFMultiplayerFinishProcessingMatchmakingStateChanges](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerfinishprocessingmatchmakingstatechanges)를 호출하여 티켓 업데이트를 확인해야 합니다.

SDK는 티켓의 상태가 변경될 때마다 **TicketStatusChanged** 상태 변경을 반환하고, 매치메이킹이 완료되면 **TicketCompleted** 상태 변경을 반환합니다.

```cpp theme={null}
HRESULT hrTicketError = S_OK;

uint32_t stateChangeCount;
const PFMatchmakingStateChange * const * stateChanges;
HRESULT hr = PFMultiplayerStartProcessingMatchmakingStateChanges(g_pfmHandle, &stateChangeCount, &stateChanges);
if (FAILED(hr))  
{  
    return;  
}  

for (uint32_t i = 0; i < stateChangeCount; ++i)
{
    const PFMatchmakingStateChange& stateChange = *stateChanges[i];

    switch (stateChange.stateChangeType)
    {
        case PFMatchmakingStateChangeType::TicketStatusChanged:
        {
            const auto& ticketStatusChanged = static_cast<const PFMatchmakingTicketStatusChangedStateChange&>(stateChange);

            PFMatchmakingTicketStatus status;
            if (SUCCEEDED(PFMatchmakingTicketGetStatus(ticketStatusChanged.ticket, &status)))
            {
                printf("Ticket status is now: %i.\n", status);
            }

            break;
        }
        case PFMatchmakingStateChangeType::TicketCompleted:
        {
            const auto& ticketCompleted = static_cast<const PFMatchmakingTicketCompletedStateChange&>(stateChange);

            printf("PFMatchmaking completed with Result 0x%08x.\n", ticketCompleted.result);

            if (FAILED(ticketCompleted.result))
            {
                // On failure, we must record the HRESULT so we can return the state change(s) and then bail
                // out of this function.
                hrTicketError = ticketCompleted.result;
            }

            break;
        }
    }
}

hr = PFMultiplayerFinishProcessingMatchmakingStateChanges(g_pfmHandle, stateChangeCount, stateChanges);
if (FAILED(hr))  
{  
    return;  
}  

// Now that we've returned the state change(s), bail out if we detected ticket failure.
if (FAILED(hrTicketError))  
{  
    return;  
}  
```

## 매치 가져오기

**PFMatchmakingStateChangeType::TicketCompleted** 상태 변경을 수신한 후 [PFMatchmakingTicketGetMatch](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketgetmatch)를 호출하여 매치의 세부 정보를 가져옵니다. 이 세부 정보에는 매치 ID, 서로 매칭된 사용자, 매치에 대한 기본 지역 및 매치와 연결된 로비에 대한 정렬 문자열이 포함되어 있습니다.

**PFMatchmakingMatchDetails** 구조체에서 필요한 정보를 검색한 후에는 [PFMultiplayerDestroyMatchmakingTicket](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket)으로 티켓을 소멸시켜야 합니다.

```cpp theme={null}
const PFMatchmakingMatchDetails* match;
HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
if (FAILED(hr))  
{  
    return;  
}  

std::string matchId = match->matchId;
std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);
```

## 티켓 취소

`PFMatchmakingServerBackfillTicketConfiguration`에 설정된 시간 초과 전에 매치메이킹 프로세스를 취소하려면 티켓 핸들을 사용하여 [PFMatchmakingTicketCancel](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketcancel)을 호출합니다.

이 API 호출로 티켓이 취소된다고 보장되지는 않습니다. 취소가 처리되기 전에 티켓이 완료될 수도 있고, 네트워킹 또는 서비스 오류로 인해 취소 요청이 실패할 수도 있습니다. 계속 진행하기 전에 티켓 취소가 완료되었는지 확인하려면 매치메이킹 상태 변경을 처리하여 티켓 결과를 가져올 수 있습니다. 그렇지 않으면 [PFMultiplayerDestroyMatchmakingTicket](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket)을 즉시 호출할 수 있습니다.

```cpp theme={null}
HRESULT hr = PFMatchmakingTicketCancel(ticket);

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);
```


## Related topics

- [서버 백필 티켓 사용 - REST API](/ko/services/playfab/multiplayer/matchmaking/backfill-tickets.md)
- [로비와 매치메이킹을 함께 사용](/ko/services/playfab/multiplayer/lobby/lobby-and-matchmaking.md)
- [PlayFab Multiplayer C++ SDK 릴리스 정보](/ko/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md)
- [PFMultiplayerCreateServerBackfillTicket](/ko/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayercreateserverbackfillticket.md)
- [PFMatchmakingServerBackfillTicketConfiguration](/ko/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingserverbackfillticketconfiguration.md)
