본문으로 건너뛰기

Unreal Engine 멤버십 튜토리얼

이 문서는 UnrealStarter 샘플 프로젝트를 기준으로, Windows PC 환경에서 Google 로그인을 이용해 Hybe Game Platform Service(이하 플랫폼)의 멤버십(인증) 기능을 연동하는 방법을 단계별로 안내합니다.

튜토리얼을 마치면 다음을 할 수 있습니다.

  • 플랫폼 SDK를 게임에 초기화(Mount) 한다.
  • Google 계정으로 플랫폼 로그인을 수행한다.
  • 신규 회원 가입 시 웹뷰 흐름을 확인한다.
  • 로그인 결과로 imid, loginToken 을 확보한다.
  • 필요 시 토큰을 갱신하고 로그아웃한다.

:::info 이 문서와 멤버십 가이드의 차이 멤버십 가이드는 API 레퍼런스와 플랫폼별(Steam, Epic, Android, iOS) 상세 설정을 다루는 참고 문서입니다. 이 튜토리얼은 처음 연동할 때 손으로 따라 하는 실습 문서이며, Windows + Google 로그인에 집중합니다.

튜토리얼에서 Mount, Login, OnLoginSuccessAPI 이름은 멤버십 가이드 API Reference로 연결되어 있습니다. 상세 시그니처·파라미터·에러 코드는 링크된 가이드 항목을 참고하세요. :::

경고

이 튜토리얼에서 다루지 않는 것

사전 요구사항

항목내용
OSWindows 10 이상
Unreal Engine5.4 이상 (5.4.4, 5.5.4에서 테스트됨)
IDEVisual Studio 2022 권장
샘플 프로젝트UnrealStarter (UnrealStarter_x.x.x.zip)
네트워크QA(또는 dev) 플랫폼 환경 접근 가능

플랫폼 SDK는 언리얼 플러그인 HybePlatform 형태로 배포됩니다. UnrealStarter는 이 플러그인을 사용하는 샘플 앱이며, 압축 해제 시 Plugins/HybePlatform/에 플러그인이 포함되어 있습니다. 자체 게임 프로젝트에 연동할 때는 동일한 방식으로 플러그인을 적용합니다.


Step 0. UnrealStarter 준비

0-1. 샘플 프로젝트 열기

  1. UnrealStarter_x.x.x.zip 파일을 압축 해제합니다.
  2. UnrealStarter.uproject 파일을 우클릭하여 Visual Studio 솔루션을 생성합니다.
  3. Visual Studio에서 솔루션을 열고 Development Editor 구성으로 빌드합니다.
정보

언리얼 5.5로 열기 UnrealStarter 샘플은 언리얼 5.4 기준으로 작성되어 있습니다. 언리얼 5.5 에디터에서 열려면 UnrealStarter.uproject 우클릭 → Switch Unreal Engine version...5.5 선택 후 프로젝트를 엽니다. 엔진 버전 전환 시 플러그인·모듈 재빌드가 필요할 수 있습니다. 자세한 내용은 멤버십 가이드 - UnrealStarter 샘플 프로젝트를 참고하세요.

0-2. 플랫폼 SDK 플러그인 적용

플랫폼 SDK는 네이티브 라이브러리와 C++ 래퍼를 HybePlatform 언리얼 플러그인으로 패키징해 배포합니다. UnrealStarter는 이 플러그인을 탑재한 샘플 앱이며, HybePlatformAgent 등 멤버십 API는 플러그인 모듈을 통해 제공됩니다.

튜토리얼 후반의 Mount(), Login() 호출이 동작하려면, 그 이전에 플러그인이 프로젝트에 적용·빌드되어 있어야 합니다.

디렉터리 구조

UnrealStarter/
├── Plugins/
│ └── HybePlatform/ ← 플랫폼 SDK 언리얼 플러그인 (배포본)
│ ├── HybePlatform.uplugin
│ └── Source/
│ ├── HybePlatform/ ← 플러그인 모듈 (HybePlatform.Build.cs)
│ └── ThirdParty/
│ └── PlatformSDK/ ← 네이티브 SDK (include, lib)
└── Source/
└── UnrealStarter/
└── UnrealStarter.Build.cs ← 게임 모듈이 HybePlatform에 의존

UnrealStarter zip에는 위 구조가 이미 포함되어 있습니다. 자체 프로젝트에 연동할 때는 배포된 HybePlatform 폴더를 게임 프로젝트의 Plugins/ 하위에 복사합니다. (멤버십 가이드 - SDK 설치 참고)

1단계 — 플러그인 배치

  1. 배포 패키지의 HybePlatform 폴더를 <프로젝트>/Plugins/HybePlatform/에 둡니다.
  2. HybePlatform.uplugin이 존재하는지 확인합니다. 이 파일이 언리얼에 런타임 모듈 HybePlatform 을 등록합니다.
Plugins/HybePlatform/HybePlatform.uplugin (발췌)
{
"Modules": [
{
"Name": "HybePlatform",
"Type": "Runtime",
"LoadingPhase": "PostConfigInit"
}
]
}

2단계 — 게임 모듈 Build.cs에서 플러그인 의존

게임(샘플) C++ 코드에서 HybePlatformAgent, HybePlatformAuthAgent 등을 사용하려면, 게임 모듈의 Build.csHybePlatform 모듈 의존을 선언해야 합니다. 이것이 “플러그인을 프로젝트에 적용”하는 핵심 단계입니다.

UnrealStarter/UnrealStarter.Build.cs (발췌)
PublicDependencyModuleNames.AddRange(new string[] {
"Core",
"CoreUObject",
"Engine",
// ...
});

PrivateDependencyModuleNames.AddRange(new string[] {
"WebBrowser",
"HybePlatform", // ← 플랫폼 SDK 플러그인 모듈
"OnlineSubsystem"
});
Build.cs역할
HybePlatform.Build.cs (플러그인)PlatformSDK 네이티브 라이브러리(.lib, .a) 링크, include 경로 등록, 플랫폼별(Windows/Android/iOS) 빌드 설정
UnrealStarter.Build.cs (게임/샘플)게임 모듈이 HybePlatform의존하도록 선언 → HybePlatformAgent.h 등 SDK 헤더·심볼 사용 가능

플러그인만 Plugins/에 복사하고 Build.csHybePlatform을 추가하지 않으면, 게임 코드에서 SDK 클래스를 include·호출할 수 없습니다.

3단계 — 플러그인 모듈 Build.cs (참고)

HybePlatform.Build.cs는 플러그인 내부에서 네이티브 SDK를 빌드에 연결합니다. Windows 예시는 다음과 같습니다.

Plugins/HybePlatform/Source/HybePlatform/HybePlatform.Build.cs (발췌)
if (Target.Platform == UnrealTargetPlatform.Win64)
{
PublicAdditionalLibraries.Add(
"$(PluginDir)/Source/ThirdParty/PlatformSDK/lib/x64/platform-sdk.lib");
}

PublicIncludePaths.Add("$(PluginDir)/Source/ThirdParty/PlatformSDK/include");

게임 프로젝트 연동 시 직접 수정할 파일은 주로 게임 모듈의 Build.cs 입니다. HybePlatform.Build.cs는 배포된 플러그인에 포함되어 있으며, 플랫폼별 네이티브 링크를 담당합니다.

4단계 — uproject 모듈 의존 (UnrealStarter)

UnrealStarter는 UnrealStarter.uproject에도 HybePlatform 모듈 의존을 명시합니다.

