콘텐츠로 이동

자동 로그인 구현하기

레시피 코드로 자동 로그인을 구현하려면 아래 절차를 순서대로 완료하세요.

시작하기 전에 공통 사전 준비를 마치세요.

전체 흐름

각 단계에서 무엇을 설정하고 무엇을 호출하는지는 아래와 같습니다.

순서 구분 하는 일
1 Hive 콘솔 Client ID 확인
2 Hive Axyl SDK 인증 모듈과 보안 저장소 모듈 설치
3 Hive Axyl SDK SDK 초기화와 모듈 등록
4 레시피 코드 레시피 폴더 복사
5 앱 코드 인증 정보 저장소 준비
6 Hive Axyl SDK, 앱 코드 로그인 직후 인증 정보 저장
7 레시피 코드 앱 시작 시 자동 로그인 호출
8 앱 코드 복원 결과 처리
9 Hive Axyl SDK, 앱 코드 액세스 토큰 자동 갱신 활성화
10 앱 서버, Hive Axyl 서버 API 앱 서버에서 액세스 토큰 검증
11 앱 코드 동작 확인
저장한 인증 정보는 세션의 최신 토큰과 같아야 합니다

Hive Axyl 인증 서버는 리프레시 토큰을 사용할 때마다 새 값으로 교체하고 이전 값을 무효화합니다. 저장해 둔 리프레시 토큰이 이전 값이라면, 액세스 토큰까지 만료된 다음 실행에서 자동 로그인이 거절됩니다. 세션의 토큰이 새로 발급될 때마다 6단계와 같은 방법으로 저장 값을 교체하세요. 갱신 시점을 감지하는 방법은 9단계에서 안내합니다.

1. Hive 콘솔에서 Client ID 확인

  • Hive 콘솔  Hive 콘솔에서 설정하거나 확인합니다.

Hive 콘솔에서 세션 복원에 사용할 Client ID를 확인하세요. 7단계에서 레시피를 만들 때 이 값을 입력합니다.

설정 항목 필수 여부 확인할 곳
Client ID 확인 필수 보안 키 획득
Client Secret은 앱 클라이언트에 넣지 마세요

레시피는 Client ID만 사용합니다. Client Secret이 앱 클라이언트에서 유출되면 악의적인 사용자가 API를 무단으로 호출할 수 있습니다.

2. SDK 모듈 설치

  • Hive Axyl SDK  Hive Axyl SDK를 앱에서 호출합니다.


    상세 절차: 모듈 설치

인증 모듈과 보안 저장소 모듈을 Unity 프로젝트에 설치하세요. 보안 저장소 모듈은 액세스 토큰과 리프레시 토큰을 기기에 암호화해 보관할 때 사용합니다.

패키지 필요 여부 역할
com.com2usplatform.hiveaxyl.core 필수 SDK 초기화와 로그인 세션 관리
com.com2usplatform.hiveaxyl.auth 필수 저장한 토큰으로 로그인, 토큰 발급
com.com2usplatform.hiveaxyl.storage 권장 액세스 토큰과 리프레시 토큰의 암호화 저장

앱에서 이미 안전한 저장소를 사용한다면 com.com2usplatform.hiveaxyl.storage를 설치하지 않아도 됩니다. 다만 이 경우에도 액세스 토큰, 리프레시 토큰, Player ID를 앱을 다시 시작한 뒤에도 읽을 수 있어야 합니다.

3. SDK 초기화

앱 시작 지점에서 SDK를 한 번 초기화하고 인증, 토큰, 보안 저장소 모듈을 등록하세요. 레시피는 SDK를 초기화하지 않으므로, 초기화하지 않은 상태에서 호출하면 FailedPrecondition 오류로 실패합니다.

아래는 자동 로그인에 필요한 모듈을 등록해 초기화하는 예제 코드입니다.

using Hive.Axyl.Auth;
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity;
using Hive.Axyl.Storage;

var config = CoreConfig.CreateBuilder("{appId}").Build();

HiveBootstrap.Initialize(config, builder =>
{
    builder
        .AddAuth()
        .AddToken()
        .AddSecureStorage();
});

{appId}에는 Hive 콘솔에서 만든 App ID를 입력하세요.

AddAuth()와 AddToken()을 등록하지 않으면 레시피가 FailedPrecondition 오류로 실패합니다. 앱에서 다른 안전한 저장소를 사용한다면 AddSecureStorage()는 등록하지 않아도 됩니다.

