기본 환경 설정
Unreal Engine C++에서 PlayNANOO REST API를 사용하기 위한 기본 환경설정 방법을 안내합니다.
1. 사전 준비사항
PlayNANOO 콘솔에서 다음 정보를 미리 발급받아야 합니다.
API 인증 정보 발급
PlayNANOO 콘솔에 접속하여 다음 정보를 확인하세요.
발급 경로: 콘솔 > 채널 > 설정 > API & 플랫폼 관리
발급받아야 할 정보:
- Game ID: 채널 고유 식별자
- Service Key: API 요청 시 사용되는 서비스 키
- Secret Key: 보안 서명 생성에 사용되는 비밀 키
보안 주의사항
Secret Key는 절대로 노출되어서는 안되며, 환경변수나 별도 설정파일로 관리하세요.
2. Unreal Engine C++ 구현
Unreal Engine에서 PlayNANOO API를 호출하기 위한 구현 방법입니다.
2.1 모듈 의존성 추가
먼저 프로젝트의 Build.cs 파일에 HTTP 관련 모듈을 추가합니다.
// YourProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"Http", // HTTP 요청
"Json", // JSON 파싱
"JsonUtilities" // JSON 유틸리티
});
2.2 기기 정보 구조체 (FDeviceInfo)
모든 API 요청에는 클라이언트 기기 정보가 포함되어야 합니다. 다음 구조체를 사용하여 기기 정보를 자동으로 수집합니다.
// DeviceInfo.h
#pragma once
#include "CoreMinimal.h"
#include "Json.h"
#include "GenericPlatform/GenericPlatformMisc.h"
#include "Internationalization/Internationalization.h"
struct FDeviceInfo
{
FString UUID;
FString Nickname;
FString DeviceId;
FString Version;
FString Platform;
FString DeviceModel;
FString DeviceOS;
FString DeviceLanguage;
FString DeviceCountry;
FString DeviceTimeOffset;
FDeviceInfo()
{
// 게임에서 관리하는 플레이어 정보 (로그인 후 설정)
UUID = UGameDataManager::Get()->GetUUID();
Nickname = UGameDataManager::Get()->GetNickname();
// 기기 정보 자동 수집
DeviceId = FPlatformMisc::GetDeviceId();
Version = UGameDataManager::Get()->GetVersionNumber();
Platform = GetPlatformName();
DeviceModel = FPlatformMisc::GetDefaultDeviceProfileName();
DeviceOS = FPlatformMisc::GetOSVersion();
DeviceLanguage = GetDeviceLanguage();
DeviceCountry = GetCountryCode();
DeviceTimeOffset = FString::FromInt(GetTimeOffset());
}
// JSON 객체에 기기 정보 추가
void AddToJson(TSharedPtr<FJsonObject>& JsonObject) const
{
JsonObject->SetStringField(TEXT("uuid"), UUID);
JsonObject->SetStringField(TEXT("nickname"), Nickname);
JsonObject->SetStringField(TEXT("device_id"), DeviceId);
JsonObject->SetStringField(TEXT("version"), Version);
JsonObject->SetStringField(TEXT("platform"), Platform);
JsonObject->SetStringField(TEXT("device_model"), DeviceModel);
JsonObject->SetStringField(TEXT("device_os"), DeviceOS);
JsonObject->SetStringField(TEXT("device_language"), DeviceLanguage);
JsonObject->SetStringField(TEXT("device_country"), DeviceCountry);
JsonObject->SetStringField(TEXT("device_timeoffset"), DeviceTimeOffset);
}
private:
FString GetPlatformName() const
{
#if PLATFORM_WINDOWS
return TEXT("Windows");
#elif PLATFORM_MAC
return TEXT("Mac");
#elif PLATFORM_IOS
return TEXT("iOS");
#elif PLATFORM_ANDROID
return TEXT("Android");
#elif PLATFORM_LINUX
return TEXT("Linux");
#else
return TEXT("Unknown");
#endif
}
FString GetDeviceLanguage() const
{
FString Culture = FInternationalization::Get().GetCurrentCulture()->GetTwoLetterISOLanguageName();
return Culture.ToUpper();
}
FString GetCountryCode() const
{
FString Culture = FInternationalization::Get().GetCurrentCulture()->GetRegion();
if (Culture.IsEmpty())
{
FString Language = GetDeviceLanguage();
if (Language == TEXT("KO")) return TEXT("KR");
if (Language == TEXT("JA")) return TEXT("JP");
if (Language == TEXT("ZH")) return TEXT("CN");
if (Language == TEXT("DE")) return TEXT("DE");
if (Language == TEXT("FR")) return TEXT("FR");
if (Language == TEXT("ES")) return TEXT("ES");
return TEXT("US");
}
return Culture.ToUpper();
}
int32 GetTimeOffset() const
{
FDateTime Now = FDateTime::Now();
FDateTime UtcNow = FDateTime::UtcNow();
FTimespan Offset = Now - UtcNow;
return FMath::RoundToInt(Offset.GetTotalSeconds());
}
};
데이터 관리
UGameDataManager는 게임에서 직접 구현해야 하는 싱글톤 클래스입니다. UUID, Nickname, AccessToken 등 플레이어 정보를 관리합니다.
2.3 요청 바디 생성 헬퍼 함수
모든 API 요청에 기기 정보를 자동으로 포함시키는 헬퍼 함수입니다.
// PlayNANOOHelper.h
#pragma once
#include "CoreMinimal.h"
#include "Json.h"
#include "Http.h"
#include "DeviceInfo.h"
#include "PlayNANOOAuth.h"
class FPlayNANOOHelper
{
public:
static TSharedPtr<FJsonObject> CreateRequestBody()
{
TSharedPtr<FJsonObject> Body = MakeShareable(new FJsonObject());
FDeviceInfo DeviceInfo;
DeviceInfo.AddToJson(Body);
return Body;
}
static FString ToJsonString(const TSharedPtr<FJsonObject>& JsonObject)
{
FString JsonBody;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonBody);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
return JsonBody;
}
static void SetCommonHeaders(TSharedRef<IHttpRequest>& Request, bool bRequireToken = true)
{
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
Request->SetHeader(TEXT("Accept"), TEXT("application/json"));
Request->SetHeader(TEXT("X-Playnanoo-Key"), FPlayNANOOAuth::ServiceKey);
Request->SetHeader(TEXT("X-Playnanoo-Id"), FPlayNANOOAuth::GameId);
if (bRequireToken)
{
FString AccessToken = UGameDataManager::Get()->GetAccessToken();
Request->SetHeader(TEXT("Authorization"), FString::Printf(TEXT("Bearer %s"), *AccessToken));
}
}
};
2.4 API 요청 예제
void UMyGame::SaveStorage(const FString& Key, const FString& Value)
{
TSharedPtr<FJsonObject> Body = FPlayNANOOHelper::CreateRequestBody();
Body->SetStringField(TEXT("key"), Key);
Body->SetStringField(TEXT("value"), Value);
FString JsonBody = FPlayNANOOHelper::ToJsonString(Body);
TSharedRef<IHttpRequest> Request = FHttpModule::Get().CreateRequest();
Request->SetURL(TEXT("https://service-api.playnanoo.com/storage/v20220701/set"));
Request->SetVerb(TEXT("PUT"));
FPlayNANOOHelper::SetCommonHeaders(Request, true);
Request->SetContentAsString(JsonBody);
Request->OnProcessRequestComplete().BindLambda(
[](FHttpRequestPtr Req, FHttpResponsePtr Res, bool bSuccess)
{
if (bSuccess && Res.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("저장 성공: %s"), *Res->GetContentAsString());
}
});
Request->ProcessRequest();
}