UnrealStarter.uproject (발췌)
{
"Modules": [
{
"Name": "UnrealStarter",
"AdditionalDependencies": [
"HybePlatform",
"WebBrowserWidget"
]
}
]
}
정보

UnrealStarter를 그대로 따라 하는 경우 zip에 플러그인과 Build.cs 설정이 이미 적용되어 있으므로, Visual Studio 솔루션 재생성 후 빌드만 하면 됩니다. 자체 게임 프로젝트에 이식할 때는 플러그인 복사 + 게임 Build.csHybePlatform 추가를 확인하세요.

플러그인 적용 후 Edit → Plugins에서 HybePlatform이 로드되는지 확인하고, 0-3. WebBrowser 플러그인 활성화를 진행합니다.

0-3. WebBrowser 플러그인 활성화

Google 로그인 및 회원 가입 과정에서 웹뷰가 필요합니다. 언리얼 에디터에서 다음을 확인하세요.

  1. Edit → Plugins 메뉴를 엽니다.
  2. WebBrowser 플러그인을 검색합니다.
  3. 체크박스가 활성화(Enabled) 되어 있는지 확인합니다.
  4. 변경 시 에디터 재시작이 필요할 수 있습니다.

플랫폼 SDK는 웹뷰 UI를 직접 제공하지 않습니다. 게임 클라이언트가 WebBrowser 플러그인을 이용해 웹뷰를 구현해야 하며, UnrealStarter는 LoginWebBrowser 클래스로 이를 처리합니다.

0-4. DefaultEngine.ini 설정

Config/DefaultEngine.ini 파일에 Custom URI Scheme이 등록되어 있어야 합니다. Google 등 Third Party Login 결과가 이 스킴을 통해 앱으로 돌아옵니다.

Config/DefaultEngine.ini
[HybeGamePlatform]
SteamAppId=0
CustomScheme=drimageplatform
Key설명
SteamAppId스팀 연동 시 AppId. Google 로그인 실습에서는 0으로 두면 됩니다.
CustomScheme외부 인증 결과를 앱에 전달할 URI 스킴. 프로젝트별로 고유 값을 사용합니다.
정보

Steam, Epic, Firebase 등 추가 설정은 멤버십 가이드의 DefaultEngine.ini 설정을 참고하세요. 이번 튜토리얼에서는 위 두 항목만 필요합니다.

0-5. 접속 환경 설정 (drimage_config.json)

샘플은 Content/UnrealStarter/Data/DrimagePlatform/drimage_config.json 파일에서 플랫폼 접속 환경을 읽습니다.

Content/UnrealStarter/Data/DrimagePlatform/drimage_config.json
{
"QA-1202": {
"BuildEnv": "qa",
"SteamAppID": 4337590,
"SteamIdentity": "platform-qa-12020020",
"ProjectId": "1202",
"BillingAuth": "test-auth-key",
"ServiceId": "12020020",
"WebClientId": "134676729186-dfbh87213kflsoqq17koq9fa1er1oviu.apps.googleusercontent.com"
}
}
필드설명
BuildEnv접속 환경 (dev, qa, prod 등)
ProjectId플랫폼에 등록된 프로젝트 ID
WebClientIdGoogle OAuth 클라이언트 ID. 현재 환경에 등록된 값이어야 합니다.
ServiceId(샘플앱 전용) 가상 게임 서버·빌링 데모용. 플랫폼 SDK Plugin은 사용하지 않음
BillingAuth(샘플앱 전용) 가상 게임 서버 HTTP 헤더용. 플랫폼 SDK Plugin은 사용하지 않음
SteamAppID / SteamIdentity스팀 연동용. Google 실습에서는 Mount JSON에 포함되지만 로그인에는 사용하지 않습니다.
경고

WebClientId 확인 Google 로그인이 실패하거나 "Login cancel"이 발생하면, WebClientId가 현재 BuildEnv에 맞게 등록되어 있는지 확인하세요. 게임별로 다른 값이 할당될 수 있습니다.

0-6. SDK 초기화 — Apply부터 Mount까지의 API 호출

Splash·Start 화면은 샘플 앱 전용 UI이며, 플랫폼 SDK API는 호출되지 않습니다. 멤버십 연동이 시작되는 시점은 Init 화면에서 Apply 버튼을 눌러 MountSDK()가 실행될 때입니다.

Init 화면의 UI 선택은 곧바로 API 인자로 전달되지는 않습니다. 사용자가 고른 값이 CachedConfig, CachedLanguage 등의 변수에 저장되고, Apply 시점에 JSON으로 조립된 뒤 Mount()에 전달됩니다.

Init UI 선택 → API 인자 매핑

Init UI 선택샘플 코드 위치API에 반영되는 방식
환경 버튼 (예: QA-1202)OnConfig_ButtonClickedCachedConfigMount(configJson) JSON의 BuildEnv, ProjectId, WebClientId
언어 버튼 (예: Korean)OnLanguage_ButtonClickedCachedLanguage ("ko")SetClientLanguage(CachedLanguage)
결제 플랫폼 PGOnPG_ButtonClickedCachedPaymentType빌링 API용 — 멤버십 튜토리얼에서는 무시

환경 버튼을 누르면 drimage_config.json에서 읽어 둔 FServiceConfig 항목이 CachedConfig에 복사됩니다.

UnrealStarter/UI/Page/InitPage.cpp - OnConfig_ButtonClicked
void UInitPage::OnConfig_ButtonClicked(int32 InIndex)
{
CachedConfig = Configs[InIndex]; // BuildEnv, ProjectId, WebClientId 등이 여기에 저장됨
bIsConfigSelected = true;
}

언어 버튼을 누르면 ISO 639-1 코드로 변환되어 CachedLanguage에 저장됩니다.

UnrealStarter/UI/Page/InitPage.cpp - OnLanguage_ButtonClicked
void UInitPage::OnLanguage_ButtonClicked(int32 InIndex)
{
CachedLanguage = GetLanguageCode(static_cast<EUSLanguageType>(InIndex));
// Korean → "ko", English → "en", Japanese → "ja", Chinese → "zh-tw"
bIsLanguageSelected = true;
}

Apply 클릭 시 API 호출 순서

Apply 버튼은 OnApply_ButtonClicked()MountSDK()를 호출합니다. MountSDK() 안에서 반드시 아래 순서로 API를 호출해야 합니다. Agent 등록과 저장 경로·언어 설정은 Mount() 이전에 완료되어야 합니다.

API별 상세 설명

1. SetPlatformAuthAgent
HybePlatformAgent::Instance().SetPlatformAuthAgent(new USPlatformAuthAgent());
항목내용
호출 이유SDK가 로그인·로그아웃·Mount 완료 등 인증 이벤트를 게임 코드로 전달할 수신자를 등록합니다.
인자HybePlatformAuthAgent* — 게임이 구현한 Auth Agent 인스턴스
호출 시점Mount() 이전. 등록하지 않으면 OnMount, OnLoginSuccess 등 콜백을 받을 수 없습니다.
이후 콜백Mount() 완료 시 OnMount, 로그인 시 OnLoginSuccess / OnLoginFailure (멤버십 가이드)
2. SetPlatformWebviewAgent
HybePlatformAgent::Instance().SetPlatformWebviewAgent(new USPlatformWebviewAgent());
항목내용
호출 이유회원 가입·약관 동의 등 웹뷰가 필요한 로그인 단계에서 SDK가 URL을 게임에 전달할 수신자를 등록합니다.
인자HybePlatformWebviewAgent* — 게임이 구현한 Webview Agent 인스턴스
호출 시점Mount() 이전
이후 콜백가입 필요 시 OnShowWebview, 완료 시 OnCloseWebview (멤버십 가이드)