4. 레시피 코드 설치

  • 레시피 코드  레시피 코드를 프로젝트에 복사합니다.

레시피는 패키지가 아니라 프로젝트에 복사해서 사용하는 소스 코드입니다. axyl-samples-unity 저장소에서 아래 항목을 Unity 프로젝트의 Assets/Recipes/ 아래로 복사하세요.

복사할 항목과 역할은 아래와 같습니다.

  • Recipes.asmdef: 레시피 공통 어셈블리 정의
  • AssemblyInfo.cs: 내부 헬퍼를 다른 레시피 어셈블리에 공개하는 설정
  • Helper/: 여러 레시피가 함께 사용하는 공통 코드
  • AutoLogin/: AutoLoginRecipe, StoredSession, 결과 유형

앱 코드에서 레시피를 호출하려면 앱 쪽 어셈블리 정의의 references에 아래 어셈블리를 추가하세요. 원본 Recipes.asmdef의 autoReferenced 값이 false이므로 앱 어셈블리가 자동으로 참조하지 않습니다.

{
  "name": "MyApp",
  "references": [
    "Hive.Axyl.Core",
    "Hive.Axyl.Auth",
    "Hive.Axyl.Storage",
    "Hive.Axyl.Samples.Recipes"
  ]
}

MyApp은 앱에서 사용하는 어셈블리 이름으로 바꾸고, 기존 설정과 참조는 유지하세요. Unity 어셈블리는 참조를 전이하지 않으므로 앱 코드가 직접 사용하는 어셈블리를 모두 여기에 적어야 합니다. Hive.Axyl.Core에는 CoreConfig와 HiveError가, Hive.Axyl.Auth에는 AddAuth()와 AddToken()이, Hive.Axyl.Storage에는 AddSecureStorage()가 들어 있습니다. AddSecureStorage()를 등록하지 않는다면 Hive.Axyl.Storage는 적지 않아도 됩니다.

AutoLogin/만 복사하면 컴파일되지 않습니다

AutoLoginRecipe는 Helper/의 공통 코드를 사용합니다. PKCE 값 생성, 토큰 만료 시각 읽기, SDK 결과 분류, 세션 준비가 모두 여기에 있습니다. Helper/, Recipes.asmdef, AssemblyInfo.cs를 함께 복사하세요.

5. 인증 정보 저장소 준비

레시피에 전달할 인증 정보는 StoredSession 형식이며, 액세스 토큰, 리프레시 토큰, Player ID로 구성됩니다. 레시피는 이 값을 저장하거나 삭제하지 않으므로 저장소는 앱이 직접 만듭니다.

세 값의 의미는 아래와 같습니다.

  • AccessToken: 지난 실행이 마지막으로 사용한 액세스 토큰. 만료된 값이어도 됨
  • RefreshToken: 지난 실행이 마지막으로 사용한 리프레시 토큰
  • PlayerId: 두 토큰이 가리키는 사용자의 Player ID

Hive Axyl SDK는 세션을 메모리에만 유지하므로 앱을 종료하면 세 값이 모두 사라집니다. 토큰은 만료되기 전까지 사용자를 대신할 수 있는 자격 증명이므로, com.com2usplatform.hiveaxyl.storage가 제공하는 기기 보안 저장소처럼 암호화된 저장소에 보관하세요.

로그인에 사용한 DeviceKey나 게스트 자격 증명은 StoredSession에 들어가지 않습니다. 두 값은 로그인 기능이 쓰는 값이므로 로그인 활용 가이드에서 안내한 대로 따로 보관하세요.

아래 세 동작을 제공하는 저장소 컴포넌트를 앱에서 만드세요. 아래 예제 코드는 이 저장소를 storedSessionStore라는 이름으로 부릅니다.

동작 예제 코드의 메서드 반환값 설명
불러오기 LoadAsync() StoredSession 또는 null 저장된 세 값을 읽어 StoredSession.Create()로 다시 만듭니다. 값이 없으면 null을 반환합니다.
저장 SaveAsync() 없음 전달받은 StoredSession의 세 값으로 기존 값을 교체합니다.
삭제 DeleteAsync() 없음 저장된 값을 지웁니다.

