유저네임 로그인 구현하기
레시피 코드로 유저네임 로그인을 구현하려면 아래 절차를 순서대로 완료하세요.
시작하기 전에 공통 사전 준비를 마치세요.
전체 흐름
각 단계에서 무엇을 설정하고 무엇을 호출하는지는 아래와 같습니다.
| 순서 | 구분 | 하는 일 |
|---|---|---|
| 1 | Hive 콘솔 | Client ID 확인과 유저네임 로그인 활성화 |
| 2 | Hive Axyl SDK | 인증 모듈과 보안 저장소 모듈 설치 |
| 3 | Hive Axyl SDK | SDK 초기화와 모듈 등록 |
| 4 | 레시피 코드 | 레시피 폴더 복사 |
| 5 | 앱 코드 | ClientId와 DeviceKey 준비 |
| 6 | 앱 코드 | 유저네임과 비밀번호 입력 처리 |
| 7 | 앱 코드 | 추가 보안 키 준비 |
| 8 | 레시피 코드 | 유저네임 로그인 호출 |
| 9 | 앱 코드 | 로그인 결과 처리 |
| 10 | 앱 코드 | 동작 확인 |
유저네임을 잘못 입력하면 새 계정이 만들어집니다
레시피는 입력한 유저네임의 계정이 없으면 그 유저네임으로 계정을 만듭니다. Success 결과의 IsNewAccount를 확인해 새 계정이 만들어졌음을 사용자에게 반드시 알리세요.
1. Hive 콘솔 설정
- Hive 콘솔 Hive 콘솔에서 설정하거나 확인합니다.
Hive 콘솔에서 로그인에 사용할 Client ID를 확인하고 유저네임 로그인을 활성화하세요. 로그인 수단이 비활성 상태이면 레시피 호출이 거절됩니다.
| 설정 항목 | 필수 여부 | 확인할 곳 |
|---|---|---|
| Client ID 확인 | 필수 | 보안 키 획득 |
| 유저네임 로그인 활성화 | 필수 | 콘솔에서 로그인 활성화 상태 확인 |
Client Secret은 앱 클라이언트에 넣지 마세요
레시피는 Client ID만 사용합니다. Client Secret이 앱 클라이언트에서 유출되면 악의적인 사용자가 API를 무단으로 호출할 수 있습니다.
2. SDK 모듈 설치
-
Hive Axyl SDK Hive Axyl SDK를 앱에서 호출합니다.
상세 절차: 모듈 설치
인증 모듈과 보안 저장소 모듈을 Unity 프로젝트에 설치하세요. 보안 저장소 모듈은 DeviceKey를 기기에 암호화해 보관할 때 사용합니다.
| 패키지 | 필요 여부 | 역할 |
|---|---|---|
com.com2usplatform.hiveaxyl.core | 필수 | SDK 초기화와 로그인 세션 관리 |
com.com2usplatform.hiveaxyl.auth | 필수 | 유저네임 로그인, 계정 생성, 토큰 발급 |
com.com2usplatform.hiveaxyl.storage | 권장 | DeviceKey의 암호화 저장 |
앱에서 이미 안전한 저장소를 사용한다면 com.com2usplatform.hiveaxyl.storage를 설치하지 않아도 됩니다. 이 경우에도 DeviceKey를 앱 재시작 뒤에 다시 읽을 수 있어야 합니다.
3. SDK 초기화
-
Hive Axyl SDK Hive Axyl SDK를 앱에서 호출합니다.
상세 절차: SDK 초기화, 보안 저장소 모듈 등록
앱 시작 지점에서 SDK를 한 번 초기화하고 인증, 토큰, 보안 저장소 모듈을 등록하세요. 레시피는 SDK를 초기화하지 않으므로, 초기화하지 않은 상태에서 호출하면 FailedPrecondition 오류로 실패합니다.
아래는 유저네임 로그인에 필요한 모듈을 등록해 초기화하는 예제 코드입니다.
{appId}에는 Hive 콘솔에서 만든 App ID를 입력하세요.
AddAuth()와 AddToken()을 등록하지 않으면 레시피가 FailedPrecondition 오류로 실패합니다. 앱에서 다른 안전한 저장소를 사용한다면 AddSecureStorage()는 등록하지 않아도 됩니다.
4. 레시피 코드 설치
- 레시피 코드 레시피 코드를 프로젝트에 복사합니다.
레시피는 패키지가 아니라 프로젝트에 복사해서 사용하는 소스 코드입니다. axyl-samples-unity 저장소에서 아래 항목을 Unity 프로젝트의 Assets/Recipes/ 아래로 복사하세요.
복사할 항목과 역할은 아래와 같습니다.
- Recipes.asmdef: 레시피 공통 어셈블리 정의
- AssemblyInfo.cs: 내부 헬퍼를 다른 레시피 어셈블리에 공개하는 설정
- Helper/: 여러 레시피가 함께 사용하는 공통 코드
- UsernameLogin/:
UsernameLoginRecipe와 결과 유형
앱 코드에서 레시피를 호출하려면 앱 쪽 어셈블리 정의의 references에 아래 어셈블리를 추가하세요. 원본 Recipes.asmdef의 autoReferenced 값이 false이므로 앱 어셈블리가 자동으로 참조하지 않습니다.
MyApp은 앱에서 사용하는 어셈블리 이름으로 바꾸고, 기존 설정과 참조는 유지하세요. Unity 어셈블리는 참조를 전이하지 않으므로 앱 코드가 직접 사용하는 어셈블리를 모두 여기에 적어야 합니다. Hive.Axyl.Core에는 CoreConfig와 HiveError가, Hive.Axyl.Auth에는 AddAuth()와 AddToken()이, Hive.Axyl.Storage에는 AddSecureStorage()가 들어 있습니다. AddSecureStorage()를 등록하지 않는다면 Hive.Axyl.Storage는 적지 않아도 됩니다.
UsernameLogin/만 복사하면 컴파일되지 않습니다
UsernameLoginRecipe는 Helper/의 비밀번호 해싱 코드, PKCE 생성 코드, 세션 준비 코드를 사용합니다. Helper/, Recipes.asmdef, AssemblyInfo.cs를 함께 복사하세요.
5. ClientId와 DeviceKey 준비
-
앱 코드 앱에서 직접 구현합니다.
상세 절차: DeviceKey
UsernameLoginRecipe의 생성자는 ClientId와 DeviceKey를 받습니다. ClientId는 1단계에서 확인한 값으로, Hive 콘솔이 프로젝트마다 발급합니다. DeviceKey는 Hive Axyl 인증 서버가 로그인 세션을 기기 단위로 구분하는 값이며, 앱이 직접 만들어 보관합니다.
레시피는 DeviceKey를 만들거나 저장하지 않으므로, 아래 조건에 맞게 만들고 관리하세요.
- 기기마다 다른 값. UUID 같은 난수 권장
- 최초 실행 때 한 번 만들어 저장하고, 이후 모든 로그인에서 재사용하는 값
- 22자 이상 64자 이하의 길이
- 공백과 제어 문자를 제외한 ASCII 문자로만 이루어진 값
저장소를 읽지 못했다고 새 DeviceKey로 덮어쓰지 마세요
값이 사라진 것이 아니라 읽기에만 실패했을 수 있습니다. 먼저 저장소 접근 문제를 해결하거나 다시 읽기를 시도하세요.
6. 유저네임과 비밀번호 입력 처리
사용자가 로그인 화면에서 입력한 유저네임과 원본 비밀번호를 그대로 레시피에 전달하세요. 레시피가 비밀번호를 SHA-256 16진수 문자열로 변환하므로, 앱 코드에서 미리 해시하면 같은 유저네임으로 만든 기존 계정에 로그인하지 못합니다.
유저네임의 허용 문자와 길이 규칙은 Hive Axyl SDK 메서드를 직접 호출할 때와 같습니다. 비밀번호는 이 연결된 절차가 설명하는 SHA-256 16진수 형식을 그대로 따르지만, 변환은 레시피가 대신하므로 앱은 형식만 확인하고 변환 코드는 구현하지 마세요.
유저네임이 비어 있거나 공백만 있으면, 또는 비밀번호가 비어 있으면 레시피가 서버를 호출하지 않고 Status가 Failure이며 Error.Code가 HiveErrorCode.InvalidArgument인 결과를 반환합니다. 이 경우에는 IsUsernameOrPasswordIncorrect가 false이므로, 로그인 버튼을 선택하기 전에 앱 화면에서 빈 입력을 먼저 걸러내세요.
원본 비밀번호와 변환된 값은 저장하거나 오류 기록에 포함하지 마세요.
7. 추가 보안 키 준비
-
앱 코드 앱에서 직접 구현합니다.
상세 절차: 유저네임 계정 생성
계정 생성에 추가 보안을 적용한 앱은 GrantKey를 함께 전달해야 합니다. 이 값은 앱 서버가 Hive Axyl 서버에서 발급받아 앱 클라이언트에 내려 주는 사전 승인 값입니다.
레시피는 새 계정을 만들 때만 GrantKey를 사용하고, 기존 계정 로그인에는 사용하지 않습니다. 추가 보안을 적용하지 않은 앱은 이 값을 전달하지 않아도 되며, 빈 문자열이나 공백만 있는 값은 전달하지 않은 것으로 처리합니다. 추가 보안이 꺼져 있을 때 GrantKey를 전달해도 그 값은 항상 검증되고 소비됩니다. 설정을 켠 뒤에는 GrantKey가 없는 계정 생성 요청이 거절되므로, 나중에 추가 보안을 켤 계획이라면 처음부터 항상 전달하도록 구현하세요.
GrantKey는 앱 클라이언트에서 만들거나 보관하지 마세요
GrantKey는 계정 생성 시도마다 앱 서버가 새로 준비합니다. 앱 클라이언트는 전달받은 값을 그대로 넘기기만 하세요. 발급에 사용하는 Client Secret과 인증 정보도 앱 클라이언트에 넣으면 안 됩니다.
8. 유저네임 로그인 호출
- 레시피 코드 레시피 코드를 앱에서 호출합니다.
로그인 버튼을 선택했을 때 LogInOrSignUpAsync()를 호출하세요. 레시피가 기존 계정 로그인을 먼저 시도하고, 해당 유저네임의 계정이 없을 때만 계정을 만듭니다.
사용자가 화면을 닫거나 로그인을 취소할 때 기다리기를 멈출 수 있도록 CancellationTokenSource를 함께 준비하세요.
추가 보안을 적용한 앱은 7단계에서 받은 grantKey를 함께 전달하세요.
화면을 닫거나 사용자가 취소를 선택할 때 cancellation.Cancel()을 호출하고, 호출이 끝나면 cancellation.Dispose()로 정리하세요.
레시피가 내부에서 수행하는 작업은 아래와 같습니다.
| 구분 | 호출 | 확인할 곳 |
|---|---|---|
| 레시피 코드 | 원본 비밀번호를 SHA-256 16진수 문자열로 변환 | Password |
| 레시피 코드 | PKCE 값을 만들어 로그인 호출과 토큰 발급 호출에 나눠 전달 | 호출 파라미터 준비 |
| Hive Axyl SDK | LoginUsernameAsync()로 기존 계정 로그인 | 유저네임 로그인 |
| Hive Axyl SDK | CreateUsernameAsync()로 계정이 없을 때 새 계정 생성 | 유저네임 계정 생성 |
| Hive Axyl SDK | IssueTokenAsync()로 인가 코드를 액세스 토큰과 리프레시 토큰으로 교환 | 액세스 토큰과 리프레시 토큰 발급 |
| Hive Axyl SDK | SetSession()으로 로그인 세션 활성화 | 세션 활성화 |
기존 계정에 로그인하면 CreateUsernameAsync()는 호출하지 않습니다. 계정을 새로 만드는 경우에는 레시피가 PKCE 값을 한 번 더 만듭니다. 거절된 호출은 인가 코드를 돌려주지 않으므로, 이미 전송한 값을 재사용하지 않기 위해서입니다.
Success가 반환되면 세션까지 준비된 상태이므로 토큰 발급이나 세션 활성화 코드를 따로 호출하지 마세요.
위 표의 상세 절차는 Hive Axyl SDK 메서드를 직접 호출할 때를 기준으로 쓰여 있습니다. 비밀번호 변환과 PKCE 생성처럼 레시피가 대신하는 단계는 앱에서 다시 구현하지 마세요. 각 호출이 무엇을 주고받는지 확인할 때만 참조하세요.
9. 로그인 결과 처리
-
앱 코드 앱에서 직접 구현합니다.
상세 절차: HiveError 정보
LoginWithUsernameOutcome은 Status로 로그인 결과를 알려 줍니다. FailedStep은 진단용 값이므로 앱의 정상 흐름을 분기하는 기준으로 사용하지 마세요.
Status | 확인할 값 | 앱 처리 |
|---|---|---|
Success | PlayerId, IsNewAccount, IsBlocked | 새 계정 여부를 알리고, 이용 제한 상태가 아니면 로그인 후 화면으로 이동합니다. |
BusinessOutcome | BusinessOutcome, IsUsernameOrPasswordIncorrect, UnknownOutcomeCode | 거절 사유에 맞게 분기하고, 모르는 값은 실패로 처리해 기록합니다. |
Failure | Error.Code, Error.TraceId | 기술 문제를 기록하고 로그인 화면을 유지한 채 재시도 흐름을 제공합니다. |
IsBlocked는 기존 계정에 로그인했을 때만 값이 채워집니다. 새 계정을 만든 직후에는 항상 false입니다.
9.1. 거절 사유별 처리
Status가 BusinessOutcome이면 BusinessOutcome 값으로 거절 사유를 구분하세요. 사유에 따라 사용자에게 다시 입력하도록 안내할지, 같은 요청을 다시 보낼지가 달라집니다.
BusinessOutcome | 의미 | 앱 처리 |
|---|---|---|
UsernameOrPasswordIncorrect | 입력한 유저네임의 계정은 있지만 비밀번호가 맞지 않습니다. IsUsernameOrPasswordIncorrect가 true로 함께 옵니다. | 유저네임과 비밀번호를 다시 입력하도록 안내합니다. |
GrantKeyRequired | 추가 보안을 적용한 앱에서 GrantKey 없이 새 계정을 만들려고 했습니다. | 앱 서버에서 GrantKey를 받아 7단계에 따라 전달한 뒤 다시 호출합니다. |
InvalidGrantKey | 전달한 GrantKey가 거절되었습니다. 추가 보안이 꺼져 있어도 전달한 값은 검증됩니다. | 앱 서버에서 새 GrantKey를 받아 다시 호출합니다. |
TemporarilyUnavailable | 토큰 발급 단계에서 Hive Axyl 인증 서버가 내부 저장소에 일시적으로 접근하지 못해 판정을 내리지 못했고, 요청은 아무 효과도 남기지 않았습니다. | 같은 유저네임과 비밀번호로 다시 호출합니다. 바로 다시 보내지 말고 간격을 두세요. 레시피는 1초, 3초, 6초 정도로 간격을 늘리고 간격마다 약간의 편차를 주는 방식을 권장합니다. |
Unrecognized | 이 레시피가 해석하지 않는 결과입니다. | 실패로 처리해 기록하고, 아는 값으로 추정하지 마세요. UnknownOutcomeCode와 RawJson은 기록에만 사용하고 사용자에게 표시하지 마세요. |
| 그 밖의 값 | 입력을 고치거나 같은 요청을 다시 보내도 해결되지 않는 거절입니다. 앱 설정 오류, 서비스 종료, IP 차단, 토큰 발급 단계의 거절이 여기에 해당합니다. | 거절 사유를 기록하고 로그인할 수 없다는 안내를 표시합니다. |
IsUsernameOrPasswordIncorrect는 거절 사유가 UsernameOrPasswordIncorrect일 때만 true이고, Status가 Failure인 결과에서는 항상 false입니다. 재입력을 안내할 때는 유저네임과 비밀번호 중 어느 값이 맞지 않았는지 구분해서 알려주지 마세요. 비밀번호가 틀렸다고 알려 주면 그 유저네임이 가입되어 있다는 사실이 드러납니다.
9.2. 새 계정과 다른 계정 처리
IsNewAccount가 true이면 입력한 유저네임으로 새 계정이 만들어진 상태입니다. 사용자가 기존 계정에 로그인하려다 유저네임을 잘못 입력했을 수도 있으므로, 새 계정이 만들어졌다는 사실을 분명히 알려주세요.
앱이 이전에 로그인한 PlayerId에 연결된 데이터를 보관한다면, 로그인 성공 때 반환된 PlayerId를 이전 값과 비교하세요. 값이 다르면 이전 계정의 데이터를 그대로 이어서 사용하지 말고 현재 계정에 맞는 화면과 데이터를 준비하세요.
9.3. 로그인 취소
화면을 닫거나 사용자가 취소를 선택할 때 cancellation.Cancel()로 실행 중인 로그인을 멈추세요. 취소 결과는 Status가 Failure이고 Error.Code가 HiveErrorCode.Cancelled인 값으로 반환됩니다.
취소되기 전에 새 계정이 만들어졌다면 계정은 그대로 남습니다. 같은 유저네임과 비밀번호로 다시 로그인하도록 안내하고, 취소 직후에 다른 유저네임으로 계정을 자동으로 만들지 마세요.
10. 동작 확인
- 앱 코드 앱에서 동작을 확인합니다.
앱 빌드에서 새 계정 생성, 기존 계정 로그인, 잘못된 비밀번호 입력을 확인하세요. Unity 에디터에서는 기기 보안 저장소가 없어 ISecureStorage가 등록되지 않으므로 DeviceKey 재사용까지 검증하려면 실제 기기에서 확인하세요.
- 아직 사용하지 않은 유저네임과 비밀번호로 로그인을 실행해
Success와IsNewAccount == true를 확인하세요. - 앱을 완전히 종료한 뒤 같은 유저네임과 비밀번호로 로그인해
Success와IsNewAccount == false를 확인하세요. - 같은 유저네임에 다른 비밀번호를 입력해
BusinessOutcome과IsUsernameOrPasswordIncorrect == true를 확인하세요. - 테스트 계정에서 유저네임을 잘못 입력해 새 계정 안내가 표시되는지 확인하세요.
다음 단계
로그인한 사용자가 앱을 다시 실행할 때 로그인 화면을 건너뛰도록 하려면 자동 로그인을 참조하세요.
로그인한 계정에서 빠져나와 다른 계정으로 로그인하도록 하려면 로그아웃 활용 가이드를 참조하세요.