자료실

Photon Cloud와 WebHooks의 응용프로그램
작성자 | admin 2021-04-26  |    조회수 : 180  

Photon CloudWebHooks의 응용프로그램


이곳에서 소개하는 WebHooks 응용프로그램은 우리의 게임 클라이언트가 Photon Cloud의 클라우드 서버를 통해 제3자 서버 플랫폼 웹서비스와 연결해 상호 소통하는 것을 의미합니다. 주목적은 사용자가 게임에 재가입하도록 허용하고 사용자/게임 데이터를 기록하는 등 이와 같은 게임, 룸 기능 확대를 용이하게 하면서 데이터 보안도 한층 더 강화하는 데 있습니다.



클라이언트WebServicesPhoton Cloudwebhooks 시스템을 통해 데이트를 전송하는 과정

전반적인 운영 설정은 하단의 세 부분으로 나누어 볼 수 있습니다.


  1. WebService 설정 및 프로그램 코드
  2. Photon Cloud 설정
  3. PUN 클라이언트 설정 및 프로그램 코드

하단에서, 위 세 부분의 기본 설정으로 소개한 후, 작은 기능 하나를 게임에 적용해 보고 제3자 서비스 플랫폼과 연결해 미니 게임형 순위표(LeaderBoard) 데이터를 전송해보겠습니다!

이전 몇몇 파트에서 소개했던 WebHooks는 Photon Server Plugin 방식을 통해 구현한 것으로, 자가 서버 설정 데이터를 참고하고 싶다면 아래 링크를 참조해주세요.

Photon Server Plugin — WebHooks (1)

Photon Server Plugin — WebHooks (2)

WebScript.io(WebScrvice)

Photon Cloud WebHooks에 대한 이해를 간소화하기 위해 우리가 사용하는 제3자 네트워크 서비스를 WebScript.io라 부르겠습니다. 이는 Lua를 이용한 온라인 서비스 프로그램 스크립트입니다. 이를 통해 우리가 자체적으로 서브 도메인인 URL(subdomain)을 설정할 수 있어, 해당 온라인의 URL을 선택하기만 하면 바로 Lua 프로그램으로 구성된 자사 서비스를 사용할 수 있습니다. 또한, 구성 후 바로 실행 및 테스트가 가능해 자체적으로 서버를 설치할 필요가 없습니다. 프로그램 설치 없이도, 애플릿(미니 프로그램이나 기능)을 아주 편리하게 테스트해볼 수 있습니다!

webscript — scripting on the web Just choose a URL and type in a script. No servers, no deployment, no hassle.www.webscript.io

상단의 webscript.io와 연결해 임의 명칭 subdomain을 자체 정의하고 경로 내 GameCreate, GameEvent, GameClose, webhook123 등을 추가할 수 있습니다. 즉, 클라이언트에서 WebRPC로 method를 불러내거나 자체적으로 원하는 명칭으로 Http Post 서비스 URL을 받을 수 있습니다.

아래 내용은 photon1120을 이용해 subdomain을 설정해 webhook1 URL을 만든 예시로, 전체 URL 형태는 다음과 같습니다.
http://photon1120.webscript.io/webhook1



당사의 webhook 프로그램 코드 사이트(URL)

아래는 해당 URL에서 실행되고 있는 Lua Script입니다.

function insertscore(leaderboard, player, score)

        -- find index

        local index = #leaderboard+1

        for i,v in ipairs(leaderboard) do

               if v.score <= score then

                       index = i

                       break

               end

        end

        -- insert new score

        table.insert(leaderboard, index, {player=player,score=score})

        -- truncate list

        while #leaderboard > 10 do table.remove(leaderboard) end

end

 

-- ensure that only one process modifies the data at a time

lease.acquire('PhotonGameData')

 

local jsonRequest = json.parse(request.body)

local _name = jsonRequest.name

local _score = jsonRequest.score

 

local scores = json.parse(storage.PhotonGameData or '[]')

insertscore(scores, _name, tonumber(_score));

storage.PhotonGameData = json.stringify(scores)

 

lease.release('PhotonGameData')

              

-- return scores

return {

        ResultCode = 0,

        Message = "",

        Data = {

               leaderboard = storage.PhotonGameData,

               CustomMSG = "OK"

        }}
Lua Script 프로그램의 출처는 주로 Photon Server에서 전송해온 매개 변수(사용자 이름, 점수 등)로, 해당 값을 랭킹에 입력해 넣은 후, 다시 JSON 객체 형식으로 랭킹 10위 내 모든 값을 백패스합니다.
InsertScore는 주로 추가 사용자의 점수를 기존의 랭킹 데이터베이스에 설치합니다.