Google 기존 회원 로그인만 하는 경우 웹뷰 콜백이 호출되지 않을 수 있지만, Agent 등록은 신규 가입 대비 반드시 필요합니다.

3. SetWritableStorageDirectory
HybePlatformAgent::Instance().SetWritableStorageDirectory(FPaths::ProjectSavedDir());
항목내용
호출 이유자동 로그인 토큰 등 SDK가 로컬에 저장하는 데이터의 쓰기 가능한 경로를 지정합니다.
인자FString dir — 앱이 쓰기 권한을 가진 디렉터리. 샘플은 FPaths::ProjectSavedDir() (프로젝트 Saved/ 폴더)
호출 시점Mount() 이전
관련 API이후 DoAutoLogin이 이 경로에 저장된 자동 로그인 정보를 읽습니다.
4. SetClientLanguage
HybePlatformAgent::Instance().SetClientLanguage(CachedLanguage); // 예: "ko"
항목내용
호출 이유SDK 내부 및 웹뷰(가입·약관 페이지) 에 표시할 언어를 설정합니다.
인자FString language — ISO 639-1 코드 (ko, en, ja, zh-tw)
호출 시점Mount() 이전 (Init UI에서 선택한 언어 버튼 → GetLanguageCode() 변환값)
5. Mount
HybePlatformAgent::Instance().Mount(JsonString);
항목내용
호출 이유플랫폼 SDK 플러그인을 초기화하고, 지정한 환경의 백엔드와 통신 준비를 마칩니다. 멤버십 API를 사용하기 위한 필수 진입점입니다.
인자FString configJson — 접속 환경 설정 JSON 문자열 (Platform Configuration 참고)
호출 시점Agent 등록·저장 경로·언어 설정 이후
결과 전달등록한 Auth Agent의 OnMount 콜백 (OnMount). true = 성공, false = 실패

샘플에서 CachedConfig로부터 조립하는 JSON 예시입니다.

UnrealStarter/UI/Page/InitPage.cpp - MountSDK() 내 JSON 조립
TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
JsonObject->SetStringField(TEXT("BuildEnv"), CachedConfig.BuildEnv);
JsonObject->SetNumberField(TEXT("SteamAppID"), CachedConfig.SteamAppID);
JsonObject->SetStringField(TEXT("SteamIdentity"), CachedConfig.SteamIdentity);
JsonObject->SetStringField(TEXT("ProjectId"), CachedConfig.ProjectId);
JsonObject->SetStringField(TEXT("WebClientId"), CachedConfig.WebClientId);
// 아래 두 필드는 샘플앱(ClientContext·가상 게임 서버) 전용 — SDK Plugin은 읽지 않음
JsonObject->SetStringField(TEXT("BillingAuth"), CachedConfig.BillingAuth);
JsonObject->SetStringField(TEXT("ServiceId"), CachedConfig.ServiceId);
// → FString JsonString으로 직렬화 후 Mount(JsonString)에 전달

Mount(configJson) 주요 필드 (Google 로그인 실습 기준):

JSON KeySDK Plugin 사용설명
BuildEnv사용접속할 플랫폼 백엔드 환경 (dev, qa, prod)
ProjectId사용플랫폼에 등록된 프로젝트 ID. 기술 PM에게 전달받은 값
WebClientId사용Google 로그인에 필수. 현재 BuildEnv에 등록된 OAuth 클라이언트여야 함
SteamAppID사용 (스팀 연동 시)Google 실습에서는 0 또는 샘플 값 포함. 스팀 미사용 시 무시
SteamIdentity사용 (스팀 연동 시)Google 실습에서는 미사용
ServiceId미사용UnrealStarter 샘플앱 전용ClientContext·가상 게임 서버 데모용
BillingAuth미사용UnrealStarter 샘플앱 전용 — 가상 게임 서버 HTTP 인증 헤더용
경고

WebClientId가 잘못되면 Google 로그인 단계에서 실패합니다. Init UI에서 고른 환경(QA-1202 등)에 맞는 WebClientIddrimage_config.json에 설정되어 있는지 확인하세요.

OnMount 콜백

Mount()가 완료되면 SDK는 등록된 Auth Agent에 결과를 알립니다.

void USPlatformAuthAgent::OnMount(bool mounted)
mounted의미게임에서 할 일
trueSDK 초기화 성공DoAutoLogin으로 자동 로그인 시도 여부 확인
falseSDK 초기화 실패ProjectId, WebClientId, SetWritableStorageDirectory 경로,
DefaultEngine.ini 점검

Output Log에서 Platform Mounted : 1이 출력되면 mounted = true입니다.

DoAutoLogin

OnMount(true) 직후 샘플은 저장된 자동 로그인 정보가 있는지 확인합니다.

HybePlatformAgent::Instance().DoAutoLogin([this](bool bAutoLogin)
{
if (bAutoLogin)
{
// 저장된 자동 로그인 정보 있음 → SDK가 로그인 시도
// 결과: OnLoginSuccess / OnLoginFailure
}
else
{
// 저장 정보 없음 → Login 화면에서 수동 로그인 대기
HybePlatformAgent::Instance().ForceSignout();
}
});
항목내용
호출 이유이전 실행에서 "자동 로그인" 옵션으로 로그인한 기록이 있으면, Login 화면을 거치지 않고 바로 로그인을 시도합니다.
인자std::function<void(bool)> callbacktrue: 자동 로그인 시도함, false: 저장된 정보 없음
호출 시점OnMount(true) 이후
관련 API자동 로그인 정보 저장은 Login 호출 시 bEnableAutologin = true로 설정할 때 이루어집니다.

첫 실행이거나 자동 로그인 기록이 없으면 bAutoLogin = false이고, 이후 Login 화면에서 Login("GOOGLE", ...)을 호출하게 됩니다. 샘플은 MountSDK() 마지막에 Login 페이지로 전환합니다.

UnrealStarter/UI/Page/InitPage.cpp - MountSDK() 마지막
UIPageManagerSubsystem->PushPage(EUIPageType::Login, true);
정보

결제 플랫폼 버튼에 대하여 Init 화면의 PG 버튼은 샘플 UI에서 Apply 활성화 조건을 충족하기 위한 선택입니다. MountSDK() 내부의 SetPlatformBillingAgent(), HybeBillingPlatform::SetAvailablePayment()빌링 API이며 Google 멤버십 로그인과는 무관합니다. Unreal Engine 빌링에서 다룹니다.

이 단계 완료 기준


Step 1. 샘플 앱 흐름 이해

멤버십 연동에 관련된 화면과 소스 파일의 대응 관계는 아래와 같습니다.

구분샘플 파일역할
Auth AgentUnrealStarter/Agent/USPlatformAuthAgent.*로그인·로그아웃·Mount 등 인증 이벤트 수신
Webview AgentUnrealStarter/Agent/USPlatformWebviewAgent.*회원가입·약관동의 웹뷰 Show/Close 처리
커스텀 웹뷰UnrealStarter/Public/LoginWebBrowser.*WebBrowser 플러그인 기반 웹뷰 구현
초기화UnrealStarter/UI/Page/InitPage.cppAgent 등록 및 Mount() 호출
로그인 UIUnrealStarter/UI/Page/LoginPage.cpp로그인 수단별 Login() 호출
계정 관리UnrealStarter/UI/Page/AccountPage.cppSignout·RefreshVerifyToken

