# Lobby 사용

> Use Cloud Code and Lobby service together to trigger server-side actions when players join lobbies.

게임에서 Lobby와 Cloud Code를 함께 사용하여 일반적인 트리거를 정의할 수 있습니다. 게임 로비가 매치를 시작할 준비가 된 상황이라고 가정합니다. 준비된 게임 로비에 대한 응답으로 다음 스크립트를 트리거할 수 있습니다. 이 예시에서는 [Remote Config](/remote-config.md)와의 연동도 함께 다룹니다.

이 예시를 따르기 전에 [Unity Dashboard](https://cloud.unity.com)를 통해 Lobby와 Cloud Code 모두를 활성화하고 단계에 따라 필수 SDK를 설치하시기 바랍니다. 서비스 인증을 사용하여 프로젝트에서 [로비를 생성](/lobby/create-a-lobby.md)하고 [ID](https://cloud-code-sdk-documentation.cloud.unity3d.com/lobby/v1.0/lobby)를 기록해 둡니다. Cloud Code를 통해 이를 수행할 수 있습니다([Unity Lobby](../how-to-guides/unity-services-integration#using-the-unity-lobby-sdk) 예시 확인).

다음 예시는 로비 ID, 그리고 로비 생성에 사용되는 서비스 ID라는 두 파라미터를 스크립트에 제공합니다. 로비를 만든 다음 메타데이터에 여러 변경 사항을 적용하여 업데이트합니다. 이러한 변경 사항은 다음과 같습니다.

* 신규 플레이어가 더 이상 참여할 수 없도록 로비를 잠급니다.
* 로비의 플레이어 ID를 사용하여 게임의 무작위 ‘플레이어 순서’를 구성합니다.
* Remote Config에 정의된 `LOBBY_CURRENT_MAPS` 설정을 사용하여 게임의 맵을 무작위로 선택합니다. 스크립트가 성공 또는 실패를 나타내는 기본 부울을 반환합니다.

###### JavaScript##javascript

```js
const _ = require("lodash-4.17");
const { LobbyApi, DataObjectVisibilityEnum } = require("@unity-services/lobby-1.2");
const { SettingsApi } = require("@unity-services/remote-config-1.1");

module.exports = async ({params,context,logger}) => {
    const { serviceId, lobbyId } = params;
    const { projectId, environmentId, playerId } = context;
    const lobbyApi = new LobbyApi(context);
    const remoteConfig = new SettingsApi(context);

    try {
        const {data: lobby} = await lobbyApi.getLobby(lobbyId, serviceId);
        return setUpGame(remoteConfig, projectId, environmentId, serviceId, lobbyApi, logger, lobby);
    } catch (err) {
       logger.error(`Failed to set up lobby: ${err.response.data.detail}`);
       return false;
    }

};

// Updates a lobby to set up for the start of a game, including reading a value from Remote Config to randomly assign to the lobby.
async function setUpGame(remoteConfig, projectId, environmentId, serviceId, lobbyApi, logger, lobby) {
    let playerIds = [];
    for (let i = 0; i < lobby.players.length; i++) {
        playerIds.push(lobby.players[i].id);
    }

    // Generate a turn order for the game by shuffling the player IDs.
    _.shuffle(playerIds);

    // Load all of the maps that are currently configured as available in Remote Config and pick a random one for this game.
    let maps = getCurrentMapsFromRemoteConfig(remoteConfig, projectId, environmentId)
    if (maps == null) {
      throw "Maps loaded from Remote Config are null.";
    }
    let gameMap = _.sample(maps);

    try {
      const updateResponse = await lobbyApi.updateLobby(
          lobby.id,
          serviceId,
          null,
          {
              isLocked: true, // Lock the lobby so that new players cannot join.
              hostId: playerIds[0], // Transfer host ownership from the service to one of the players.
              data: {
                  "playerOrder": {
                      value: playerIds.toString(),
                      visibility: DataObjectVisibilityEnum.Member // Set the visibility of the player order so that only lobby members can access it.
                  },
                  "map": {
                      value: gameMap,
                      visibility: DataObjectVisibilityEnum.Public // Set the visibility of the game map so that anyone who views the lobby can access it.
                  }
              }
          }
      );

      return true;
    } catch (err) {
      throw err;
    }

    return lobbyUpdateSuccess;
}

// Loads the Remote Config JSON value for LOBBY_CURRENT_MAPS and returns the array of maps inside of it.
// If the JSON is invalid, the return value is null.
async function getCurrentMapsFromRemoteConfig(remoteConfig, projectId, environmentId) {
  const currentMapsId = 'LOBBY_CURRENT_MAPS';
  const remoteConfigResponse = await remoteConfig.assignSettingsGet(
    projectId,
    environmentId,
    'settings',
    [currentMapsId]
  );

  let mapsJSON = remoteConfigResponse?.data?.configs?.settings?.[currentMapsId];
  if (!mapsJSON || !mapsJSON.maps || mapsJSON.maps.length == 0) {
    return null;
  }

  return mapsJSON.maps;
}

// Uncomment the code below to enable the inline parameter definition
// - Requires Cloud Code JS dev environment setup with NodeJS (https://docs.unity3d.com/Packages/com.unity.services.cloudcode@latest/index.html?subfolder=/manual/Authoring/javascript_project.html)
//
// module.exports.params = {
//   serviceId: { type: "String", required: true },
//   lobbyId: { type: "String", required: true },
// };
```

> **Note:**
>
> **참고:** Unity 에디터를 사용하여 스크립트를 관리하는 경우 스크립트 하단의 코드 주석 처리를 해제하여 스크립트 내의 필수 `serviceId`와 `lobbyId` 파라미터를 선언할 수 있습니다. 스크립트 내 파라미터 관리 방법에 관한 자세한 내용은 [Unity 에디터](../../scripts/how-to-guides/write-scripts/unity-editor#modify-script-parameters) 내에서 스크립트 파라미터 수정을 참고하십시오.

이 Remote Config JSON의 구조는 단순하지만 이 예시 구성을 확장하여 게임을 더 세밀하게 제어할 수 있습니다. 마찬가지로 게임 설정 외에 Cloud Code에서 다양한 트리거를 고려할 수 있으며, 그 예시는 다음과 같습니다.

* 로비 생성에 따라 트리거하여 메타데이터 값을 조정하고 문자열을 다듬습니다.
* Cloud Save 플레이어 데이터를 사용하여 플레이어의 쿼리 결과를 필터링하고, 참여를 승인/거부하고, 메타데이터를 설정합니다.
* Economy 데이터를 사용하여 플레이어 또는 로비 메타데이터를 설정합니다.