이렇게 우리의 WebService를 모두 준비했으니, 이어서 Photon Cloud를 설정해보겠습니다!

Photon Cloud 응용프로그램 설정

Photon Webhooks 운영 과정은 이벤트 구동형으로, 클라이언트에서 Photon Cloud로 GameCreate, GameEvent 또는 GameClose와 같은 이벤트를 발송하고, 또는 클라이언트 자체적으로 WebRPC를 호출하기도 합니다. Photon Server에서 이러한 이벤트를 수신하고 나면 이미 설정한 지정 사이트(URLs)로 HTTP POST 조건으로 전송합니다. Photon Server에서 제3자 서비스 응답값을 수신하고 나면 다시 클라이언트로 전송해 콜백 등과 관련된 후속 처리를 용이하게 해줍니다..

따라서, 우리는 우선 웹페이지를 오픈한 후 Photon Cloud의 Photon Realtim 계정에 연결하고 이곳에서 우리가 사용할 응용프로그램 앱을 만들어 설치하면 Manage를 클릭해 내부 관리 설정으로 진입할 수 있습니다.



Photon Cloud 응용프로그램 관리

해당 내부 관리 화면에서 Webhooks 설정 구역을 찾아 Create a new Webhook을 클릭합니다. 아래 화면을 참조하세요!



Webhook 추가 관리

Photon Cloud의 Webhook도 하나의 서버 플러그인 유형이기 때문에 여러 버전으로 구분되어 있습니다. Demo 버전은 PUN 내 샘플로 설치한 테스트 버전으로, 현재 저희에게는 필요하지 않기 때문에 Webhooks v1.2로 테스트해보겠습니다(최신 버전)!



Webhooks 버전 옵션

기본 설정

  1. BaseUrl(필수): 연결하고자 하는 서비스 사이트(URL) 및WebRPC 호출 시 사용하는 Method를 입력합니다. 관련된 클라이언트 쪽 프로그램 콜백(Callbacks)은 아래 경로 설명에서 관련 설정을 입력하게 됩니다.
  2. CustomHttpHeaders(선택 기입): 이곳에서 JSON 객체를 정의할 수 있고, 내부에는 주로 Key:Value 페이링값이 입력되며, Photon Server에서 내보내는 HTTP 헤더는 자체 정의한 JSON 객체를 함께 패킷화해 외부 서비스로 전송하게 됩니다.



기본 설정 & 경로 설정

경로 설정

아래 경로값마다 각각 관련된 제3자 사이트 경로를 입력하면 됩니다. 만약에 입력할 값이 없다면 관련 이벤트는 전달되지 않고 반환값도 존재하지 않아, 클라이언트에 이미 설정된 WebRPC가 있다 해도 콜백(Callbacks) 호출을 수신하지 않습니다.
  1. PathCreate
    룸을 새로 만들거나 룸 상태를 업데이트할 때 호출하게 되는 서비스입니다.
  2. PathClose
    룸이 Photon Server에서 삭제될 때 호출됩니다.
  3. PathJoin
    플레이어가 Photon Server 내 룸에 들어올 때 호출됩니다.
  4. PathLeave
    플레이어가 룸에서 벗어날 때 호출됩니다.
  5. PathEvent
    클라이언트가 룸에서 이벤트를 발송할 때 호출됩니다.
  6. PathGameProperties
    클라이언트에서 룸/플레이어 매개 변수 설정 시 호출됩니다.

이제 우리가 방금 webscript.io로 생성한 URL을 BaseUrl에 입력하면 됩니다. 지금은 다른 부분은 우선 건너뛰고, Save를 클릭해서 Photon Cloud 계정으로 되돌아가면 응용프로그램 Webhooks 관리 화면에서 아래와 같은 화면을 볼 수 있습니다.



Photon Cloud 계정 내 응용프로그램 Webhooks 관리 화면

이렇게 Photon Cloud에 설정해보았습니다. 어떻습니까? 간단하죠?
이어서 클라이언트 프로그램을 살펴보겠습니다!

WebRPC

Unity PUN / Photon Realtime에서 직접 WebRPC로 Photon Cloud상의 WebHooks 기능을 호출할 수 있습니다. 매개 변수 설정 내 method 명칭을 자체적으로 가져올 수 있어 호출할 서비스 경로를 지정하는 것과 같습니다.