SDK 아키텍처 요약

게임 클라이언트는 플랫폼 SDK가 발생시키는 이벤트를 수신할 Agent를 구현해야 합니다.

Agent역할
HybePlatformAuthAgent인증(로그인·로그아웃·탈퇴·초기화) 이벤트 수신
HybePlatformWebviewAgent회원가입·약관동의·본인인증 등 웹뷰 이벤트 수신

SDK의 진입점은 HybePlatformAgent 싱글톤입니다. 멤버십 관련 모든 API는 이 클래스를 통해 호출합니다.

클래스 관계도와 로그인 시퀀스 다이어그램은 멤버십 가이드 - 연동 개요로그인 Flow를 참고하세요.


Step 2. Auth Agent 구현

플랫폼 로그인 과정에서 발생하는 이벤트를 수신하기 위해 HybePlatformAuthAgent를 상속한 USPlatformAuthAgent 클래스를 구현합니다.

2-1. 클래스 선언

UnrealStarter/Agent/USPlatformAuthAgent.h
class UNREALSTARTER_API USPlatformAuthAgent : public HybePlatformAuthAgent
{
public:
virtual void OnMount(bool mounted) override;
virtual void OnLoginSuccess(const FString& resultJson) override;
virtual void OnLoginFailure(const FString& resultJson) override;
virtual void OnLogoutSuccess() override;
virtual void OnLogoutFailure(const FString& message) override;
virtual void OnWithDraw() override;
virtual void OnRefreshVerifyToken(const FString& token) override;
// ...
};

멤버십 튜토리얼에서 반드시 이해해야 할 콜백은 다음 네 가지입니다.

콜백호출 시점게임에서 할 일
OnMountMount() 완료 후초기화 성공 여부 확인, 자동 로그인 시도
OnLoginSuccess로그인 성공imid·loginToken 파싱, 게임 화면 전환
OnLoginFailure로그인 실패에러 코드 확인, 사용자에게 안내
OnLogoutSuccess로그아웃 성공로그인 화면으로 복귀

2-2. OnMount — 초기화 완료 및 자동 로그인

Mount()가 성공하면 SDK가 OnMount(true)를 호출합니다. 샘플에서는 이 시점에 자동 로그인을 시도합니다.

UnrealStarter/Agent/USPlatformAuthAgent.cpp
void USPlatformAuthAgent::OnMount(bool mounted)
{
if (mounted)
{
HybePlatformAgent::Instance().DoAutoLogin([this](bool bAutoLogin)
{
if (bAutoLogin)
{
// 저장된 자동 로그인 정보가 있음 — SDK가 로그인을 시도합니다.
// 결과는 OnLoginSuccess / OnLoginFailure로 전달됩니다.
}
else
{
// 저장된 자동 로그인 정보 없음 — Login 화면에서 수동 로그인
HybePlatformAgent::Instance().ForceSignout();
}
});
}
}

동작 설명:

  • DoAutoLogin은 이전에 "자동 로그인" 옵션으로 로그인한 적이 있으면 bAutoLogin = true를 반환하고, SDK가 백그라운드에서 로그인을 시도합니다.
  • bAutoLogin = false이면 Login 화면에서 사용자가 직접 로그인 수단을 선택해야 합니다.
  • mounted = false이면 초기화 실패입니다. ProjectId, WebClientId, 저장 경로 등 Platform Configuration을 확인하세요.

2-3. OnLoginSuccess — 로그인 성공 처리

로그인이 성공하면 SDK가 JSON 문자열을 전달합니다. 이 JSON에서 imid, loginToken, countryCode 등을 추출합니다. (OnLoginSuccess JSON 참고)

UnrealStarter/Agent/USPlatformAuthAgent.cpp
void USPlatformAuthAgent::OnLoginSuccess(const FString& resultJson)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(resultJson);
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
auto imid = JsonObject->GetStringField(TEXT("imid"));
GetClientContext().SetImid(imid);
GetClientContext().ApplyLoginInfo(resultJson);
}

// 게임 스레드에서 Lobby 화면으로 전환
AsyncTask(ENamedThreads::GameThread, [this]()
{
// UIPageManagerSubsystem->PushPage(EUIPageType::Lobby, true);
});
}

주의 사항:

  • SDK 콜백은 게임 스레드가 아닐 수 있으므로, UI 전환은 AsyncTask(ENamedThreads::GameThread, ...) 안에서 수행합니다.
  • OnLoginSuccess 직후 RefreshVerifyToken()을 호출하지 마세요. 방금 발급된 loginToken은 일정 시간 유효하며, 즉시 갱신하면 FAIL_LOCK_REQUEST 오류가 발생할 수 있습니다. (멤버십 가이드 - 게임 서버 로그인 참고)

2-4. OnLoginFailure — 로그인 실패 처리

UnrealStarter/Agent/USPlatformAuthAgent.cpp
void USPlatformAuthAgent::OnLoginFailure(const FString& resultJson)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(resultJson);
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
auto code = JsonObject->GetIntegerField(TEXT("code"));
// code에 따라 사용자에게 적절한 메시지 표시
}
}

Google 로그인 실습에서 자주 보는 상황은 사용자가 브라우저 인증 창을 닫은 경우입니다. 이 경우 실패 JSON이 전달되며, 게임에서는 알림 팝업 등으로 안내하면 됩니다.

2-5. OnLogoutSuccess — 로그아웃 후 처리

UnrealStarter/Agent/USPlatformAuthAgent.cpp
void USPlatformAuthAgent::OnLogoutSuccess()
{
GetClientContext().SetImid(TEXT(""));

AsyncTask(ENamedThreads::GameThread, []()
{
// Login 화면으로 복귀
// UIPageManagerSubsystem->PushPage(EUIPageType::Login, true);
});
}

Step 3. Webview Agent 및 커스텀 웹뷰 구현

회원 가입, 서비스 이용 약관 동의, 본인 확인 등은 웹 페이지를 통해 진행됩니다. 플랫폼 SDK는 웹뷰 UI를 제공하지 않으며, 게임 클라이언트가 URL을 받아 직접 웹뷰를 띄워야 합니다.

경고

플랫폼 SDK는 웹뷰를 직접 제공하지 않습니다 OnShowWebview(url) 이벤트를 수신하면, 게임이 보유한 WebBrowser 기반 UI로 해당 URL을 로드해야 합니다. UnrealStarter는 ULoginWebBrowserUGlobalWidgetManager로 이를 처리합니다.

3-1. Webview Agent 구현

HybePlatformWebviewAgent를 상속하여 Show/Close 이벤트를 처리합니다.

UnrealStarter/Agent/USPlatformWebviewAgent.h
class UNREALSTARTER_API USPlatformWebviewAgent : public HybePlatformWebviewAgent
{
public:
virtual void OnCloseWebview() override;
virtual void OnShowWebview(const FString& url) override;
};
UnrealStarter/Agent/USPlatformWebviewAgent.cpp
void USPlatformWebviewAgent::OnShowWebview(const FString& url)
{
AsyncTask(ENamedThreads::GameThread, [url]()
{
UGlobalWidgetManager::GetInstance()->ShowWebview(url);
});
}

void USPlatformWebviewAgent::OnCloseWebview()
{
AsyncTask(ENamedThreads::GameThread, []()
{
UGlobalWidgetManager::GetInstance()->CloseWebview();
});
}