세 동작 모두 저장소 접근을 기다리므로 비동기 메서드로 만들고, 호출하는 화면이 가진 CancellationToken을 함께 받으세요.

StoredSession은 저장한 세 값으로 다시 만드세요

JsonUtility는 StoredSession의 속성 값을 저장하지 않습니다. 두 토큰과 PlayerId를 공개 필드로 가진 별도 형식에 옮겨 저장하고, 불러올 때는 그 값으로 StoredSession.Create()를 호출하세요.

StoredSession.Create()는 두 토큰이 모두 비어 있거나 PlayerId가 0 이하이면 ArgumentException을 발생시킵니다. 저장된 값이 없으면 빈 StoredSession을 만들지 말고 null을 반환해 레시피에 그대로 전달하세요.

저장소가 정상으로 동작하지 않을 때는 상황을 구분해 처리하세요. com.com2usplatform.hiveaxyl.storage를 사용한다면 저장과 읽기 호출의 결과로 상황을 구분합니다.

상황 결과 값 처리
저장소 접근 거부 AccessDenied 저장된 값을 삭제하지 않고 로그인 화면을 노출
일시적 실패 또는 알 수 없는 결과 Failure(Problem.Code가 Internal 등), UnknownOutcome 저장된 값을 삭제하지 않고 로그인 화면을 노출
저장 데이터 손상 확정 DataCorrupted 저장소를 초기화한 뒤 로그인 화면을 노출

저장소 접근 거부와 데이터 손상은 다르게 처리하세요. 접근이 거부되거나 일시적으로 실패한 경우에는 기존 데이터가 남아 있을 수 있으므로 저장소를 초기화하면 안 됩니다.

6. 로그인 직후 인증 정보 저장

  • Hive Axyl SDK  Hive Axyl SDK를 앱에서 호출합니다.

    앱 코드  앱에서 직접 구현합니다.


    상세 절차: 인증 정보 저장

사용자가 로그인해 세션이 활성화된 직후에 세션의 토큰을 읽어 저장하세요. 이 단계를 건너뛰면 다음 실행에서 복원할 값이 없습니다.

ISessionManager.GetSnapshot()은 현재 세션의 액세스 토큰, 리프레시 토큰, Player ID를 한 번에 돌려줍니다. 이 값으로 StoredSession을 만들어 5단계의 저장소에 넘기세요. 세션이 없는 상태에서는 세 값이 비어 있어 StoredSession.Create()가 ArgumentException을 발생시키므로, IsLoggedIn으로 세션을 먼저 확인하세요.

using Hive.Axyl.Core;
using Hive.Axyl.Samples.Recipes;

StoredSession CaptureStoredSession()
{
    ISessionManager session = HiveCore.Resolve<ISessionManager>();
    if (!session.IsLoggedIn)
    {
        return null;
    }

    SessionSnapshot snapshot = session.GetSnapshot();

    return StoredSession.Create(
        snapshot.AccessToken, snapshot.RefreshToken, snapshot.PlayerId);
}

StoredSession captured = CaptureStoredSession();
if (captured != null)
{
    await storedSessionStore.SaveAsync(captured, cancellationToken);
}

cancellationToken은 저장을 호출하는 로그인 화면이 가진 CancellationToken입니다.

CaptureStoredSession()은 8단계에서도 사용합니다. 자동 로그인에 성공하면 새 토큰 한 쌍이 발급되므로 그 시점에도 저장 값을 교체해야 합니다.

7. 자동 로그인 호출

  • 레시피 코드  레시피 코드를 앱에서 호출합니다.

앱을 시작할 때 저장된 인증 정보를 불러와 LoginAsync()에 전달하세요. 값이 null이면 레시피가 복원을 시도하지 않고 NoSession을 돌려주므로, 저장된 값이 있는지 앱에서 미리 판단하지 않아도 됩니다.

세션이 없는 상태에서만 호출하세요

레시피는 복원에 성공하면 세션을 설치합니다. 이미 로그인한 상태에서 호출하면 방금 만든 세션이 교체됩니다. 앱을 시작한 뒤 로그인 화면을 그리기 전에 한 번만 호출하세요.

사용자가 시작 화면을 벗어나면 기다리기를 멈출 수 있도록 CancellationTokenSource를 함께 준비하세요.

using System.Threading;
using Hive.Axyl.Samples.Recipes;

