# Game Overrides와 CCD의 연동

> Use Remote Config and badges to integrate Game Overrides with Cloud Content Delivery so you can target content to specific audiences.

[Game Overrides](/game-overrides.md)를 사용하면 특정 잠재 고객에게 콘텐츠를 타게팅할 수 있습니다. 예를 들어 A/B 테스트를 실행하고 지리적 위치와 특정 기간에 맞게 콘텐츠를 커스터마이즈할 수 있습니다. 배지는 의도한 콘텐츠를 식별하고, Remote Config는 라이브 플레이어에게 영향을 주지 않으면서 해당 콘텐츠를 테스트하고, 동시에 특정 플레이어에게 배지가 있는 콘텐츠를 배포합니다.

Game Overrides를 연동하려면 다음 단계를 완료합니다.

1. [Remote Config 패키지 설치](#install-the-remote-config-package)
2. [프로젝트 ID 연결](#link-your-project-id)
3. CCD 배지를 사용하여 콘텐츠를 타게팅하는 [오버라이드를 생성](#create-an-override)합니다.
4. [게임 코드에 Remote Config 연동](#integrate-remote-config-into-your-game-code)
5. [CCD에서 적절한 에셋 검색](#retrieve-the-appropriate-assets-from-ccd)

## Remote Config 패키지 설치##install-the-remote-config-package

패키지 설치에 대한 자세한 내용은 [패키지 관리자](https://docs.unity3d.com/Manual/Packages.html)를 참고하십시오.

> **Note:**
>
> 이 단계는 사용 중인 Unity 에디터의 버전에 따라 다를 수 있습니다.

1. Unity 에디터에서 **Window** > **Package Manager**를 선택합니다.
2. 패키지 목록 뷰에서 **Remote Config**를 선택합니다.
3. 패키지 세부사항 뷰에서 Remote Config를 프로젝트로 임포트하는 데 필요한 버전을 선택하고 설치합니다.

## 프로젝트 ID 연결##link-your-project-id

아직 연결하지 않았다면 Unity 프로젝트를 프로젝트 ID에 연결해야 합니다.

Unity 에디터에서 프로젝트를 연결하면 다음을 수행합니다.

1. Services 창(**Window** > **General** > **Services**)을 엽니다.
2. **General settings**를 선택합니다.
3. Project settings 메뉴의 Services 섹션에 있는 드롭다운에서 현재 조직을 선택합니다. 관련 조직 목록을 보려면 Unity Hub에 로그인해야 합니다.
4. **Use an existing Unity project ID**를 선택하여 이전에 개발자 대시보드에서 생성한 ID에 프로젝트를 연결하거나, **Create project ID**를 선택하여 프로젝트를 새 ID에 연결합니다.


**Frame:**
![](/api/media?file=/ccd/media/images/ccd-campaigns-link-1.png)

## 오버라이드 생성##create-an-override

Game Overrides 서비스 또는 Cloud Content Delivery 서비스를 통해 [Unity Dashboard](https://dashboard.unity3d.com/)에서 오버라이드를 생성할 수 있습니다. [오버라이드 생성](/game-overrides/get-started.md)을 참고하십시오.

1. 내비게이션에서 **LiveOps**를 선택하여 Game Overrides 서비스로 이동한 다음 두 번째 내비게이션에서 **Game Overrides** > **Overrides**를 선택합니다.\
   또는 Cloud Content Delivery 서비스 자체 버킷의 Targeting 탭에서 **Create Override**를 선택하여 Overview 페이지로 이동할 수도 있습니다.

2. **오버라이드 생성**을 선택합니다.

3. 오버라이드 이름을 지정하고 **Next**를 선택합니다.

4. [JEXL 조건](https://docs.unity3d.com/Packages/com.unity.remote-config@latest/index.html?subfolder=/manual/CampaignsAndSettings.html%23condition)을 지정하여 타게팅할 플레이어를 선택한 다음 타게팅할 플레이어의 비율을 지정합니다. **Next**를 선택합니다.

5. **+ Choose content type**을 선택한 다음 **Cloud Content Delivery** > **Badge**를 선택합니다. **Done**을 선택합니다.

   > **Note:**
   >
   > CCD 배지를 타게팅하는 대신 일반 Remote Config 구성을 사용하여 오버라이드를 생성하려면 **Config Overrides**를 선택합니다. [Remote Config](https://docs.unity3d.com/Packages/com.unity.remote-config@latest/index.html?subfolder=/manual/GameOverridesAndSettings.html)를 참고하십시오.

6. **Choose a bucket**을 선택한 다음 사용하려는 버킷을 선택합니다.

7. **Choose your badge**를 선택한 다음 사용하려는 배지를 선택합니다. **Choose**를 선택한 다음 **Next**를 선택합니다.

8. 오버라이드를 실행할 **Start** 및 **End Date**를 선택합니다. **Finish**를 선택합니다.

9. 오버라이드를 활성화하려면 **Enable**을 선택합니다.

## 게임 코드에 Remote Config 연동##integrate-remote-config-into-your-game-code

`RemoteConfig` API는 `Unity.Services` 네임스페이스에 포함되어 있으며 이는 게임 스크립트에도 포함되어야 합니다. 클래스와 메서드에 대한 자세한 내용은 [Remote Config 스크립팅 API](https://docs.unity3d.com/Packages/com.unity.remote-config@latest/index.html?subfolder=/api/index.html) 기술 자료를 참고하십시오.

Remote Config 서비스에는 액세스 가능한 [`RemoteConfigService`](https://docs.unity3d.com/Packages/com.unity.remote-config-runtime@latest/index.html?subfolder=/api/Unity.Services.RemoteConfig.RemoteConfigService.html) 인스턴스가 있어, 런타임 시 구성을 가져오고 적용하는 작업을 처리할 수 있습니다. 이 예제에서는 이 값을 사용하여 오버라이드에서 정의한 CCD 구성의 키-값 페어를 가져옵니다. 이 페어의 키는 정적 문자열 `CCD_CONFIG_KEY`입니다. 그런 다음 검색이 성공하면 `ApplyCcdConfig` 함수를 호출합니다. `ApplyCcdConfig`는 가져오기 요청에 대한 응답을 나타내는 [`ConfigResponse`](https://docs.unity3d.com/Packages/com.unity.remote-config-runtime@latest/index.html?subfolder=/api/Unity.RemoteConfig.ConfigResponse.html) 구조체를 사용합니다.

*C#*

```cs
public struct userAttributes {}
public struct appAttributes {}
 
async Task InitializeRemoteConfigAsync()
{
  // initialize handlers for unity game services
  await UnityServices.InitializeAsync();
 
  // remote config requires authentication for managing environment information
  if (!AuthenticationService.Instance.IsSignedIn)
  {
    await AuthenticationService.Instance.SignInAnonymouslyAsync();
  }
}
 
async void Start()
{
    if (Utilities.CheckForInternetConnection())
    {
        await InitializeRemoteConfigAsync();
    }
 
    RemoteConfigService.Instance.appConfig = RemoteConfigService.Instance.GetConfig("ccd");
    RemoteConfigService.Instance.FetchCompleted += ApplyCcdConfig;
    RemoteConfigService.Instance.FetchConfigs("ccd", new userAttributes(), new appAttributes());
}
 
void ApplyCcdConfig(ConfigResponse configResponse)
{
    switch (configResponse.requestOrigin)
    {
        case ConfigOrigin.Default:
            Debug.Log("Default values will be returned");
            break;
        case ConfigOrigin.Cached:
            Debug.Log("Cached values loaded");
            break;
        case ConfigOrigin.Remote:
            Debug.Log("Remote Values changed");
 
            if (RemoteConfigService.Instance.appConfig.HasKey("CCD_CONFIG_KEY"))
            {
                // get the correct key-value pair for CCD (the key will always be "CCD_CONFIG_KEY")
                string jsonValue = RemoteConfigService.Instance.appConfig.GetJson("CCD_CONFIG_KEY");
                // you will use jsonValue in the next step
            }
 
            break;
    }
}
```

## CCD에서 적절한 에셋 검색##retrieve-the-appropriate-assets-from-ccd

CCD 구성을 가져온 후에는 버킷 정보와 배지 이름을 추출하여 CCD에서 적절한 에셋을 검색할 수 있습니다.

`CcdConfig` 클래스를 정의하는 것부터 시작합니다.

*C#*

```cs
public class CcdConfig
{
   public string bucketId;
   public string bucketName;
   public string badgeName;
}
```

그런 다음 `ApplyCcdConfig` 함수에서는 가져온 CCD 구성에서 이러한 값을 추출하고 이를 사용하여 CCD에서 적절한 에셋을 검색할 수 있습니다.

*C#*

```cs
// extract the config values that you have defined when creating your Override
CcdConfig ccdConfig = JsonUtility.FromJson<CcdConfig>(jsonValue);
 
// the bucketId and badgeName are required to fetch the appropriate assets
var bucketId = ccdConfig.bucketId;
var badgeName = ccdConfig.badgeName;
 
// fetch the entry from CCD
// Note that for a dynamic file path, a config override can be used in order to fetch
// the correct file path for your asset
JObject entry = CcdManager.Instance.GetEntry(bucketId, badgeName, "ENTRY_PATH");
// fetch the entry's content from CCD
var content = CcdManager.Instance.GetContent(bucketId, entry["entryid"].ToString());
 
// use your asset(s) as needed
// YOUR CODE HERE
```

`CCDManager` 클래스는 CCD의 [클라이언트 API](https://services.docs.unity.com/content-delivery-client)를 사용하여 에셋을 가져옵니다. 각 씬의 게임 오브젝트에 `CCDManager`를 연결해야 합니다.

> **Note:**
>
> 에셋이 큰 경우 비동기식으로 가져오는 것을 고려하십시오.

`CCDManager` 클래스는 다음 코드 샘플과 유사할 수 있습니다.

*C#*

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using Unity.RemoteConfig;
 
using System.Net;
using System;
using System.IO;
 
public class CcdManager : MonoBehaviour
{
 
   private static string projectId = "YOUR_PROJECT_ID_HERE";
   private static string ccdBaseUrl = $"https://{projectId}.client-api.unity3dusercontent.com/client_api/v1/";
 
   private static CcdManager m_Instance;
   public static CcdManager Instance { get { return m_Instance; } }
 
   private void Awake()
   {
     if (m_Instance != null && m_Instance != this)
       {
           Destroy(this.gameObject);
           return;
       }
 
       m_Instance = this;
       DontDestroyOnLoad(this.gameObject);
   }
 
   public JObject GetEntry(string bucketId, string badgename, string entrypath) {
     var entryUrl = $"{ccdBaseUrl}/buckets/{bucketId}/release_by_badge/{badgename}/entry_by_path/?path={entrypath}";
 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(entryUrl);
     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
     StreamReader reader = new StreamReader(response.GetResponseStream());
     string jsonResponse = reader.ReadToEnd();
     JObject ccdEntry =  JObject.Parse(jsonResponse);
 
     return ccdEntry;
   }
 
   public string GetContent(string bucketId, string entryid) {
     var contentUrl = $"{ccdBaseUrl}/buckets/{bucketId}/entries/{entryid}/content/";
 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format(contentUrl));
     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
     StreamReader reader = new StreamReader(response.GetResponseStream());
     string contentValue = reader.ReadToEnd();
 
     return contentValue;
   }
}
```

이제 오버라이드로 정의된 에셋을 검색했습니다.