왜 GameThread에서 실행하나요?

웹뷰는 UMG 위젯이므로 반드시 게임 스레드에서 생성·표시해야 합니다. SDK 콜백이 다른 스레드에서 올 수 있기 때문에 AsyncTask(ENamedThreads::GameThread, ...)로 감쌉니다.

3-2. 커스텀 웹뷰 (LoginWebBrowser)

언리얼 WebBrowser 플러그인을 상속한 ULoginWebBrowser가 실제 웹 페이지를 렌더링합니다.

UnrealStarter/Public/LoginWebBrowser.h
UCLASS()
class UNREALSTARTER_API ULoginWebBrowser : public UWebBrowser
{
GENERATED_BODY()

public:
UFUNCTION(BlueprintCallable)
void PostMessage(FString jsonResponse);

void PrepareJsBridge();
void OnHandleOnUrlChanged(const FText& InText);
void ShowWebview(const FString& url);
void CloseWebview();
};

JavaScript Bridge

웹 페이지의 JavaScript와 언리얼 C++ 사이를 연결하는 브릿지입니다. 웹 페이지에서 webbridge라는 이름으로 언리얼 함수를 호출할 수 있게 바인딩합니다.

모든 플랫폼에서 아래와 같이 BindUObject 세 번째 인자를 true 로 설정합니다. URL이 변경되어도 JavaScript Bridge 바인딩이 유지됩니다.

UnrealStarter/Private/LoginWebBrowser.cpp
void ULoginWebBrowser::PrepareJsBridge()
{
FString linkName = TEXT("webbridge");
WebBrowserWidget->BindUObject(linkName, this, true);
}
세 번째 인자동작
true (권장)URL 변경 후에도 바인딩 유지. 모든 플랫폼에서 기본으로 사용
false (Windows/macOS 대안)URL 변경 시 바인딩 해제 → OnUrlChanged에서 PrepareJsBridge()로 재바인딩 필요
정보

Windows / macOS에서 바인딩 실패 시 PC(Windows, macOS)에서 BindUObject(..., true) 적용 후 JavaScript Bridge가 동작하지 않으면, 세 번째 인자를 false 로 변경하세요.

WebBrowserWidget->BindUObject(linkName, this, false);

false를 사용하면 페이지 이동마다 바인딩이 해제되므로, 아래 URL 변경 알림 절의 OnHandleOnUrlChanged에서 PrepareJsBridge()를 호출해 재바인딩해야 합니다.

URL 변경 알림

웹뷰 내에서 페이지가 이동할 때마다 SDK에 URL 변경을 알려야 합니다. OnUrlChanged API를 참고하세요.

BindUObject 세 번째 인자를 false 로 사용하는 경우(주로 Windows/macOS에서 바인딩 실패 시), URL 변경 시 PrepareJsBridge()로 재바인딩합니다.

UnrealStarter/Private/LoginWebBrowser.cpp
void ULoginWebBrowser::OnHandleOnUrlChanged(const FText& InText)
{
#if PLATFORM_WINDOWS || PLATFORM_MAC
PrepareJsBridge(); // BindUObject(..., false) 사용 시에만 필요
#endif
FString url = InText.ToString();
HybePlatformAgent::Instance().GetWebviewAgent()->OnUrlChanged(url);
}

BindUObject(..., true)를 사용하는 경우 URL 변경 시 재바인딩은 필요하지 않지만, SDK에 URL 변경을 알리기 위해 OnUrlChanged(url) 호출은 모든 플랫폼에서 수행해야 합니다.

JavaScript → Unreal 메시지

웹 페이지에서 호출한 JavaScript 메서드를 SDK에 전달합니다. EvalMethod API를 참고하세요.

UnrealStarter/Private/LoginWebBrowser.cpp
void ULoginWebBrowser::PostMessage(FString jsonMethod)
{
HybePlatformAgent::Instance().GetWebviewAgent()->EvalMethod(
jsonMethod, [this](const FString& resultJson)
{
if (!resultJson.IsEmpty())
{
FString js = FString::Printf(TEXT("window.unityEventHandler(%s);"), *resultJson);
ExecuteJavascript(js);
}
});
}

웹뷰 닫기

웹뷰를 닫을 때는 반드시 SDK에 OnNotifyWebviewClose() 를 호출해야 합니다. 그래야 SDK가 로그인 플로우를 계속 진행할 수 있습니다.

UnrealStarter/Private/LoginWebBrowser.cpp
void ULoginWebBrowser::CloseWebview()
{
WebBrowserWidget->LoadURL(TEXT("about:blank"));
SetVisibility(ESlateVisibility::Hidden);
HybePlatformAgent::Instance().GetWebviewAgent()->OnNotifyWebviewClose();
}

3-3. WebviewWidget에서 웹뷰 초기화

UGlobalWidgetManager::ShowWebview(url)이 호출되면 UWebviewWidget이 생성되고, 아래처럼 URL을 로드합니다.

UnrealStarter/UI/Page/WebviewWidget.cpp
void UWebviewWidget::InitWithUrl(const FString& url)
{
if (WebBrowser != nullptr)
{
WebBrowser->PrepareJsBridge();
WebBrowser->ShowWebview(url);
}
}

Step 4. SDK 초기화 (Mount)

Init 화면에서 Apply를 누르면 InitPage::MountSDK()가 호출됩니다. 멤버십 연동에 필요한 핵심 흐름은 다음과 같습니다.

4-1. Mount 전 준비 (반드시 Mount 이전에 수행)

UnrealStarter/UI/Page/InitPage.cpp - MountSDK()
void UInitPage::MountSDK()
{
// 1. Agent 등록
HybePlatformAgent::Instance().SetPlatformAuthAgent(new USPlatformAuthAgent());
HybePlatformAgent::Instance().SetPlatformWebviewAgent(new USPlatformWebviewAgent());

// 2. 로컬 저장 경로 지정 (자동 로그인 정보 저장에 사용)
HybePlatformAgent::Instance().SetWritableStorageDirectory(FPaths::ProjectSavedDir());

// 3. 클라이언트 언어 설정
HybePlatformAgent::Instance().SetClientLanguage(CachedLanguage);

// 4. Configuration JSON 준비
TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
JsonObject->SetStringField(TEXT("BuildEnv"), CachedConfig.BuildEnv);
JsonObject->SetStringField(TEXT("ProjectId"), CachedConfig.ProjectId);
JsonObject->SetStringField(TEXT("WebClientId"), CachedConfig.WebClientId);
// SteamAppID, SteamIdentity — SDK 사용 (스팀 연동 시)
// BillingAuth, ServiceId — 샘플앱 전용, SDK Plugin 미사용

FString JsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);

// 5. Mount 호출
HybePlatformAgent::Instance().Mount(JsonString);

// 6. Login 화면으로 전환
UIPageManagerSubsystem->PushPage(EUIPageType::Login, true);
}

각 단계 설명:

순서API설명
1SetPlatformAuthAgent인증 이벤트를 수신할 Agent 등록. Mount 전에 반드시 호출
1SetPlatformWebviewAgent웹뷰 이벤트를 수신할 Agent 등록. Mount 전에 반드시 호출
2SetWritableStorageDirectory자동 로그인 토큰 등을 저장할 로컬 경로. 보통 FPaths::ProjectSavedDir()
3SetClientLanguageUI 언어 코드 (ko, en 등)
4Configuration JSONMount()에 전달할 환경 설정 — 아래 상세 (Platform Configuration)
5MountSDK 초기화. 결과는 OnMount 콜백으로 전달

