# 푸시 메시지 전송

> Push messages to clients over a WebSocket connection from Cloud Code modules.

Cloud Code C# 모듈에서는 WebSocket을 통해 메시지를 클라이언트에 푸시할 수 있습니다. 이 페이지는 이 기능의 개요와 더불어 Cloud Code 모듈과 Cloud Code SDK에서 이 기능을 사용하는 방법에 관한 지침을 제공합니다.

> **Note:**
>
> **참고**: 푸시 메시지와 [푸시 알림](/push-notifications.md)은 게임에서 다른 목적으로 사용됩니다. 푸시 메시지는 게임플레이에 적극적으로 참여하는 플레이어를 타게팅하며, 푸시 알림은 게임이 비활성 상태이거나 백그라운드에서 가동되고 있을 때 디바이스에 전송됩니다.

푸시 메시지를 보내려면 모듈 엔드포인트를 호출해야 합니다. Unity 에디터에서 푸시 메시지를 구독할 수 있습니다.

## 사용 사례 및 이점##use-cases-and-benefits

다음과 같이 다양한 목적으로 푸시 메시지를 사용할 수 있습니다.

| 사용                                                                          | 예시                                                                                                                    | 이점           |
| :-------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- | :----------- |
| 실시간으로 메시지를 서버에서 클라이언트로 푸시하여 게임의 상호 작용을 향상합니다.                               | 플레이어에게 게임 이벤트, 업데이트 또는 비동기식 멀티플레이어 게임(예: 경쟁 카드 게임)에 대해 알릴 수 있습니다.                                                     | 실시간 상호 작용    |
| 업데이트와 알림을 클라이언트에 바로 푸시하여 사용자에게 최신 이벤트, 변경 사항 또는 게임 내 액션과 관련된 소식을 계속 알려 줍니다. | 데이터가 사용 가능해지면 바로 사용자에게 알릴 수 있어 수동으로 새로 고치거나 업데이트를 확인하지 않아도 됩니다. 실시간 전략 게임 같이 빈번한 업데이트가 필요한 게임에서 특히 유용합니다.             | 사용자 경험       |
| 기존 폴링 기법보다 효율성을 높이기 위해 WebSocket을 사용하여 메시지를 푸시합니다.                          | 클라이언트는 새 데이터가 있는지 서버에 계속해서 묻는 대신, 데이터가 사용 가능해졌을 때 서버에서 새 데이터를 전송할 때까지 기다리면 됩니다. 이렇게 되면 불필요한 네트워크 트래픽이 감소하여 지연이 줄어듭니다. | 효율적인 네트워크 사용 |
| 푸시 모델의 확장성을 사용하여 많은 사용자가 참여하는 게임을 지원합니다.                                    | Cloud Code에서 푸시 메시지를 사용하여 연결된 모든 클라이언트에 한 번에 업데이트를 보내 수많은 플레이어가 참여하는 멀티플레이어 게임에서 운영 비용과 요청의 양을 줄일 수 있습니다.             | 확장성과 비용      |
| 이벤트 기반 모델을 사용하여 다양한 유형의 메시지에 대한 게임의 응답을 커스터마이즈합니다.                          | 수신하는 메시지의 MessageType 프로퍼티에 따라 다양한 게임 액션을 트리거할 수 있습니다.                                                                | 커스터마이즈 기능    |
| Unity 생태계의 일부로서 Cloud Code를 다른 Unity 서비스와 함께 원활하게 사용합니다.                    | Unity Authentication 서비스를 사용하여 플레이어 인증을 처리하고 Unity 게임 엔진 내에서 메시지를 처리할 수 있습니다.                                         | 원활한 연동       |

## 모듈 생성##create-a-module

다음 코드 예시는 두 메서드가 포함된 모듈의 기본 구조를 보여 줍니다.

* `SendPlayerMessage`: 연결된 특정 플레이어에게 메시지를 보냅니다.
* `SendProjectMessage`: 프로젝트에서 연결된 모든 플레이어에게 메시지를 브로드캐스트합니다.

> **Warning:**
>
> **중요**: `SendProjectMessage` 메서드는 프로젝트에서 연결된 모든 플레이어에게 메시지를 전송합니다. 이렇게 하면 플레이어에게 메시지를 스팸으로 보내는 등의 남용이 발생할 여지가 있습니다. [액세스 제어](./access-control.md) 정책을 만들어 엔드포인트에 대한 플레이어 액세스를 제한하여 이를 방지할 수 있습니다.