var recipe = new AutoLoginRecipe(clientId);

var cancellation = new CancellationTokenSource();
CancellationToken cancellationToken = cancellation.Token;

StoredSession stored = await storedSessionStore.LoadAsync(cancellationToken);

AutoLoginOutcome outcome = await recipe.LoginAsync(stored, cancellationToken);

clientId에는 1단계에서 확인한 값을 입력하세요. 비어 있는 값을 넣으면 생성자가 ArgumentException을 발생시킵니다. 시작 화면을 벗어나거나 사용자가 취소를 선택할 때 cancellation.Cancel()을 호출하고, 호출이 끝나면 cancellation.Dispose()로 정리하세요.

레시피는 저장된 액세스 토큰의 만료 시각을 읽어 두 복원 경로 중 하나를 한 번만 선택합니다. 한 경로가 실패해도 다른 경로로 넘어가지 않으며, 쓸 수 있는 토큰이 없으면 복원을 시작하지 않습니다.

  • 액세스 토큰의 만료까지 30초 넘게 남은 상태: 액세스 토큰으로 로그인한 뒤 새 토큰 한 쌍 발급
  • 리프레시 토큰은 있지만 액세스 토큰이 없거나, 만료되었거나, 만료 시각을 읽을 수 없는 상태: 리프레시 토큰을 새 토큰 한 쌍으로 교환
  • 쓸 수 있는 토큰이 하나도 없는 상태: 복원을 시도하지 않고 StoredCredentialIsStale이 true인 NoSession 반환

레시피가 내부에서 수행하는 작업은 아래와 같습니다.

구분 호출 확인할 곳
레시피 코드 PKCE 값 한 쌍을 만들어 로그인 호출과 토큰 발급 호출에 나눠 전달 저장한 액세스 토큰으로 복원
Hive Axyl SDK LoginWithAccessTokenAsync()로 저장한 액세스 토큰을 검증하고 인가 코드 발급 저장한 액세스 토큰으로 복원
Hive Axyl SDK IssueTokenAsync()로 인가 코드를 액세스 토큰과 리프레시 토큰으로 교환 액세스 토큰과 리프레시 토큰 발급
Hive Axyl SDK IssueTokenAsync()로 저장한 리프레시 토큰을 새 토큰 한 쌍으로 교환 저장한 리프레시 토큰으로 복원
Hive Axyl SDK SetSession()으로 로그인 세션 활성화 세션 활성화

세션은 복원이 모두 끝난 뒤에 한 번만 활성화됩니다. 중간에 실패하면 세션이 만들어지지 않으므로, 실패한 뒤에 세션을 직접 정리하지 않아도 됩니다.

액세스 토큰 경로에서는 서버가 돌려준 Player ID와 저장해 둔 Player ID를 대조합니다. 두 값이 다르면 다른 계정의 세션이 만들어질 수 있으므로 레시피가 토큰 교환 전에 중단하고, Status는 Failure, Error.Code는 HiveErrorCode.FailedPrecondition으로 돌려줍니다. 이때 저장한 값은 그대로 남으므로 사용자가 직접 로그인하도록 안내하세요.

위 표의 상세 절차는 Hive Axyl SDK 메서드를 직접 호출할 때를 기준으로 쓰여 있습니다. PKCE 값을 만드는 작업처럼 레시피가 대신하는 단계는 앱에서 다시 구현하지 마세요. 각 호출이 무엇을 주고받는지 확인할 때만 참조하세요.

8. 복원 결과 처리

AutoLoginOutcome은 Status로 복원 결과를 알려 주고, StoredCredentialIsStale로 저장해 둔 값을 계속 보관할지 알려 줍니다. 두 값은 별개이므로 함께 확인하세요.