클라이언트에서 PhotonNetwork.WebRpc를 실행할 때마다, Photon Cloud에서 수신한 후 method를 상응하는 경로로 전환해주고, Photon Cloud 계정 관리 설정에 미리 정의해둔 BaseURL에 맞춰 외부에 일회성 웹서버 Http POST 조건이 생성됩니다.

using System.Collections.Generic;

Dictionary parameters = new Dictionary();
parameters.Add ("name", "Steven Hu");
parameters.Add ("age", "28");

PhotonNetwork.WebRpc ("webhook1", parameters);

위와 같이, 우리는 string:object Dictionary 유형의 객체를 매개 변수로 삼아 Photon Cloud로 전달해 Photon Cloud에서 해당 자체 보유 데이터를 다시 HTTP 서버로 전달해 처리하게 할 수 있습니다.

클라이언트 코드 —  Unity PUN

앞장의 시리즈 문서와 같이 우리 Unity에는 두 개 화면이 있는데 하나는 마스터 서버 연결 전용 화면이고, 또 다른 하나는 스코어 보내기용 화면입니다. 첫 장면은 우리에게도 동일한 PUN 관리 PhotonManager가 있고, 게임 서버와의 연결 성공 후 제2장면이 로딩되니 우선 LeaderboardRoom.scene부터 호출하면 됩니다. 프로그램 코드 프로세스는 다음과 같습니다. 

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

 

public class PhotonManager : Photon.PunBehaviour {

              

        public static PhotonManager instance;

        // 로컬 사용자

        public static GameObject localPlayer;

        // 캐릭터 진입 지점

        GameObject defaultSpawnPoint;

 

        void Awake()

        {

               if (instance ! = null)

               {

                       DestroyImmediate(gameObject);

                       return;

               }

               DontDestroyOnLoad(gameObject);

               instance = this;

 

               //PUN의 맵 로딩 자동 동기화를 사용할 수 있고, 맵 로딩 초기화 시 발생할 수 있는 네트워크 문제를 피할 수 있습니다.

               PhotonNetwork.automaticallySyncScene = true;

        }

              

        void Start () {

               Connect();

//             InvokeRepeating("UpdateStatus", 2, 1);

        }

 

        void Connect() {

               //Photon Cloud/Server와의 연결 시작 시 게임 버전은 문자열 모드로 설정

                PhotonNetwork.ConnectUsingSettings("PUN_PhotonWebhook_1.2");

        }

 

        void UpdateStatus() {

               string status = PhotonNetwork.connectionStateDetailed.ToString();

               Debug.Log(status);

        }

              

        public void JoinGameRoom()

        {

               //게임룸과 명칭 설정 시 사용자 인원수 최대 2명

               RoomOptions options = new RoomOptions();

               options.MaxPlayers = 2;

               PhotonNetwork.JoinOrCreateRoom("RoomPlugins", options, TypedLobby.Default);

        }

 

        public override void OnConnectedToMaster ()

        {

               //마스터 서버에 연결 후, 버튼(UI)으로 기타 후속 동작을 표시하거나 실행할 수 있습니다.

               Debug.Log("Master Server에 접속했습니다");

        }

 

        public override void OnJoinedRoom()

        {

               Debug.Log("룸에 진입했습니다");

 

               //마스터 클라이언트일 경우, 즉시 구축 및 초기화하고 게임 화면 로딩 가능

               if (PhotonNetwork.isMasterClient)

               {

                    PhotonNetwork.LoadLevel("LeaderboardRoom");

               }

        }

 

        //게임 화면 로딩

        void OnLevelWasLoaded(int levelNumber)

        {

               if (!PhotonNetwork.inRoom) return;

 

               Debug.Log("게임 화면 로딩/게임룸 내");

 

        }

 

        public override void OnPhotonPlayerConnected(PhotonPlayer newPlayer)

        {

               Debug.Log("Other Player Entered." );

        }

})


LeaderboardRoom.scene에서 바로 간단하게 버튼을 통해 WebRPC를 송출하면 되기 때문에 DoSubmitScore 기록으로 사용자 이름과 점수를 획득하고 우리가 기록해 넣은 버튼(랭킹 작성)과 함께 사용합니다. 화면은 다음과 같습니다.



SubmitButton으로 Name&Score를 WebRPC 방식으로 송출 



using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using ExitGames.Client.Photon;

 

public class SubmitObject : Photon.PunBehaviour {

 