> **Note:**
>
> **참고**: [Triggers](/triggers.md)를 사용하여 전체 프로젝트에 메시지를 브로드캐스트할 수 있습니다. [사용 사례 샘플: 플레이어에게 새해 인사 전하기](/triggers/tutorials/use-cases/happy-new-year.md)를 참고하십시오.

`Unity.Services.CloudCode.Apis` 패키지는 푸시 메시지를 보내는 데 사용되는 인터페이스인 `PushClient` 인스턴스를 제공합니다.

```csharp
using Microsoft.Extensions.DependencyInjection;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Apis;

namespace PushExample
{
    public class PushExample
    {
        [CloudCodeFunction("SendPlayerMessage")]
        public async Task<string> SendPlayerMessage(IExecutionContext context, PushClient pushClient, string message, string messageType, string playerId)
        {
            var response = await pushClient.SendPlayerMessageAsync(context, message, messageType, playerId);
            return "Player message sent";
        }

        // Recommended to use access control to limit access to this endpoint
        [CloudCodeFunction("SendProjectMessage")]
        public async Task<string> SendProjectMessage(IExecutionContext context, PushClient pushClient, string message, string messageType)
        {
            var response = await pushClient.SendProjectMessageAsync(context, message, messageType);
            return "Project message sent";
        }
    }

    public class ModuleConfig : ICloudCodeSetup
    {
        public void Setup(ICloudCodeConfig config)
        {
            config.Dependencies.AddSingleton(PushClient.Create());
        }
    }
}
```

모듈을 배포하는 방법을 알아보려면 [Hello World 배포](../getting-started) 페이지를 참고하십시오.

## Unity 에디터 설정##set-up-the-unity-editor

Cloud Code SDK는 메시지를 구독할 수 있는 인터페이스를 제공합니다. 특정 플레이어 또는 전체 플레이어를 위해 메시지를 구독할 수 있습니다.

Unity 에디터에서 Cloud Code를 사용하려면 먼저 Cloud Code SDK를 설치하고 [Unity Gaming Services 프로젝트](/cloud/projects.md)를 Unity 에디터에 연결해야 합니다.

### 프로젝트 연결##link-project

[Unity Gaming Services 프로젝트](/cloud/projects.md)를 Unity 에디터와 연결합니다. Unity Dashboard에서 UGS 프로젝트 ID를 확인할 수 있습니다.

1. Unity 에디터에서 **Edit** > **Project Settings** > **Services**를 선택합니다.

2. 프로젝트를 연결합니다.
   프로젝트에 Unity 프로젝트 ID가 없는 경우 다음 단계를 진행합니다.

   1. **Create a Unity Project ID** > **Organizations**를 선택한 다음 드롭다운에서 조직을 선택합니다.
   2. **Create project ID**를 선택합니다.

   Unity 프로젝트 ID가 있는 경우 다음 단계를 진행합니다.

   1. **Use an existing Unity project ID**를 선택합니다.
   2. 드롭다운에서 조직과 프로젝트를 선택합니다.
   3. **Link project ID**를 선택합니다.

이렇게 하면 Unity 프로젝트 ID가 표시되고 프로젝트가 Unity 서비스에 연결됩니다. `UnityEditor.CloudProjectSettings.projectId` 파라미터를 사용하여 Unity 에디터 스크립트에서 프로젝트 ID에 액세스할 수도 있습니다.

### SDK 설치##sdk-installation

다음과 같이 Unity 에디터용 최신 Cloud Code 패키지를 설치합니다.

1. Unity 에디터에서 **Window** > **Package Manager**를 엽니다.
2. Package Manager에서 **Unity Registry** 목록 뷰를 선택합니다.
3. `com.unity.services.cloudcode`를 검색하거나 목록에서 Cloud Code 패키지를 찾습니다.
4. 패키지를 선택하고 **Install**을 클릭합니다.

> **Note:**
>
> **참고**: Cloud Code SDK 버전 2.4.0 이상에서 메시지를 구독할 수 있습니다.

