Amazon GameLift Realtime Server Workshop 진행 해보기- Part.4 (Option) 클라이언트 서비스 설치

An mihyang
Cloud Villains
Published in
16 min readJun 30, 2023

워크샵 출처: https://catalog.us-east-1.prod.workshops.aws/workshops/bccf7c14-8f6f-441b-a4ff-fd6a2b402892/ja-JP/30-client-service

이번 게시글에서는 GameLift에 클라이언트 서비스를 설치하고 게임 클라이언트에서 직접 요청을 보내지 않고 클라이언트 서비스에서 요청을 보내도록 변경하는 작업을 진행 하겠습니다.

1. Lambda 함수 만들기

Lambda 함수는 서버리스 컴퓨팅 서비스인 AWS Lambda에서 실행하는 코드입니다. AWS Lambda는 이벤트 발생 시 Lambda 함수를 실행하여 고객을 대신하여 기본 컴퓨팅 리소스를 관리합니다. AWS Lambda에 대한 자세한 내용은 공식 사이트를 참조하시길 바랍니다.

1.1. Lambda 함수 만들기

AWS Management Console의 서비스 검색 필드에 Lambda를 입력한 다음 검색어에 표시되는 Lambda를 클릭합니다.

콘솔 화면의 우측 상단에 리전 확인 후 Lambda 화면에서 함수 생성 버튼을 클릭합니다.

함수 생성 화면에서 아래와 같이 설정한 후에 함수 생성버튼을 클릭합니다.

  • 옵션: 새로 작성
  • 함수 이름: GameLiftClientService
  • 런타임: Node.js 14.x

그 외 나머지 설정은 기본 값으로 설정합니다.

생성된 함수 화면을 스크롤하여 코드 소스 화면을 확인합니다. 해당 뷰어에 아래 코드를 붙여 넣습니다.

const AWS = require('aws-sdk');
// TODO region 설정
const GameLift = new AWS.GameLift({region: 'ap-northeast-1'});

// TODO aliasID 설정
const aliasID = "alias-00000000-0000-0000-0000-000000000000";

exports.handler = async (event) => {
let response;

switch (event.Action) {
case "CreateRoom":
// 게임 세션 생성
await GameLift.createGameSession({
AliasId: aliasID,
MaximumPlayerSessionCount: 2,
Name: event.RoomName
}).promise().then(data => {
response = data.GameSession;
}).catch(err => {
response = err;
});
break;
case "JoinRoom":
// 플레이어 세션 생성
await GameLift.createPlayerSession({
GameSessionId : event.GameSessionId,
PlayerId: event.PlayerId,
}).promise().then(data => {
response = data.PlayerSession;
}).catch(err => {
response = err;
});
break;
case "SearchRooms":
// 사용 가능한 게임 세션 찾기
await GameLift.searchGameSessions({
AliasId: aliasID,
FilterExpression: "hasAvailablePlayerSessions=true"
}).promise().then(data => {
console.log(data.GameSessions);
response = { GameSessions: data.GameSessions };
}).catch(err => {
response = err;
});
break;
default:
response = {
statusCode: 500,
};
break;
}
return response;
};

붙여 넣은 소스 코드를 수정합니다.

  • 3번째 줄을 현재 사용 중인 리전으로 수정

const GameLift = new AWS.GameLift({region: 'ap-northeast-1'});

  • 6번째 줄의 내용을 GameLift 콘솔에서 생성한 별칭의 ID로 수정

const aliasID = "alias-00000000-0000-0000-0000-000000000000";

  • GameLift 별칭(alias) ID 확인하기

GameLift → 별칭 → ID 확인

수정이 완료 되었으면 편집기 상단의 Deploy 버튼을 클릭하여 적용합니다.

편집기 상단의 탭 → 구성 → 권한 → 실행 역할을 확인합니다.

설정되어있는 역할을 클릭합니다.

역할을 클릭하면 IAM의 해당 역할 설정 페이지가 열립니다.

권한 탭 → 권한 추가 클릭 → 정책 변경을 클릭합니다.

권한 정책 검색 필드에 GameLiftClientServicePolicy을 검색하여 체크한 후에 권한 추가 버튼을 클릭합니다.