Status 확인할 값 앱 처리
Success PlayerId, IsBlocked 세션이 활성화된 상태입니다. 저장 값을 새 토큰으로 교체하고, 이용 제한 상태가 아니면 앱 화면으로 이동합니다.
NoSession StoredCredentialIsStale 복원할 값이 없습니다. false면 저장된 값이 아예 없는 최초 실행이거나 로그아웃한 상태이고, true면 저장된 값은 있지만 쓸 수 있는 토큰이 남아 있지 않은 상태입니다. 두 경우 모두 로그인 화면을 노출하고, true일 때는 저장 값도 지웁니다.
BusinessOutcome BusinessOutcome, UnknownOutcomeCode, RawJson 거절 사유에 맞게 분기하고, 모르는 값은 실패로 처리해 기록합니다.
Failure Error.Code, Error.TraceId 기술 문제를 기록하고, 저장 값을 보관한 채 로그인 화면을 노출합니다.
if (outcome.Status == AutoLoginStatus.Success)
{
    // 복원 과정에서 새 토큰 한 쌍이 발급되었습니다. 저장 값을 교체합니다.
    await storedSessionStore.SaveAsync(CaptureStoredSession(), cancellationToken);

    if (outcome.IsBlocked == true)
    {
        // 이용이 제한된 사용자입니다. 앱 화면으로 이동하지 않습니다.
        ShowRestrictionNotice();
    }
    else
    {
        // null은 이번 복원에서 이용 제한 여부를 확인하지 않았다는 뜻입니다.
        EnterApp(outcome.PlayerId);
    }
}
else if (outcome.StoredCredentialIsStale)
{
    // 저장한 값으로는 더 이상 복원할 수 없습니다.
    await storedSessionStore.DeleteAsync(cancellationToken);
    ShowLoginScreen();
}
else
{
    // 저장한 값은 그대로 두고 로그인 화면을 노출합니다.
    ShowLoginScreen();
}

EnterApp(), ShowRestrictionNotice(), ShowLoginScreen()은 앱의 화면 전환 코드입니다.

StoredCredentialIsStale이 false라고 해서 저장한 값을 다시 쓸 수 있다고 보장하지는 않습니다. 리프레시 토큰 경로에서는 응답을 받기 전에 토큰이 이미 소모되었을 수 있습니다. 값을 지우지는 말되, 곧바로 다시 호출하지도 마세요. 같은 값으로 다시 호출해도 안전한 경우는 실패 처리에서 확인하세요.

IsBlocked는 true, false, null 세 가지 값을 가지는 bool? 형식입니다. 액세스 토큰 경로로 복원에 성공했을 때만 서버가 돌려준 이용 제한 여부가 채워지고, 리프레시 토큰 경로로 복원했을 때와 성공이 아닌 모든 결과에서는 null입니다. 리프레시 토큰 경로는 토큰만 교환하고 사용자 상태를 확인하지 않기 때문입니다.

true이면 이용이 제한된 사용자이므로 앱 진입을 막으세요. null은 이용 제한이 없다는 뜻이 아니라 이번 복원에서 확인하지 않았다는 뜻입니다. 복원 경로와 관계없이 이용 제한 여부를 확인해야 한다면 이용 제한을 따로 호출하세요.

FailedStep은 어느 단계에서 멈췄는지 알려 주는 진단용 값입니다. 오류 기록에만 사용하고 앱의 화면 흐름을 분기하는 기준으로 사용하지 마세요.

CancellationToken으로 복원을 취소하면 Status는 Failure가 되고 Error.Code는 HiveErrorCode.Cancelled가 됩니다. 이때 세션은 만들어지지 않습니다.

9. 액세스 토큰 자동 갱신 활성화

  • Hive Axyl SDK  Hive Axyl SDK를 앱에서 호출합니다.

    앱 코드  앱에서 직접 구현합니다.


    상세 절차: 액세스 토큰 자동 갱신

복원한 세션도 시간이 지나면 액세스 토큰이 만료되므로, 자동 갱신을 켜 두면 사용자가 플레이 도중에 다시 로그인하지 않아도 됩니다. 자동 갱신을 켜면 만료된 토큰으로 메서드를 호출했을 때 Hive Axyl SDK가 리프레시 토큰으로 새 토큰을 받아 세션을 갱신하고 원래 요청을 이어서 처리합니다.

using System.Threading;
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
using Hive.Axyl.Samples.Recipes;

// SDK 초기화 이후 한 번만 호출합니다. baseUrl은 ITokenService가 사용하는 토큰 서버 호스트와 같은 값입니다.
AuthTokenRefresh.Enable("{baseUrl}", "{clientId}");

// 아래는 세션 이벤트를 구독하는 컴포넌트의 멤버입니다.
private ISessionManager m_session;

private void Start()
{
    m_session = HiveCore.Resolve<ISessionManager>();
    m_session.OnSessionRefreshed += SaveRefreshedSession;
}