4-2. Mount에 전달하는 Configuration JSON

Mount(configJson)유일한 인자configJson은 SDK 초기화에 가장 중요한 입력값입니다. SDK는 이 JSON을 파싱하여 어느 플랫폼 백엔드에 접속할지, 어느 게임(프로젝트)으로 식별할지, Google 등 Third Party 로그인에 어떤 OAuth 클라이언트를 쓸지를 결정합니다. 필드 정의는 Platform Configuration을 참고하세요.

JSON 내용이 잘못되면 OnMount(false)가 호출되거나, Mount는 성공해도 이후 Login("GOOGLE") 단계에서 실패할 수 있습니다.

JSON이 만들어지는 경로 (UnrealStarter)

Content/.../drimage_config.json
↓ Init 화면에서 환경 버튼 선택
CachedConfig (FServiceConfig)
↓ MountSDK()에서 FJsonObject 조립
FString JsonString

HybePlatformAgent::Mount(JsonString)

Init 화면에서 QA-1202를 선택하면, drimage_config.json의 해당 항목이 CachedConfig에 복사되고 MountSDK()에서 아래와 같이 JSON으로 직렬화됩니다.

UnrealStarter/UI/Page/InitPage.cpp - MountSDK()
TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
JsonObject->SetStringField(TEXT("BuildEnv"), CachedConfig.BuildEnv);
JsonObject->SetNumberField(TEXT("SteamAppID"), CachedConfig.SteamAppID);
JsonObject->SetStringField(TEXT("SteamIdentity"), CachedConfig.SteamIdentity);
JsonObject->SetStringField(TEXT("ProjectId"), CachedConfig.ProjectId);
JsonObject->SetStringField(TEXT("WebClientId"), CachedConfig.WebClientId);
// 샘플앱 전용 — SDK Plugin은 아래 두 필드를 읽지 않음
JsonObject->SetStringField(TEXT("BillingAuth"), CachedConfig.BillingAuth);
JsonObject->SetStringField(TEXT("ServiceId"), CachedConfig.ServiceId);

FString JsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);

UE_LOG(USLog, Log, TEXT("JSON: %s"), *JsonString);
HybePlatformAgent::Instance().Mount(JsonString);

실제 게임 프로젝트에서는 drimage_config.json 대신 빌드 환경별 설정 파일, 원격 설정, 또는 게임 서버에서 내려받은 값으로 SDK가 요구하는 필드만 조립하면 됩니다. UnrealStarter는 QA/dev 전환과 빌링 데모를 위해 ServiceId, BillingAuth를 JSON에 추가로 넣지만, 플랫폼 SDK Plugin은 이 값들을 사용하지 않습니다.

정보

ServiceId, BillingAuth는 샘플앱 전용 필드 UnrealStarter는 Mount()에 전달하는 JSON 문자열을 ClientContext::Prepare()에도 넘겨 샘플 전용 값을 파싱합니다. BillingAuth·ServiceId가상 게임 서버(VirtualGameServerSubsystem) HTTP 요청 헤더에만 쓰이며, HybePlatform 플러그인(SDK)의 Mount·로그인 로직에는 관여하지 않습니다. 실제 게임 연동 시 Mount JSON에 포함할 필요가 없습니다.

전체 JSON 예시 (QA-1202 기준)

Init에서 QA-1202를 선택한 뒤 Mount()에 전달되는 JSON입니다. 샘플은 SDK 필드와 샘플앱 전용 필드를 한 JSON에 함께 실어 보냅니다.

Mount(configJson) 전달 예시 — UnrealStarter 샘플
{
"BuildEnv": "qa",
"SteamAppID": 4337590,
"SteamIdentity": "platform-qa-12020020",
"ProjectId": "1202",
"WebClientId": "134676729186-dfbh87213kflsoqq17koq9fa1er1oviu.apps.googleusercontent.com",
"BillingAuth": "test-auth-key",
"ServiceId": "12020020"
}

SDK Plugin이 실제로 읽는 멤버십 연동 최소 필드만 따로 보면 다음과 같습니다.

Mount(configJson) — SDK Plugin이 사용하는 필드 (Google 로그인)
{
"BuildEnv": "qa",
"ProjectId": "1202",
"WebClientId": "134676729186-dfbh87213kflsoqq17koq9fa1er1oviu.apps.googleusercontent.com",
"SteamAppID": 0,
"SteamIdentity": ""
}
정보

SteamAppID는 JSON에서 숫자(number) 타입입니다. SetNumberField로 직렬화해야 하며, 문자열 "4337590"으로 넣으면 SDK 파싱 오류나 초기화 실패의 원인이 될 수 있습니다.

필드별 상세 설명

플랫폼 SDK Plugin이 사용하는 필드

Key타입필수 (Mount)Google 로그인값의 출처설명
BuildEnvstring필수간접 영향기술 PM / drimage_config.json접속할 플랫폼 백엔드 환경. dev, qa, prod 등. SDK가 API 엔드포인트·인증 서버 URL을 이 값으로 결정합니다. 잘못된 값이면 OnMount(false)
ProjectIdstring필수필수기술 PM / drimage_config.json플랫폼에 등록된 게임(프로젝트) ID. 로그인·토큰 발급 시 게임 식별에 사용됩니다.
WebClientIdstring필수필수Google Cloud Console / 기술 PMGoogle OAuth 2.0 웹 클라이언트 ID. Login("GOOGLE") 시 OAuth 인증에 사용됩니다.
SteamAppIDnumber조건부미사용기술 PM / drimage_config.json스팀 AppId. 스팀 로그인·스팀 빌링 연동 시 필수. Google만 쓰면 0
SteamIdentitystring조건부미사용기술 PM / drimage_config.json스팀 인증용 식별 토큰. 스팀 연동 시 BuildEnv에 맞는 값 필요

UnrealStarter 샘플앱 전용 필드 (SDK Plugin 미사용)

Key타입SDK Plugin샘플앱에서의 용도
ServiceIdstring미사용ClientContext::Prepare()가 파싱 후, 가상 게임 서버 요청의 X-Req-Svcid 헤더·svcId 필드에 사용
BillingAuthstring미사용ClientContext::Prepare()가 파싱 후, 가상 게임 서버 HTTP 요청의 인증 헤더에 사용

샘플은 Mount 직전에 동일 JSON을 GetClientContext().Prepare(JsonString)에도 전달합니다. SDK는 BillingAuth·ServiceId를 무시하고, 샘플앱만 이 값을 보관합니다.

필드가 SDK 동작에 미치는 영향

BuildEnv + ProjectId — Mount 단계

SDK는 이 두 값으로 플랫폼 백엔드 연결 대상을 확정합니다. BuildEnv가 유효하지 않거나 ProjectId가 플랫폼에 등록되지 않은 경우 초기화가 실패하여 OnMount(false)가 호출됩니다.

WebClientId — Login 단계 (Google)

Mount가 성공해도 WebClientId가 현재 BuildEnv용 OAuth 클라이언트와 일치하지 않으면 Google 로그인 창에서 인증이 완료되지 않거나 OnLoginFailure가 발생합니다.

SteamAppID / SteamIdentity — 스팀 연동 시

Google 로그인 튜토리얼에서는 실질적으로 사용하지 않지만, 샘플 drimage_config.json에는 스팀 데모용 값이 포함되어 있습니다. 실제 게임에서 스팀을 쓰지 않는다면 SteamAppID: 0과 빈 SteamIdentity를 전달하는 구성도 가능합니다. (멤버십 가이드 - Platform Configuration 참고)