> **Note:**
>
> **참고**: Unity 패키지 관리자 인터페이스를 익히려면 [Package Manager 창](https://docs.unity3d.com/Manual/upm-ui.html) 기술 자료를 참고하십시오.

### SDK 설정##sdk-setup

다음과 같이 Cloud Code SDK를 시작합니다.

1. Cloud Code 서비스 대시보드 페이지를 통해 서비스를 활성화합니다.
2. Cloud Code와 Authentication SDK를 모두 설치합니다.
3. **Edit** > **Project Settings** > **Services**를 선택하여 Unity 에디터 내에서 클라우드 프로젝트에 로그인합니다.
4. Unity 에디터에서 새 C# Monobehaviour 스크립트를 생성합니다. Unity 매뉴얼의 [스크립트 생성 및 사용](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html)을 참고하십시오.
5. 스크립트에서 await `UnityServices.InitializeAsync()`를 사용하여 Core SDK를 초기화합니다.
6. 스크립트에서 Authentication SDK를 초기화합니다.

> **Note:**
>
> **참고**: Cloud Code 서비스에 액세스하려면 플레이어에게 유효한 플레이어 ID와 액세스 토큰이 있어야 합니다. Cloud Code API를 사용하려면 먼저 Authentication SDK로 플레이어를 인증해야 합니다. 다음 코드 스니핏을 사용하여 익명으로 인증하거나 [Authentication](/authentication.md) 기술 자료에서 자세한 내용과 기타 로그인 방법을 확인할 수 있습니다.

```cs
await AuthenticationService.Instance.SignInAnonymouslyAsync();
```

## 메시지 구독##subscribe-to-messages

특정 플레이어 또는 전체 플레이어를 위해 메시지를 구독할 수 있습니다. 다음 코드 스니핏을 Unity 프로젝트의 `MonoBehaviour` 스크립트에 대한 가이드로 사용할 수 있습니다.

이 스크립트는 익명 플레이어로 인증하며 플레이어별, 프로젝트별 메시지 모두를 구독하고 다양한 유형의 이벤트를 처리합니다.

```csharp
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Unity.Services.Authentication;
using Unity.Services.CloudCode;
using Unity.Services.CloudCode.Subscriptions;
using Unity.Services.Core;
using UnityEngine;
namespace CloudCode
{
	public class CloudCodePushExample : MonoBehaviour
	{
    	async void Start()
        {
            await UnityServices.InitializeAsync();
            await AuthenticationService.Instance.SignInAnonymouslyAsync();
            Debug.Log(AuthenticationService.Instance.PlayerId);
            await SubscribeToPlayerMessages();
            await SubscribeToProjectMessages();
        }
        // This method creates a subscription to player messages and logs out the messages received,
        // the state changes of the connection, when the player is kicked and when an error occurs.
        Task SubscribeToPlayerMessages()
        {
            // Register callbacks, which are triggered when a player message is received
            var callbacks = new SubscriptionEventCallbacks();
            callbacks.MessageReceived += @event =>
            {
                Debug.Log(DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"));
                Debug.Log($"Got player subscription Message: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.ConnectionStateChanged += @event =>
            {
                Debug.Log($"Got player subscription ConnectionStateChanged: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.Kicked += () =>
            {
                Debug.Log($"Got player subscription Kicked");
            };
            callbacks.Error += @event =>
            {
                Debug.Log($"Got player subscription Error: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            return CloudCodeService.Instance.SubscribeToPlayerMessagesAsync(callbacks);
        }
        // This method creates a subscription to project messages and logs out the messages received,
        // the state changes of the connection, when the player is kicked and when an error occurs.
        Task SubscribeToProjectMessages()
        {
            var callbacks = new SubscriptionEventCallbacks();
            callbacks.MessageReceived += @event =>
            {
                Debug.Log(DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"));
                Debug.Log($"Got project subscription Message: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.ConnectionStateChanged += @event =>
            {
                Debug.Log($"Got project subscription ConnectionStateChanged: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.Kicked += () =>
            {
                Debug.Log($"Got project subscription Kicked");
            };
            callbacks.Error += @event =>
            {
                Debug.Log($"Got project subscription Error: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            return CloudCodeService.Instance.SubscribeToProjectMessagesAsync(callbacks);
        }
	}
}
```

## 플레이어에게 메시지 전송##send-messages-to-players

플레이어에게 메시지를 보내려면 모듈에서 `SendPlayerMessage` 또는 `SendProjectMessage` 함수를 호출합니다.

모듈을 실행하는 방법을 알아보려면 [모듈 실행](./run-modules.md)을 참고하십시오.

### Unity Runtime에서 실행##run-from-unity-runtime

`CloudCodeService` 인스턴스의 `CallModuleEndpointAsync` 메서드를 통해 다른 플레이어에게 메시지를 보낼 수 있습니다. 모듈 이름과 함수 이름을 처음 두 개의 인자로, 필수 파라미터가 있는 딕셔너리를 세 번째 인자로 사용해야 합니다.

예를 들어 플레이어에게 메시지를 보내려면 다음을 호출하면 됩니다.

```csharp
var sendPlayerMessageResult = await CloudCodeService.Instance.CallModuleEndpointAsync<string>("PushExample", "SendPlayerMessage",
	new Dictionary<string, object> {{"message", "hello with a player message from PushExample!"}, {"messageType", "testType"}, {"playerId", "<other-unity-player-ID>"}});
```

> **Note:**
>
> **참고**: [액세스 제어](./access-control.md) 정책을 만들어 플레이어가 게임의 모든 다른 플레이어에게 프로젝트 메시지를 전송하는 `SendProjectMessage` 모듈 함수의 호출을 거부할 수 있습니다.

## 이벤트##events

플레이어와 프로젝트별 구독 모두에 다음과 같은 4개의 이벤트 핸들러가 있습니다.

* `MessageReceived`: 플레이어가 새 메시지를 수신하면 트리거됩니다.
* `ConnectionStateChanged`: 연결 상태가 변경되면 트리거됩니다.
* `Kicked`: 서버가 메시지로부터 플레이어를 강제로 구독 취소하면 트리거됩니다. 이때 WebSocket 연결이 종료되지는 않으며, 게임 클라이언트가 메시지를 다시 구독하지 못하도록 차단하지도 않습니다.
* `Error`: 연결 처리에서 오류가 발생하거나 플레이어가 메시지를 수신하면 트리거됩니다.

## 메시지 엔벨로프##message-envelope

`IMessageReceivedEvent`는 플레이어가 푸시 서비스로부터 수신하는 메시지를 나타내는 인터페이스입니다. Cloud Code가 WebSocket 연결을 통해 메시지를 보내면 이벤트가 트리거됩니다.

`IMessageReceivedEvent` 인터페이스의 페이로드는 아래 표를 참고하십시오.

| 프로퍼티            | 설명                                                                                                               | 예시                                         |
| --------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `SpecVersion`   | 수신한 메시지 엔벨로프의 규격 버전입니다. 이 프로퍼티를 사용하면 클라이언트가 메시지를 올바르게 처리할 수 있습니다.                                                | 1.0                                        |
| `Id`            | 메시지에 대한 고유 ID입니다. 이 프로퍼티를 사용하여 메시지를 트래킹하거나 기록합니다.                                                                | `4f88f657-27da-4b1d-a013-9033dbc7b48b`     |
| `Source`        | 메시지 엔벨로프의 소스입니다. 메시지의 출처를 나타내며 메시지를 디버깅하거나 라우팅하는 데 사용할 수 있습니다. 소스는 항상 Cloud Code의 도메인입니다.                        | `https://cloud-code.service.api.unity.com` |
| `Type`          | 메시지의 엔벨로프 유형입니다. 이 프로퍼티는 메시지에 포함된 데이터 유형을 나타내며, 이 프로퍼티를 통해 클라이언트가 처리 방식을 결정할 수 있습니다. 값은 항상 Cloud Code 메시지 유형입니다. | `com.unity.services.cloud-code.push.v1`    |
| `Time`          | 메시지 생성 날짜 및 시간입니다. 이 프로퍼티를 사용하여 메시지를 기록하거나 지연을 계산할 수 있습니다.                                                       | `2023-09-19T10:26:40.436878688Z`           |
| `ProjectId`     | 메시지가 연결된 프로젝트의 ID입니다.                                                                                            | `b6670776-9fd3-4d66-8bf4-63fb1112dc95`     |
| `EnvironmentId` | 메시지의 대상인 환경의 ID입니다. 이 프로퍼티를 사용하여 데브, 스테이징, 프로덕션 같이 서로 다른 개발 환경을 구별할 수 있습니다.                                      | `a4bc2571-d1e7-4507-9cc9-80b687d48d8f`     |
| `CorrelationId` | 관련된 메시지의 배열을 트래킹하는 데 사용할 수 있는 ID입니다. 예를 들어 여러 메시지가 대화 또는 워크플로를 구성하는 경우 상관 관계 ID를 공유할 수 있습니다.                     | `afbd7c6e-e999-4ca2-86fc-3c908ba83bf2`     |
| `Message`       | Cloud Code에서 플레이어로 전송되는 실제 메시지 내용입니다.                                                                            | ‘hello world!’                             |
| `MessageType`   | 플레이어가 수신하는 메시지의 유형입니다. `Type`과 유사하지만 엔벨로프가 아닌 메시지 내용과 관련됩니다.                                                     | ‘정보’                                       |