private void OnDestroy()
{
    m_session.OnSessionRefreshed -= SaveRefreshedSession;
}

// 갱신된 토큰을 저장소에 반영합니다.
private async void SaveRefreshedSession(SessionSnapshot snapshot)
{
    var refreshed = StoredSession.Create(
        snapshot.AccessToken, snapshot.RefreshToken, snapshot.PlayerId);

    await storedSessionStore.SaveAsync(refreshed, CancellationToken.None);
}

{baseUrl}에는 ITokenService가 연결하는 토큰 서버 주소를 입력하세요. 3단계처럼 AddToken()을 인자 없이 등록했다면 https://core-api.hiveaxyl.com입니다. {clientId}에는 1단계에서 확인한 값을 입력하세요. Enable()은 한 번만 호출할 수 있습니다. SDK를 초기화하기 전에 호출하거나 두 번 호출하면 InvalidOperationException이 발생합니다. 구독한 컴포넌트가 사라질 때는 예제 코드의 OnDestroy()처럼 OnSessionRefreshed와 9.2에서 구독하는 OnSessionExpired의 구독을 모두 해제하세요.

9.1. 갱신된 토큰 저장

자동 갱신으로 발급된 토큰은 세션에만 반영되고 저장소에는 반영되지 않습니다. ISessionManager.OnSessionRefreshed는 세션의 토큰이 새로 등록될 때마다 최신 SessionSnapshot과 함께 발생하므로, 이 이벤트를 구독해 저장 값을 교체하세요. 이 구독을 빼면 저장해 둔 리프레시 토큰이 오래된 값이 되어 다음 실행의 자동 로그인이 거절됩니다.

로그아웃하거나 다른 계정으로 로그인해 저장 값을 바꾸기 전에는 진행 중인 저장이 끝나기를 기다리세요. 저장이 삭제보다 늦게 끝나면 지운 정보가 되살아나, 다음 실행에서 로그아웃한 계정으로 다시 로그인됩니다.

9.2. 세션 종료 처리

리프레시 토큰까지 만료되면 자동 갱신이 실패하고 세션이 종료됩니다. ISessionManager.OnSessionExpired 이벤트를 구독해 이 상황을 감지하고, 종료된 세션의 저장 값을 지운 뒤 로그인 화면으로 안내하세요. 이 이벤트는 로그아웃처럼 세션을 직접 정리할 때도 발생합니다.

이 이벤트는 어느 계정의 세션이 끝났는지 알려 주지 않습니다. 현재 세션이 어느 계정의 것인지 앱이 기억해 두고, 그 계정의 저장 값만 지우세요. 다른 계정의 저장 값과 게스트 자격 증명은 지우지 마세요.

이벤트 없이 세션이 끝나면 저장 값을 지우지 마세요

토큰 갱신이 유효성을 확정하지 못한 채 연속으로 세 번 실패하면 OnSessionExpired 없이 세션이 끝나고 IsLoggedIn이 false가 됩니다. 이때 저장해 둔 값은 여전히 유효하므로 지우지 말고, 7단계의 자동 로그인으로 세션을 다시 만드세요. 발생 조건은 OnSessionExpired를 참조하세요.

10. 앱 서버에서 액세스 토큰 검증

앱 서버가 플레이 데이터를 다루는 앱이라면, 복원한 세션으로 보낸 요청도 새로 로그인한 세션과 똑같이 검증해야 합니다. 자동 로그인은 세션을 복원할 뿐이므로 앱 서버가 사용자를 식별하는 절차는 달라지지 않습니다.

앱 클라이언트가 ISessionManager.AccessToken을 앱 서버로 보내면, 앱 서버가 그 값으로 Hive Axyl 서버 API를 호출해 토큰이 유효한지와 토큰 주인의 Player ID를 확인합니다. 앱 클라이언트가 보낸 Player ID를 그대로 신뢰하지 말고 Hive Axyl 서버가 확인해 준 값을 기준으로 처리하세요.

앱 서버 없이 앱 클라이언트만으로 서비스한다면 이 단계는 필요하지 않습니다.

11. 동작 확인

  • 앱 코드  앱에서 동작을 확인합니다.