Configuration JSON vs DefaultEngine.ini

Mount JSON과 DefaultEngine.ini역할이 다릅니다. 둘 다 SDK 초기화·로그인에 필요하므로 함께 맞춰야 합니다.

구분Mount configJsonDefaultEngine.ini [HybeGamePlatform]
전달 방식Mount() 호출 시 런타임 문자열엔진 설정 파일, 빌드·실행 시 로드
주요 내용백엔드 환경, 프로젝트 ID, OAuth ID (BuildEnv, ProjectId, WebClientId 등)Custom URI Scheme, 스팀 AppId, Firebase/EOS 경로 등
Google 로그인 예시WebClientId (OAuth 클라이언트)CustomScheme (인증 후 앱 복귀 URI)
변경 시점Init UI·빌드 플래버·원격 설정 등으로 실행마다 바뀔 수 있음보통 앱 빌드 설정으로 고정

Google 로그인 실습에서 최소한 필요한 조합:

Config/DefaultEngine.ini
[HybeGamePlatform]
SteamAppId=0
CustomScheme=drimageplatform
Mount(configJson) — SDK Plugin 필수 필드 (Google 로그인)
{
"BuildEnv": "qa",
"ProjectId": "1202",
"WebClientId": "<현재 qa 환경에 등록된 Google OAuth Web Client ID>",
"SteamAppID": 0,
"SteamIdentity": ""
}

ServiceId, BillingAuth포함하지 않아도 SDK Mount·Google 로그인에 영향이 없습니다.

자주 하는 실수

증상원인확인 방법
OnMount(false)BuildEnv 오타, 미지원 환경Output Log, 멤버십 가이드 - OnMount
OnMount(false)ProjectId 미등록·오입력기술 PM에게 전달받은 ProjectId와 JSON 값 일치 여부
OnMount(false)SetWritableStorageDirectory 경로 쓰기 불가SetWritableStorageDirectoryFPaths::ProjectSavedDir() 등 쓰기 가능 경로 사용
Google Login cancelWebClientId가 현재 BuildEnv용이 아님drimage_config.jsonWebClientId와 Google Console 등록 환경
Google Login cancelCustomScheme 미설정·불일치DefaultEngine.iniCustomScheme
dev/qa 혼용Init에서 qa 선택했는데 JSON에 dev BuildEnvCachedConfig가 선택한 환경 버튼과 일치하는지

Output Log의 JSON: %s 로그로 실제 Mount()에 전달된 문자열을 반드시 확인하세요. UI에서 QA를 골랐는데 JSON에 다른 환경이 들어가는 경우를 빠르게 잡을 수 있습니다.

경고

ProjectId, WebClientId 등은 게임(타이틀)별로 기술 PM에게 전달받은 값입니다. 샘플 drimage_config.json의 값을 그대로 상용 게임에 사용하지 마세요. ServiceId, BillingAuth는 샘플앱 데모용이므로 실제 연동 시 Mount JSON에 넣을 필요가 없습니다.

상세 API 스펙은 멤버십 가이드 - Platform ConfigurationMount를 참고하세요.

정보

샘플에 포함된 빌링 관련 코드 UnrealStarter의 MountSDK()에는 멤버십 외에 결제 연동용 코드도 포함되어 있습니다.

// Part 2 (빌링 튜토리얼)에서 다룹니다 — 멤버십만 연동할 때는 이해만 하고 넘어가도 됩니다.
HybePlatformAgent::Instance().SetPlatformBillingAgent(new USBillingAgent());
HybeBillingPlatform::SetAvailablePayment(CachedPaymentType);

Init 화면의 결제 플랫폼(PG) 선택도 빌링 시연용 UI입니다. Google 멤버십 로그인 실습에는 영향을 주지 않습니다.

4-3. Mount 결과 확인

Mount()가 성공하면 등록한 Auth Agent의 OnMount(true)가 호출됩니다.

Output Log에서 Platform Mounted : 1 메시지가 출력되는지 확인하세요.


Step 5. Google 로그인

Login 화면에서 Google 버튼을 누르면 플랫폼 로그인이 시작됩니다.

5-1. Login 호출

UnrealStarter/UI/Page/LoginPage.cpp
void ULoginPage::OnGoogleLoginButtonClicked()
{
HandleLogin(TEXT("GOOGLE"));
}

void ULoginPage::HandleLogin(const FString& LoginType)
{
FString signinMethod = LoginType;
bool bEnableAutoLogin = AutoLoginCheckBox->IsChecked();

GetClientContext().SetSigninMode(signinMethod);
HybePlatformAgent::Instance().Login(signinMethod, bEnableAutoLogin);
// 성공: OnLoginSuccess / 실패: OnLoginFailure
}
파라미터설명
signinMethod로그인 수단. Google의 경우 "GOOGLE" (Login API 참고)
bEnableAutoLogintrue이면 다음 실행 시 DoAutoLogin으로 자동 로그인 시도

5-2. 로그인 플로우 (Google)

신규 회원인 경우:

  1. SDK가 OnShowWebview(url)을 호출합니다.
  2. USPlatformWebviewAgentUGlobalWidgetManager::ShowWebview(url)을 실행합니다.
  3. ULoginWebBrowser가 Google 가입·약관 동의 페이지를 표시합니다.
  4. 가입이 완료되면 SDK가 OnCloseWebview()를 호출하고, OnLoginSuccess가 호출됩니다.

기존 회원인 경우:

5-3. 자동 로그인

Login 화면의 자동 로그인 체크박스를 켠 상태로 로그인하면, 다음 앱 실행 시 OnMountDoAutoLogin 경로로 자동 로그인이 시도됩니다.

  1. 첫 로그인: Google 버튼 + 자동 로그인 체크 → OnLoginSuccess
  2. 앱 재실행: Init → Apply → OnMountDoAutoLogin(true)OnLoginSuccess → Lobby

자동 로그인 정보는 SetWritableStorageDirectory로 지정한 경로에 저장됩니다.

5-4. 로그인 성공 확인

로그인에 성공하면 Lobby 화면으로 전환됩니다. Output Log에서 다음을 확인하세요.

  • imid 값이 출력되는지
  • Platform Mounted : 1 이후 OnLoginSuccess 로그가 있는지

Step 6. 로그인 결과와 토큰

6-1. OnLoginSuccess JSON

로그인 성공 시 resultJson에 포함되는 주요 필드입니다. (멤버십 가이드 - OnLoginSuccess 참고)

{
"imid": "4M87F6H5GFFZDPY8QM97",
"loginToken": "xxx-xxx",
"countryCode": "KR"
}
필드설명
imid게임별 유저 ID. 게임 내 계정 식별에 사용
loginToken게임 서버 인증용 토큰. 약 1시간 동안 유효. RefreshVerifyToken으로 갱신 가능
countryCode가입 국가 코드 (ISO 3166-1 alpha-2). 예: KR, US

샘플에서는 ClientContextimid를 저장합니다.

UnrealStarter/Private/ClientContext.cpp
void ClientContext::ApplyLoginInfo(const FString& loginJson)
{
TSharedPtr<FJsonObject> jsonObject;
TSharedRef<TJsonReader<TCHAR>> jsonReader = TJsonReaderFactory<TCHAR>::Create(loginJson);
if (FJsonSerializer::Deserialize(jsonReader, jsonObject))
{
Imid = jsonObject->GetStringField(TEXT("imid"));
}
}