    public void DoSubmitScore() {

        Dictionary parameters = new Dictionary();

        parameters.Add ("name", "Steven Hu");

        parameters.Add ("score", "100");

 

        PhotonNetwork.WebRpc ("webhook1", parameters);

    }

 

    void OnWebRpcResponse(OperationResponse operationResponse) {

 

        if (operationResponse.ReturnCode ! = 0) {

            Debug.Log("WebRPC 동작실패. Response: " + operationResponse.ToStringFull());

            return;

        }

 

        WebRpcResponse webRpcResponse = new WebRpcResponse (operationResponse);

        if (webRpcResponse.ReturnCode ! = 0)

        {

            Debug.Log("WebRPC '" + webRpcResponse.Name + "문제발생. Error: " + webRpcResponse.ReturnCode + " Message: " + webRpcResponse.DebugMessage);

            return;

        }

 

        Dictionary parameters = webRpcResponse.Parameters;

 

        //랭킹, 정보 등 같은 매개 변수값 나열

        foreach (KeyValuePair pair in parameters) {

            Debug.Log(string.Format("KEY {0} / VALUE: {1}", pair.Key, pair.Value));

        }

    }

}

PhotonNetwork.WebRpc 호출 시, 첫 번째 매개 변수 webhook이 바로 저희가 설정한 webservice 경로이며, 두 번째 매개 변수는 JSON 객체 형식으로 내보낼 수 있습니다. 따라서 우리는 게임에서 획득한 이름과 점수를 두 번째 매개 변수로 송출하는 것이 좋습니다.

WebRPC 호출 후, Photon Cloud에서 일부 데이터 및 정보를 우리 클라이언트로 리턴해주고, PUN에서는 OnWebRpcResponse를 호출하기 시작합니다. 우리가 내부에서 ReturnCode가 0인지를 조회해 봤을 때, 0이 아니라면 문제가 있음을 의미합니다… 아마도 Photon Cloud 내부의 WebHook 경로를 정확하게 설정하지 못했거나, WebService 자체 경로 사이트 오류일 수도 있습니다. 따라서 문제가 발생한 경우엔 이러한 절차 처리 시 조심스럽게 취급해야 합니다!

ReturnCode가 0이라면 좋습니다! 그다음 우리는 다른 데이터 반환 문제를 처리할 수 있습니다. 랭킹, 사용자 이름, 기타 자체 지정 정보 등 모두 JSON 객체로 반환됩니다!

전반적인 운용

webscript.io에 기록한 랭킹 루프백은 아래 데이터처럼 Photon Cloud로 반환하게 됩니다.



반환된 webscript.io 데이터

만약 모든 연산과 설정이 제대로 적용되었다면 PUN 내 LeaderboardRoom.scene에서 아래와 같은 송출된 로그를 볼 수 있습니다. 여러 번 입력하고 나면, 서버에서 반환해온 데이터 중 랭킹 10위 내 정보를 확인할 수 있습니다. 이는 바로 우리의 조작이 성공했음을 의미합니다!



클라이언트의 점수 송출 후, 랭킹 10위 내 사용자 이름과 점수를 포함한 데이터 반환을 수신하게 됩니다.

요약

해당 예시에서 랭킹 데이터 액세스 기능을 적용한 것은 Photon CloudWebhooks의 조작법과 운용 방식을 쉽게 이해하기 위함입니다. 일단 해당 절차를 이해하고 나면, Photon Cloud를 이용한 데이터 전송 시스템을 실행해서 신속하게 제3자 외부 데이터베이스, 클라우드 컴퓨팅, WebService를 통해 소통하고 교류할 수 있고 더 안정적이고 효율적인 구성을 설계할 수 있습니다.

현재 제3자 Google Cloud Platform, AWS, Microsoft Azure 등과 같은 강력한 서버 플랫폼이 존재합니다. 이러한 대형 플랫폼을 통해 신속하게 대량의 데이터를 처리한 후 다시 반환해 표시한다면, 게임 구조 설계를 한층 더 확장할 수 있고 기계 처리 비용을 절약할 수 있습니다. 그리고 무엇보다도 클라이언트 쪽의 사용자가 우리의 처리 방법을 알 필요도 없기 때문에 데이터를 신속하고 안전하게 처리할 수 있습니다!

그렇다면 여러분은 이에 대해 어떤 생각을 가지고 있나요? 어떤 의문이든 언제든지 https://www.facebook.com/photoncloudkr/ 이나 developer@photonengine.kr로 문의 주세요!


출처 : Hu씨의 Photon 블로그 이야기 (대만)