실제 기기에서 두 복원 경로를 모두 확인하세요. Unity 에디터에서는 기기 보안 저장소가 없어 ISecureStorage가 등록되지 않으므로 저장과 재시작 흐름을 그대로 검증할 수 없습니다.

  1. 로그인한 뒤 저장소를 읽어 null이 아닌 StoredSession이 돌아오는지 확인하세요.
  2. 앱을 완전히 종료한 뒤 다시 실행해 Success와 로그인할 때와 같은 PlayerId를 확인하세요.
  3. 저장된 액세스 토큰을 형식이 깨진 문자열로 바꿔 놓고 앱을 다시 실행하세요. 레시피가 만료 시각을 읽지 못해 리프레시 토큰 경로를 선택하므로, 이 경로로도 Success가 나오는지 확인합니다.
  4. 저장소를 비운 뒤 앱을 실행해 NoSession이 나오고 로그인 화면이 보이는지 확인하세요.

실패 처리

레시피 메서드는 예외를 던지지 않고 결과 객체를 돌려줍니다. 8단계의 Status가 BusinessOutcome이면 Hive Axyl 서버가 복원을 거절한 것이므로 BusinessOutcome 값에 따라 처리가 달라집니다.

BusinessOutcome 의미 앱이 할 일
InvalidRefreshToken, PlayerNotFound 저장한 인증 정보를 더 이상 쓸 수 없습니다. StoredCredentialIsStale이 true로 함께 오므로 저장 값을 삭제하고 로그인 화면을 노출합니다.
TemporarilyUnavailable 토큰 발급 단계에서 Hive Axyl 인증 서버가 내부 저장소에 일시적으로 접근하지 못해 판정을 내리지 못했고, 요청은 아무 효과도 남기지 않았습니다. 토큰 발급 결과 가운데 다시 시도할 수 있는 결과는 이것뿐입니다. 바로 다시 호출하지 말고, 시도할 때마다 간격을 늘려 가며 같은 값으로 다시 호출하세요. 간격은 앱이 정합니다.
AppIdMismatch 저장된 토큰을 발급한 App ID와 현재 빌드의 App ID가 다릅니다. 저장 값을 지우지 말고 빌드의 App ID를 확인하세요.
AppNotFound, InvalidClient 앱이 보낸 App ID나 Client ID를 서버가 알지 못합니다. 저장 값을 지우지 말고 Hive 콘솔의 App ID와 Client ID를 확인하세요.
UnsupportedGrantType 서버가 레시피의 토큰 발급 방식을 지원하지 않습니다. 앱이 고칠 수 있는 값이 없습니다. 오류를 기록한 뒤 로그인 화면을 노출하세요.
IpBlocked, ServiceTerminated 서버가 정책에 따라 요청을 거절했습니다. 저장 값을 지우지 말고 사용자에게 상황을 안내하세요.
InvalidGatewayContext 요청의 호출 정보를 게이트웨이가 받아들이지 않았습니다. 사용자에게 표시하지 말고 기록한 뒤 로그인 화면을 노출하세요.
InvalidAuthorizationCode, ExpiredAuthorizationCode, CodeChallengeMismatch 복원 과정의 토큰 발급이 거절되었습니다. 저장 값을 지우지 말고 로그인 화면을 노출하세요. 리프레시 토큰이 이미 소모되었을 수 있으므로 자동으로 다시 호출하지 마세요.
Unrecognized 이 레시피가 번역하지 않는 응답입니다. 실패로 처리해 기록하고, 아는 값으로 추정하지 마세요.
실패했다고 같은 리프레시 토큰으로 다시 호출하지 마세요

Hive Axyl 인증 서버는 리프레시 토큰을 사용할 때마다 새 값으로 교체하고 이전 값을 무효화합니다. 다시 시도할 수 있는 TemporarilyUnavailable만 예외이며, 그 밖의 실패 뒤에 같은 값으로 다시 호출하면 그 호출도 거절됩니다.

Unrecognized는 두 가지 상황을 함께 가리킵니다. UnknownOutcomeCode에 값이 있으면 현재 SDK 빌드가 모르는 응답을 서버가 보낸 것이고, 비어 있으면 SDK는 아는 응답이지만 레시피가 아직 옮기지 않은 것입니다. 두 값 모두 RawJson과 함께 오류 기록에만 사용하고 사용자에게 표시하지 마세요.

Status가 Failure인 경우의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.

다음 단계

사용자가 앱을 떠날 때 저장한 인증 정보를 지우려면 로그아웃 활용 가이드를 참조하세요.