6-2. 게임 서버 연동 (개념)

플랫폼 로그인이 완료되면 게임 서버에 접속할 때 loginToken 을 전달합니다. 게임 서버는 이 토큰을 플랫폼 API로 검증하여 사용자를 인증합니다.

정보

이 튜토리얼의 범위 UnrealStarter의 VirtualGameServerSubsystem결제 데모용 가상 게임 서버입니다. 멤버십 튜토리얼에서는 loginToken을 확보하는 것까지만 다루며, 실제 HTTP 연동은 게임 프로젝트의 서버 연동 가이드를 참고하세요.

경고

OnLoginSuccess 직후 RefreshVerifyToken 호출 금지 OnLoginSuccess에서 받은 loginToken은 즉시 게임 서버에 사용할 수 있습니다. 이 시점에 RefreshVerifyToken()을 호출하면 FAIL_LOCK_REQUEST 오류가 발생할 수 있으므로 호출하지 마세요.


Step 7. 토큰 갱신 (선택)

loginToken은 약 1시간 동안 유효합니다. 다음 상황에서는 갱신이 필요합니다.

  • 로그인 후 즉시 게임 서버에 접속하지 않고 로비에서 오래 대기하는 경우
  • 게임 서버 연결이 끊긴 후 재접속하는 경우
  • 비정상 종료 후 로비로 복귀해 재접속하는 경우

7-1. RefreshVerifyToken 호출

Lobby → Account 화면 → 토큰 갱신 버튼을 누르면 다음 코드가 실행됩니다.

UnrealStarter/UI/Page/AccountPage.cpp
void UAccountPage::OnRefreshTokenButtonClicked()
{
HybePlatformAgent::Instance().RefreshVerifyToken();
}

7-2. OnRefreshVerifyToken 콜백

갱신된 토큰은 Auth Agent의 OnRefreshVerifyToken으로 전달됩니다.

UnrealStarter/Agent/USPlatformAuthAgent.cpp
void USPlatformAuthAgent::OnRefreshVerifyToken(const FString& token)
{
if (token.IsEmpty())
{
// 갱신 실패 — 사용자에게 안내
}
else
{
// 갱신된 token을 게임 서버 재접속에 사용
}
}
정보

샘플의 빌링 관련 코드 샘플의 OnRefreshVerifyToken에는 USBillingAgent::PrepareBillingPlatform() 호출이 포함되어 있습니다. 이는 빌링 연동용이며, 멤버십만 사용할 때는 무시해도 됩니다.


Step 8. 로그아웃

8-1. 일반 로그아웃 (Signout)

Lobby → Account로그아웃 버튼:

UnrealStarter/UI/Page/AccountPage.cpp
void UAccountPage::OnLogoutButtonClicked()
{
GetClientContext().SetSigninMode("");
HybePlatformAgent::Instance().Signout();
// 성공 시 OnLogoutSuccess → Login 화면 복귀
}

Signout()은 플랫폼 서버에 로그아웃을 요청하고, 성공하면 OnLogoutSuccess가 호출되어 Login 화면으로 돌아갑니다.

8-2. 강제 로그아웃 (ForceSignout)

서버 통신 없이 로컬 세션만 정리할 때 사용합니다.

HybePlatformAgent::Instance().ForceSignout();

8-3. 탈퇴 (Withdraw)

회원 탈퇴는 Withdraw() API를 사용합니다. 탈퇴 완료 시 OnWithDraw가 호출되며, 샘플에서는 ForceSignout()으로 로컬 세션을 정리합니다. 상세 내용은 멤버십 가이드 - 탈퇴를 참고하세요.


검증 체크리스트

튜토리얼을 완료했는지 아래 항목을 확인하세요.

  • UnrealStarter가 Windows 에디터에서 정상 실행된다.
  • Init 화면에서 QA 환경·언어·PG를 선택하고 Apply가 활성화된다.
  • Output Log에 Platform Mounted : 1이 출력된다.
  • Login 화면에서 Google 버튼으로 로그인에 성공한다.
  • (신규 계정) 웹뷰에서 가입·약관 동의가 완료된다.
  • Lobby 화면으로 전환된다.
  • Log에서 imid 값을 확인할 수 있다.
  • (선택) Account 화면에서 RefreshVerifyToken 동작
  • Signout 후 Login 화면으로 복귀

자주 발생하는 문제 (Windows + Google)

Mount 실패 (OnMount(false))

  • drimage_config.jsonProjectId, WebClientId가 올바른지 확인
  • SetWritableStorageDirectory에 쓰기 가능한 경로가 지정되었는지 확인
  • DefaultEngine.ini[HybeGamePlatform] 섹션이 존재하는지 확인

Google 로그인 취소 / 실패

  • Configuration JSON의 WebClientId가 현재 BuildEnv(qa/dev)에 등록된 OAuth 클라이언트 ID인지 확인
  • 사용자가 브라우저 인증 창을 닫은 경우 OnLoginFailure가 호출되는 것이 정상

웹뷰가 표시되지 않음

  • WebBrowser 플러그인이 활성화되어 있는지 확인
  • USPlatformWebviewAgent::OnShowWebviewGameThread에서 ShowWebview를 호출하는지 확인
  • ULoginWebBrowser::PrepareJsBridge()ShowWebview 전에 호출되는지 확인

Apply 버튼이 비활성화됨

Windows에서는 환경 + 언어 + 결제 플랫폼(PG) 세 가지를 모두 선택해야 Apply가 활성화됩니다. PG를 선택했는지 확인하세요.

기타

더 많은 문제 해결 방법은 멤버십 가이드 - Troubleshooting을 참고하세요.


다음에 읽을 문서

문서내용
Unreal Engine 멤버십Steam/Epic/모바일 로그인, API Reference, iOS Capability
Unreal Engine 빌링 튜토리얼Android PlayStore 결제 실습 (빌링 Part 2)
Unreal Engine 빌링인앱 결제·PG 결제 연동
멤버십 체크리스트출시 전 멤버십 연동 점검 항목

핵심 소스 파일 요약

파일멤버십 튜토리얼에서의 역할
UnrealStarter/Agent/USPlatformAuthAgent.*Mount, OnLoginSuccess/OnLoginFailure, OnLogoutSuccess, OnRefreshVerifyToken
UnrealStarter/Agent/USPlatformWebviewAgent.*OnShowWebview/OnCloseWebview
UnrealStarter/Public/LoginWebBrowser.*OnUrlChanged, EvalMethod, OnNotifyWebviewClose
UnrealStarter/UI/Page/WebviewWidget.cpp웹뷰 위젯 초기화
UnrealStarter/UI/Page/InitPage.cppAgent 등록, Configuration JSON, Mount()
UnrealStarter/UI/Page/LoginPage.cppLogin("GOOGLE", autoLogin)
UnrealStarter/UI/Page/AccountPage.cppRefreshVerifyToken(), Signout()
UnrealStarter/Private/ClientContext.cppOnLoginSuccess JSON에서 imid 저장
UnrealStarter/UnrealStarter.Build.cs게임 모듈이 HybePlatform 플러그인에 의존 선언
Plugins/HybePlatform/Source/HybePlatform/HybePlatform.Build.cs네이티브 PlatformSDK 라이브러리 링크 (플러그인 내부)
Plugins/HybePlatform/플랫폼 SDK 언리얼 플러그인 배포본
Config/DefaultEngine.iniCustomScheme, SteamAppId
Content/.../drimage_config.jsonPlatform Configuration (QA/dev)