> ## 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.

# 로비 찾기

> 검색 가능한 속성, 멤버 수 및 거리 기반 정렬에 대한 필터 및 정렬 문자열을 사용하여 공개 PlayFab Lobby를 검색하여 로비를 발견합니다.

플레이어가 맵, 난이도 및 기타 인게임 특성 등 특정 조건 세트를 충족하는 로비를 찾을 수 있게 하는 것은 타이틀에 종종 유용합니다. 이 검색 기능을 통해 플레이어는 원하는 사람들과 함께 원하는 게임 세션을 찾을 수 있습니다.

이 문서에서는 \_\_FindLobbies\_\_를 사용하여 플레이어가 로비를 찾을 수 있도록 하는 방법에 대해 설명합니다. 게임 타이틀에서 로비 찾기가 어떻게 사용될 수 있는지 확인하려면 [일반적인 시나리오](#common-scenarios)를 참조하세요.

<Note>
  백그라운드 매치메이킹을 구현하기 위해 \_\_FindLobbies\_\_를 사용하는 것은 권장되지 않습니다. 이 시나리오에서는 [matchmaking feature](/services/playfab/multiplayer/matchmaking)를 사용하는 것을 강력히 권장합니다. 그렇지 않으면, 검색 데이터 필드에서 무작위 값을 사용하는 등의 필터링, 정렬 및 기타 기법을 통해 동일한 로비에 참여하려는 플레이어들의 충돌을 처리해야 합니다.
</Note>

## 로비 검색 속성과 로비 찾기 간의 관계 이해

플레이어는 검색 속성을 정의하여 자신의 로비를 발견 가능하게 만듭니다. 플레이어는 현재 활성 로비 전반에 정의된 검색 속성을 기반으로 검색 결과를 필터링하고 정렬하기 위해 쿼리 문자열과 함께 \_\_FindLobbies\_\_를 호출하여 이러한 발견 가능한 로비를 찾습니다. 이러한 쿼리와 일치하는 로비가 호출 플레이어에게 반환됩니다.

검색 속성 정의에 대한 자세한 내용은 [검색 가능한 로비 만들기](/services/playfab/multiplayer/lobby/define-search-keywords)를 참조하세요.

## FindLobbies 사용 방법

\_\_FindLobbies\_\_를 호출할 때, filter 매개 변수를 사용하여 로비의 사용자 지정 검색 속성을 기반으로 특정 조건 세트와 일치하는 검색 결과만 반환하도록 쿼리를 제한할 수 있습니다.

또한 sorting 매개 변수를 사용하여 검색 속성을 기반으로 서비스에서 반환받은 결과를 정렬할 수 있습니다. 서비스는 제한된 수의 검색 결과만 반환하므로 이는 유용합니다. 정렬은 가장 관련성 높은 검색 결과를 볼 수 있도록 보장합니다.

### 일반적인 시나리오

다음은 타이틀에서 **FindLobbies** 기능이 사용되는 몇 가지 일반적인 방법입니다.

* 타이틀에서 특정 게임 모드에 대한 게임 세션의 로비 찾기
* 친구가 호스팅하는 게임 세션의 로비 찾기
* 모든 로컬 플레이어를 위한 충분한 플레이어가 있는 게임 세션의 로비 찾기
* 예기치 않은 게임 클라이언트 또는 게임 서버 충돌 후 연결을 복구하기 위해 이미 참여 중인 로비 찾기

### 지원되는 검색 키

사용자 지정 검색 속성을 정의할 때 제한된 키 집합만 사용할 수 있습니다.

* 문자열 속성의 경우 다음 키가 지원됩니다: string\_key1, string\_key2, \[...] string\_key30
* 숫자 속성의 경우 다음 키가 지원됩니다: number\_key1, number\_key2, \[...] number\_key30

### FindLobbies에 대한 쿼리 문자열 구성

**FindLobbies** API에 대한 쿼리 문자열은 OData와 유사한 구문으로 구조화됩니다. 필터 문자열의 최대 크기는 600자입니다.

이러한 OData 연산자를 사용하여 쿼리 문자열을 구성할 수 있습니다. 연산자는 대소문자를 구분합니다.

| 연산자 | 의미    | 예제                                                      |
| --- | ----- | ------------------------------------------------------- |
| eq  | 같음    | string\_key1 eq 'CaptureTheFlag'                        |
| lt  | 미만    | number\_key2 lt 10                                      |
| le  | 이하    | number\_key2 le 10                                      |
| gt  | 초과    | number\_key3 gt 100                                     |
| ge  | 이상    | number\_key3 ge 100                                     |
| ne  | 같지 않음 | string\_key1 ne 'CaptureTheFlag'                        |
| and | and   | string\_key1 eq 'CaptureTheFlag' and number\_key2 lt 10 |

<Note>
  문자열 속성을 비교할 때, 비교되는 값을 작은따옴표로 감싸도록 하세요. 예: "string\_key1 eq **'SOME STRING VALUE'**". 숫자 속성은 감쌀 필요가 없습니다.
</Note>

사용할 수 있는 미리 정의된 연산자도 있습니다. 지정 시 반드시 "lobby/" 접두사가 붙어야 합니다.

| 연산자                  | 의미                                       | 예제                                 |
| -------------------- | ---------------------------------------- | ---------------------------------- |
| memberCount          | 로비의 플레이어 수                               | lobby/memberCount eq 5             |
| maxMemberCount       | 로비에 허용되는 최대 플레이어 수                       | lobby/maxMemberCount gt 10         |
| memberCountRemaining | 로비에 참여할 수 있는 남은 플레이어 수                   | lobby/memberCountRemaining gt 0    |
| membershipLock       | 로비의 잠금 상태, 'Unlocked' 또는 'Locked'와 같아야 함 | lobby/membershipLock eq 'Unlocked' |
| amOwner              | 사용자가 소유자인 로비, 'true'와 같아야 함              | lobby/amOwner eq 'true'            |
| amMember             | 사용자가 멤버인 로비, 'true'와 같아야 함               | lobby/amMember eq 'true'           |
| amServer             | 서버가 클라이언트 소유 로비에 참여한 로비, 'true'와 같아야 함   | lobby/amServer eq 'true'           |

이러한 상수에 대한 SDK 정의는 [여기](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/constants/pflobbysearchkeys)에 문서화되어 있습니다.

### 정렬

오름차순("asc") 또는 내림차순("desc") 순서로 이 쿼리에 대한 정렬을 포함하는 OData 스타일 문자열. OrderBy 절은 검색 숫자 키 또는 숫자인 미리 정의된 검색 키 중 어느 것에나 사용할 수 있습니다. 숫자에 가장 가까운 것으로 정렬하려면, 지정된 숫자 검색 키로부터의 거리로 정렬하기 위해 distance 모니커를 사용할 수 있습니다. distance 정렬과 함께 오름차순 또는 내림차순을 사용할 수 없습니다. 이 필드는 하나의 정렬 절 또는 하나의 distance 절만 지원합니다. 정렬이 제공되지 않거나 주어진 정렬에 대한 동점 판정이 필요한 경우, 기본 정렬은 생성 시간을 기준으로 내림차순이 됩니다.

| 예제                          | 의미                    |
| --------------------------- | --------------------- |
| number\_key1 asc            | 숫자 검색 키를 기준으로 오름차순 정렬 |
| lobby/memberCount desc      | 숫자 검색 키를 기준으로 내림차순 정렬 |
| distance\{number\_key1 = 5} | 주어진 숫자로부터의 거리로 정렬     |
| *default*                   | 생성 시간을 기준으로 내림차순 정렬   |

## Lobby and Matchmaking SDK를 사용하여 로비를 찾는 예제

이 예제에서, 플레이어는 다음 요구 사항을 가진 모든 로비를 찾고자 합니다.

* 게임 모드는 "DeathMatch"입니다.
* 경쟁 스타일은 "Ranked"입니다.
* 플레이어의 스킬 레벨이 로비의 최소 및 최대 스킬 제한 내에 있습니다.

또한, 플레이어는 결과를 다음 지침으로 정렬하려고 합니다.

* 플레이어의 스킬 레벨에 가장 가까운 최적의 스킬 레벨을 가진 로비가 더 높게 정렬되어야 합니다.

```cpp theme={null}
static PFMultiplayerHandle g_pfmHandle = nullptr;

#define SUPPORT_XBL_CROSSPLAY

#define PFLOBBY_SEARCH_KEY_GAME_MODE "string_key1"
#define PFLOBBY_SEARCH_KEY_COMPETITION_STYLE "string_key2"
#define PFLOBBY_SEARCH_KEY_SKILL "number_key1"

#define GAME_MODE_DEATH_MATCH "DeathMatch"
#define COMPETITION_STYLE_RANKED "Ranked"

// Find lobbies based on player's search criteria.
void FindGamesWithRuntimeQuery(
    uint32_t minimumSkill,
    uint32_t maximumSkill,
    uint32_t optimalSkill)
{
    PFLobbySearchFriendsFilter friendsFilter;
    friendsFilter.includeSteamFriends = true;
#ifdef SUPPORT_XBL_CROSSPLAY
    friendsFilter.includeXboxFriendsToken = MyGame::GetLocalUserXboxToken();
#endif // SUPPORT_XBL_CROSSPLAY

    // Limit results based on friend's filter.
    PFLobbySearchConfiguration searchConfiguration = { 0 };
    searchConfiguration.friendsFilter = &friendsFilter;

    // Create filter string based on player's search parameters.
    std::string filterString;
    filterString += PFLOBBY_SEARCH_KEY_GAME_MODE + std::string(" eq ") + "'" + GAME_MODE_DEATH_MATCH + "'";
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_COMPETITION_STYLE + std::string(" eq ") + "'" + COMPETITION_STYLE_RANKED + "'";
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" ge ") + std::to_string(minimumSkill);
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" le ") + std::to_string(maximumSkill);

    // Create sort string based on player's sort preference.
    std::string sortString;
    sortString += std::string("distance{") + PFLOBBY_SEARCH_KEY_SKILL + "=" + std::to_string(optimalSkill) + "}";

    searchConfiguration.filterString = filterString.c_str();
    searchConfiguration.sortString = sortString.c_str();

    HRESULT hr = PFMultiplayerFindLobbies(g_pfmHandle, &m_localUser, &searchConfiguration, nullptr);
}

void ProcessStateChanges()
{
    while (true)
    {
        uint32_t stateChangeCount;
        const PFLobbyStateChange* const* stateChanges;
        RETURN_VOID_IF_FAILED(PFMultiplayerStartProcessingLobbyStateChanges(
            g_pfmHandle,
            &stateChangeCount,
            &stateChanges));

        for (uint32_t i = 0; i < stateChangeCount; ++i)
        {
            const PFLobbyStateChange* stateChange = stateChanges[i];
            switch (stateChange->stateChangeType)
            {
                case PFLobbyStateChangeType::FindLobbiesCompleted:
                {
                    GuiPostCurrentLobbySearchResults(
                        static_cast<const PFLobbyFindLobbiesCompletedStateChange&>(*stateChange));
                    break;
                }
                default:
                {
                    break;
                }
            }
        }

        RETURN_VOID_IF_FAILED(PFMultiplayerFinishProcessingLobbyStateChanges(
            g_pfmHandle,
            stateChangeCount,
            stateChanges));
    }
}

// Update game UI to display search results when a list of matching lobbies is returned.
void GuiPostCurrentLobbySearchResults(
    const PFLobbyFindLobbiesCompletedStateChange& stateChange)
{
    if (FAILED(stateChange.result))
    {
        GuiToastErrorAndExitScreen();
        return;
    }

    for (uint32_t i = 0; i < stateChange.searchResultCount; ++i)
    {
        const PFLobbySearchResult& searchResult = stateChange.searchResults[i];
        GuiPostLobbySearchResultRow(searchResult); // defined elsewhere
    }
}
```

## 참고

* [검색 가능한 로비 만들기](/services/playfab/multiplayer/lobby/define-search-keywords)
* [로비 참여](/services/playfab/multiplayer/lobby/join-lobbies)
* [Lobby 및 matchmaking](/services/playfab/multiplayer/lobby/lobby-and-matchmaking)
* [Lobby properties](/services/playfab/multiplayer/lobby/lobby-properties)
* [로비 만들기](/services/playfab/multiplayer/lobby/create-a-lobby)


## Related topics

- [Multiplayer Unity 플러그인 빠른 시작](/ko/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md)
- [MPSD에서 PlayFab Multiplayer 및 MPA로 이동](/ko/services/xbox-services/multiplayer/mpsd/concepts/live-mpsd-to-mlp.md)
- [로비 초대](/ko/services/playfab/multiplayer/lobby/lobby-invites.md)
- [로비 참여](/ko/services/playfab/multiplayer/lobby/join-lobbies.md)
- [검색 가능한 로비 만들기](/ko/services/playfab/multiplayer/lobby/define-search-keywords.md)