다시 Lambda 함수 설정 화면으로 돌아갑니다. 브라우저 화면을 새로고침 합니다.

구성 → 권한 → 리소스 요약 → 리소스별 클릭

아래와 같이 Amazon GameLift에 대한 권한이 추가된 것을 확인할 수 있습니다.

2. Amazon Cognito ID Pool 준비

이 섹션에서는 게임 클라이언트에서 클라이언트 서비스(Lambda 함수)를 호출할 수 있도록 Amazon Cognito를 사용하여 클라이언트 인증 처리를 수행할 준비를 진행합니다.

Amazon Cognito는 웹 및 모바일 애플리케이션의 인증, 권한 부여 및 사용자 관리를 지원합니다. 이번에는 게임 클라이언트를 인증하고 AWS 리소스(Lambda 함수)에 대한 액세스를 제어하는 솔루션으로 사용합니다. Amazon Cognito에 대한 자세한 내용은 공식 사이트를 참조해 주세요.

2.1. Amazon Cognito ID Pool 준비

AWS Management Console 서비스 검색 필드에 cognito 검색하여 클릭합니다.

Amazon Cognito 대시보드에서 자격 증명 풀을 클릭한 후에 자격 증명 풀 생성 버튼을 클릭합니다.

1단계 자격 증명 풀 신뢰 구성을 아래와 같이 설정한 후에 다음 버튼을 클릭합니다.

  • 사용자 액세스 : 인증된 액세스
  • 인증된 보안 인증 정보 소스 : Amazon Cognito 사용자 풀

2단계 권한 구성을 아래와 같이 설정한 후에 다음 버튼을 클릭합니다.

  • IAM 역할 : 새 IAM 역할 생성
  • IAM 역할 이름 : Cognito_puzzleAuth_role

3단계 속성 구성에서 자격 증명 풀 이름을 설정한 후에 다음 버튼을 클릭합니다.

  • 자격 증명 풀 이름 : Puzzle

검토 후 자격 증명 풀 생성 버튼 클릭하여 생성을 완료합니다.

생성된 자격 증명 풀을 선택한 후에 사용자 액세스 탭 → 게스트 액세스 → 설정되어있는 역할을 클릭합니다.

역할을 클릭하면 IAM의 해당 역할 설정 페이지가 열립니다.

권한 탭에서 정책을 확장하고 편집 버튼을 클릭합니다.

JSON을 클릭하여 아래 코드를 정책 편집기 창에 붙여 넣습니다.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Invoke",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:ap-northeast-1:000000000000:function:GameLiftClientService"
},
{
"Effect": "Allow",
"Action": [
"mobileanalytics:PutEvents",
"cognito-sync:*"
],
"Resource": [
"*"
]
}
]
}

이 때, 10 행의 코드에 1.1 단계에서 생성한 Lambda 함수의 ARN을 입력합니다.
arn:aws:lambda:ap-northeast-1:000000000000:function:GameLiftClientService

  • Lambda 함수의 ARN 확인 방법

Lambda → 함수 선택 → 우측의 함수 ARN 확인

변경 사항 저장 버튼을 클릭하여 저장합니다.

3. 게임 클라이언트 수정

이번 섹션에서는 게임 클라이언트의 소스 코드와 Unity Scene을 수정하고 Amazon GameLift 서비스에 대한 요청을 게임 클라이언트가 아닌 클라이언트 서비스(Lambda 함수)에서 보내도록 변경합니다.

3.1. UnityPackage 파일 가져오기

먼저 추가 패키지 링크를 통해 필요한 패키지를 다운로드 합니다.

Unity를 열어 아래의 Project 뷰에서 아래와 같이 마우스를 우클릭한 후에
Import Package -> Custom Package... 를 클릭합니다.

위에서 다운로드 받은 패키지를 선택한 후에 Import 버튼을 클릭하여 패키지를 가져옵니다.

3.2. Cognito ID Pool의 ID 수정

클라이언트 인증 프로세스가 Cognito에서 수행되도록 변경합니다. Assets/Scripts/Lobby/ClientServiceAccessor.cs 파일을 열어 수정을 시작합니다.

25 행의 ID 입력 부분에 2.1 단계에서 생성한 자격 증명 풀의 ID를 입력합니다.

  • 자격 증명 풀 ID 확인하기

3.3. LobbyManager.cs 수정

ClientServiceAccessor 클래스를 사용하여 처리하기 위해 LobbyManager 클래스를 수정합니다.

Assets/Scripts/Lobby/LobbyManager.cs 파일을 열어 수정을 진행합니다.

  • LobbyManager 클래스의 OnEnable 함수 의 코드를 수정합니다.
    AmazonGameLiftClient m_GameLift;ClientServiceAccessor m_accessor;
  • LobbyManager 클래스에 정의된 Awake() 함수와 OnDisable() 함수를 삭제합니다.
  • LobbyManager 클래스에 정의되어있는 다음 함수를 모두 수정합니다.

OnEnable() 함수

void OnEnable()
{
m_accessor = m_accessor ?? gameObject.AddComponent<ClientServiceAccessor>();
}

CreateRoom() 함수

public async Task<PlayerSession> CreateRoom(string roomName = null)
{
if (string.IsNullOrEmpty(roomName)) roomName = Guid.NewGuid().ToString();
Debug.Log("CreateRoom using ClientService");
string gameSessionId = await m_accessor.CreateRoom(roomName);
return await JoinRoom(gameSessionId);
}

JoinRoom() 함수

public async Task<PlayerSession> JoinRoom(string gameSessionId)
{
Debug.Log("JoinRoom using ClientService");
var playerSession = await m_accessor.JoinRoom(gameSessionId);
NetworkManager.PlayerSession = playerSession;
SceneManager.LoadScene("Gameplay");
return playerSession;
}

SearchRoom() 함수

public async Task<List<GameSession>> SearchRooms()
{
Debug.Log("SearchRooms using ClientService");
return await m_accessor.SearchRooms();
}
  • LobbyManager 클래스 선언 전에 있는 아래의 소스를 삭제합니다.
    [RequireComponent(typeof(AwsConfig))]
  • LobbyManager 클래스의 시작 부분에 있는 아래 소스를 삭제합니다.
    AwsConfig m_Config;

변경 후 LobbyManager.cs 코드

namespace Lobby
{
using Amazon.GameLift;
using Amazon.GameLift.Model;
using Gameplay;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using System.Threading.Tasks;

public sealed class LobbyManager : MonoBehaviour
{
ClientServiceAccessor m_accessor;

void OnEnable()
{
m_accessor = m_accessor ?? gameObject.AddComponent<ClientServiceAccessor>();
}

public async Task<PlayerSession> CreateRoom(string roomName = null)
{
if (string.IsNullOrEmpty(roomName)) roomName = Guid.NewGuid().ToString();
Debug.Log("CreateRoom using ClientService");
string gameSessionId = await m_accessor.CreateRoom(roomName);
return await JoinRoom(gameSessionId);
}

public async Task<PlayerSession> JoinRoom(string gameSessionId)
{
Debug.Log("JoinRoom using ClientService");
var playerSession = await m_accessor.JoinRoom(gameSessionId);
NetworkManager.PlayerSession = playerSession;
SceneManager.LoadScene("Gameplay");
return playerSession;
}

public async Task<List<GameSession>> SearchRooms()
{
Debug.Log("SearchRooms using ClientService");
return await m_accessor.SearchRooms();
}

public void LocalPlay()
{
NetworkManager.PlayerSession = null;
SceneManager.LoadScene("Gameplay");
}
}
}

3.4. Unity Scene 수정

Unity의 Project 뷰에서 Assets → Scenes → Lobby를 클릭합니다.

Hierarchy 뷰에서 LobbyManager 게임 객체를 클릭합니다.

우측의 Inspector 뷰에 표시된 Aws Config (Script) 옆을 아래 이미지와 같이 우클릭하여 컨텍스트 메뉴의 Remove Component를 클릭합니다.

4. 동작 확인

File → Build And Run 을 클릭하여 게임을 실행시킵니다.

테스트를 위해 방을 생성합니다.

Unity Editor에서도 실행 버튼(▶︎)을 클릭하여 방에 입장합니다.

위에서 생성한 GameLiftClientService Lambda 함수의 CloudWatch 메트릭과 CloudWatch Logs Insights를 참조하여 Lambda 함수가 실행 중인지 확인합니다.

--

--