Unity : Firebase 등록 및 Auth로 (이메일/소셜) 로그인 구현

2026. 1. 11. 15:17·Unity

Firebase

애플리케이션 개발 시 백엔드 인프라 구축의 번거로움을 최소화하는 BaaS(Backend as a Service) 플랫폼이다.

서버 코드 작성 및 인프라 관리 부담을 줄여 개발 효율성을 극대화하는 것을 목적으로 한다.

즉, 우리는 Firebase를 이용해 간단한 인증부터 DB, API까지 여러 방면으로 서버 개발 없이 빠르게 활용할 수 있다.

 


Firebase 등록 방법

1. Firebase 검색 후 Firebase - Google 페이지로 들어간다

2. Get started in console

 

3. 새 Firebase 프로젝트 만들기 클릭해서 프로젝트 만들기

 

4. 프로젝트 생성

 

프로젝트 이름을 지정하고 그 뒤에 Gemini 애널리틱스 사용 여부를 묻는데 그냥 둘다 사용 안 해도 된다.

애널리틱스는 서비스 사용량, 트래픽 분석 도구 같은 거니 필요한 경우에만 체크하면 된다.

 

5. 프로젝트 생성 완료

 

생성 완료시 최초로 다음과 같은 화면이 보인다.

 

6. 프로젝트 세팅

좌상단의 프로젝트 개요 옆에 있는 톱니바퀴를 클릭하면 프로젝트 설정 메뉴가 나온다

 

프로젝트 설정을 클릭하고 들어가면 아래와 같은 창이 뜬다.

 

유니티 프로젝트에 사용할 것이니 하단의 내 앱 쪽에서 유니티 로고를 클릭해준다.

 

 

적당히 앱 이름 등록해주고

 

 

google-services.json 다운로드를 클릭해 json 파일을 받아 Assets 폴더에 넣어준다.

json 파일은 파이어베이스에 접근하기 위한 key 등 주요 데이터가 들어있기 때문에 git에 업로드 하거나 함부로 노출하면 안되니 주의하자.

 

 

SDK zip을 다운받아준다.

SDK zip 안에는 Firebase의 각종 서비스에 대한 패키지 파일들이 들어있다.

 

크기가 그리 가볍진 않으니 내가 필요한 서비스만 유니티 프로젝트에 임포트 해주자.

여기까지 했으면 기본적인 등록은 끝났다. 다음은 인증 서비스를 만들어 보자.

 

 


Authentication 설정

Firebase Authentication은 애플리케이션의 사용자 인증 시스템을 구축하기 위한 관리형 서비스이다.

복잡한 인증 로직(암호화, 세션 유지, 보안 토큰 관리 등)을 직접 구현하지 않고 SDK 호출만으로 처리할 수 있도록 설계되어있는 매우 편리한 기능이다.

 

설정을 순차적으로 알아보자.

 

1. Authentication 활성화

 

이번에 사용해볼 건 Auth, 즉 인증(회원가입/로그인) 기능이다.

좌측의 빌드 탭을 클릭하면 리스트가 나온다.

 

Authentication 을 클릭하면 다음과 같은 창이 뜬다.

 

 

시작하기 버튼을 눌러 Authentication을 활성화 한다.

 

 

2. 로그인 방법 설정

 

우선 이메일/비밀번호와 추가 제공업체 Google을 클릭해서 활성화 해주자

 

 

그럼 이런 창이 뜬다.

등록이 완료 된 거다.

 

3. 사용자 탭에서 유저 리스트를 확인할 수 있다.

 

여기서 사용자의 고유값은 최 우측의 사용자 UID 값이다.

식별자, 닉네임 등 다른 수치는 사용자의 고유함을 보장하기 어려울 수 있기에 유저 식별에는 이 UID값을 활용하도록 하자.

 

이러면 등록 끝

 


 

이메일 / 비밀번호 기반 로그인 구현하기

 

1. FirebaseApp 초기화 및 의존성 검사

Firebase 기능을 사용하기 전, 가장 먼저 실행해야하는 단계다.

기기에 구글 플레이 서비스가 최신 상태인지 확인하고 SDK를 초기화 한다.

FirebaseApp.CheckAndFixDependenciesAsync();

 

위 메서드는 유니티 실행시 비동기로 환경을 체크하며, DependencyStatus.Available 상태일 때

FirebaseAuth.DefaultInstance 를 통해 인증 인스턴스를 가져온다.

 

2. 회원 가입

신규 사용자를 등록하는 단계다. 이메일과 비밀번호를 파라미터로 전달한다.

CreateUserWithEmailAndPasswordAsync(email, password);

 

놀랍도록 직관적인 메서드명...

 

3. 사용자 프로필 업데이트 (Nickname 설정)

사용자의 닉네임도 설정해줄 수 있다.

UpdateUserProfileAsync(UserProfile);

 

UserProfile을 생성하고, DisplayName 속성에 원하는 닉네임을 할당한다.

user.UpdateUserProfileAsync(profile) 을 호출해 사용자 정보를 갱신할 수 있다.

 

4. 로그인

SignInWithEmailAndPasswordAsync(email, password);

 

입력한 정보 (email, password)가 일치하면 FirebaseUser 객체를 반환합니다.

실패시 FirebaseException을 통해 비밀번호 불일치, 존재하지 않는 사용자 등의 구체적인 에러 코드를 확인할 수 있습니다.

 

 

전체 코드

 

using System;
using System.Collections;
using System.Threading.Tasks;
using Firebase;
using Firebase.Auth;
using Firebase.Extensions;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class FirebaseAuthManager : MonoBehaviour
{
    [Header("UI References")]
    [SerializeField] private TMP_InputField _emailField;
    [SerializeField] private TMP_InputField _pwField;
    [SerializeField] private TMP_InputField _nicknameField;
    [SerializeField] private Button _startButton;
    [SerializeField] private TMP_Text warningText;
    [SerializeField] private TMP_Text confirmText;

    // 인증 관련 핵심 객체
    public static FirebaseAuth auth; // Firebase 인증 서비스 인스턴스
    public static FirebaseUser user; // 현재 인증된 사용자 정보 (UID, DisplayName 등 포함)

    void Awake()
    {
        // [초기화] 구글 서비스 의존성 검사 및 Firebase 초기화
        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
        {
            var dependencyStatus = task.Result;
            if (dependencyStatus == DependencyStatus.Available)
            {
                auth = FirebaseAuth.DefaultInstance;
                Debug.Log("Firebase Auth Init Complete");
            }
            else
            {
                Debug.LogError($"Firebase dependencies not resolved: {dependencyStatus}");
            }
        });
    }

    void Start()
    {
        _startButton.interactable = false;
        warningText.text = "";
        confirmText.text = "";
    }

    // --- Public Interface (버튼 연결용) ---

    public void OnClickLogin()
    {
        StartCoroutine(LoginCoroutine(_emailField.text, _pwField.text));
    }

    public void OnClickSignUp()
    {
        StartCoroutine(SignUpCoroutine(_emailField.text, _pwField.text, _nicknameField.text));
    }

    // --- Authentication Logic ---

    /*
     * [로그인] 이메일과 비밀번호를 이용한 인증 메서드
     * 성공 시 유저 정보를 획득하고 시작 버튼을 활성화함
     */
    private IEnumerator LoginCoroutine(string email, string pw)
    {
        Task<AuthResult> loginTask = auth.SignInWithEmailAndPasswordAsync(email, pw);
        yield return new WaitUntil(() => loginTask.IsCompleted);

        if (loginTask.Exception != null)
        {
            HandleAuthError(loginTask.Exception);
        }
        else
        {
            user = loginTask.Result.User;
            warningText.text = "";
            confirmText.text = "Login Success!";
            _nicknameField.text = user.DisplayName;
            _startButton.interactable = true;
        }
    }

    /*
     * [회원가입] 계정 생성 및 닉네임 설정 로직
     * CreateUser 후 UpdateUserProfileAsync를 통해 DisplayName(닉네임)을 서버에 등록
     */
    private IEnumerator SignUpCoroutine(string email, string pw, string nickName)
    {
        // 1. 계정 생성 시도
        Task<AuthResult> signUpTask = auth.CreateUserWithEmailAndPasswordAsync(email, pw);
        yield return new WaitUntil(() => signUpTask.IsCompleted);

        if (signUpTask.Exception != null)
        {
            HandleAuthError(signUpTask.Exception);
        }
        else
        {
            user = signUpTask.Result.User;

            if (user != null)
            {
                // 2. 닉네임(UserProfile) 설정
                UserProfile profile = new UserProfile { DisplayName = nickName };
                Task profileTask = user.UpdateUserProfileAsync(profile);
                yield return new WaitUntil(() => profileTask.IsCompleted);

                if (profileTask.Exception != null)
                {
                    HandleAuthError(profileTask.Exception);
                }
                else
                {
                    warningText.text = "";
                    confirmText.text = "Sign Up & Profile Set Complete!";
                    _startButton.interactable = true;
                }
            }
        }
    }

    /*
     * [에러 핸들링] Firebase 인증 과정에서 발생하는 에러 코드를 분석하여 UI에 출력
     */
    private void HandleAuthError(AggregateException exception)
    {
        FirebaseException firebaseEx = exception.GetBaseException() as FirebaseException;
        AuthError errorCode = (AuthError)firebaseEx.ErrorCode;

        string message = errorCode switch
        {
            AuthError.MissingEmail => "이메일을 입력해주세요.",
            AuthError.MissingPassword => "비밀번호를 입력해주세요.",
            AuthError.WrongPassword => "비밀번호가 틀렸습니다.",
            AuthError.InvalidEmail => "유효하지 않은 이메일 형식입니다.",
            AuthError.UserNotFound => "존재하지 않는 사용자입니다.",
            AuthError.WeakPassword => "비밀번호가 너무 취약합니다.",
            AuthError.EmailAlreadyInUse => "이미 가입된 이메일입니다.",
            _ => "알 수 없는 에러가 발생했습니다."
        };

        warningText.text = message;
        confirmText.text = "";
        Debug.LogWarning($"Auth Error: {errorCode}");
    }
}

 

대부분의 에러도 Firebase에서 정의해뒀으므로 관리가 편리한 편이다.

 

유니티에 간단하게 로그인창 만들어서 적용해보면

 

 

잘 작동 한다

 


Google 소셜 로그인

 

1. 로그인 방법에서 Google이 활성화 되어있어야 한다.

또한 안드로이드 빌드시 SHA-1 등록을 해야하니 주의하자.

 

2. 코드

using Google; // Google Sign-In SDK 필요

// ... 기존 변수 선언부 아래에 추가
[SerializeField] private string _webClientId = "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com";

public void OnClickGoogleLogin()
{
    Configuration configuration = new Configuration
    {
        WebClientId = _webClientId,
        RequestIdToken = true
    };
    GoogleSignIn.Configuration = configuration;
    GoogleSignIn.Configuration.UseGameSignIn = false;
    GoogleSignIn.Configuration.RequestIdToken = true;

    GoogleSignIn.DefaultInstance.SignIn().ContinueWithOnMainThread(task =>
    {
        if (task.IsFaulted)
        {
            Debug.LogError("Google Sign-In Failed");
        }
        else if (task.IsCanceled)
        {
            Debug.Log("Google Sign-In Canceled");
        }
        else
        {
            // Google에서 획득한 ID 토큰으로 Firebase 인증 시도
            StartCoroutine(SignInWithGoogleCoroutine(task.Result.IdToken));
        }
    });
}

/*
 * [Google 인증] Google ID 토큰을 Firebase Credential로 변환하여 로그인
 */
private IEnumerator SignInWithGoogleCoroutine(string idToken)
{
    // 1. Google 인증 정보를 Firebase용 Credential로 변환
    AuthCredential credential = GoogleAuthProvider.GetCredential(idToken, null);

    // 2. 변환된 Credential로 Firebase 로그인
    Task<AuthResult> loginTask = auth.SignInWithCredentialAsync(credential);
    yield return new WaitUntil(() => loginTask.IsCompleted);

    if (loginTask.Exception != null)
    {
        HandleAuthError(loginTask.Exception);
    }
    else
    {
        user = loginTask.Result.User;
        confirmText.text = $"Google Login Success: {user.DisplayName}";
        _startButton.interactable = true;
        
        // 소셜 로그인은 이미 닉네임이 있으므로 필드에 자동 채우기
        _nicknameField.text = user.DisplayName;
    }
}

 

기존 코드에 이 코드를 추가하면 된다.

구글 로그인에 사용되는 각 주요 메서드들은 다음과 같다.

 

// 1. Google 로그인 설정 (Configuration) : Google SDK에 인증 요청 사양을 전달.
Configuration configuration = new Configuration
{
    WebClientId = "YOUR_WEB_CLIENT_ID", // Firebase와 연동하기 위한 필수 키
    RequestIdToken = true,               // Firebase 인증에 필요한 ID 토큰 요청 여부
    RequestEmail = true                  // 유저의 이메일 정보 접근 권한 요청
};

// 2. Google 계정 선택 및 인증 (SignIn) : 
// 비동기(Task)로 동작하며, 성공 시 유저의 신원 정보가 담긴 Task 결과를 반환.
GoogleSignIn.DefaultInstance.SignIn().ContinueWithOnMainThread(task => {
    // task.Result를 통해 GoogleSignInUser 객체에 접근 가능
});

// 3. Firebase용 자격 증명 생성 (GetCredential)
// Google로부터 받은 ID 토큰을 Firebase 시스템이 인식할 수 있는 'Credential'로 변환
// idToken: GoogleSignInUser로부터 획득한 고유 토큰
AuthCredential credential = GoogleAuthProvider.GetCredential(idToken, null);

// 4. 자격 증명을 이용한 최종 로그인 (SignInWithCredentialAsync)
// 변환된 Credential을 Firebase 서버에 제출하여 최종 세션을 획득
Task<AuthResult> loginTask = auth.SignInWithCredentialAsync(credential);

/* 5. 사용자 정보 참조 (FirebaseUser)
 * 주요 프로필 속성: 
 * - user.UserId: 서비스 내 고유 식별자 (UID)
 * - user.DisplayName: Google 계정에 설정된 이름
 * - user.PhotoUrl: Google 프로필 이미지 경로
 */
FirebaseUser user = loginTask.Result.User;

 

 

여기서 ContinueWithOnMainThread를 쓰는 이유에 대해 의문을 품을 수 있다.

 

ContinueWith : 작업 완료 후 백그라운드 스레드에서 후속 로직을 실행 → Unity에서 에러 발생

ContinueWithOnMainThread : 작업 완료 후 실행 흐름을 유니티 메인 스레드로 강제 전환하여 안전하게 실행

 

간단하게 Unity는 라이프사이클 정책상 싱글쓰레드로 동작하기 때문에 ContinueWithOnMainThread를 사용하는 것이다.

 

 

끝끝끝

'Unity' 카테고리의 다른 글

Unity : 같은 PC에서 클라이언트 여러개 실행시 멈추는 현상 (Firestore)  (0) 2026.02.08
Unity : 관리자 콘솔 구현 및 프리징 현상 개선  (0) 2026.02.08
Unity Network : Photon Pun2 - PhotonView, IPunObservable, RPC  (0) 2026.01.07
Unity Network : Photon Pun 2 - Lobby / Room  (0) 2026.01.07
Unity UI: 코드로 레이아웃 제어 vs 프리팹 기반 구성  (0) 2026.01.05
'Unity' 카테고리의 다른 글
  • Unity : 같은 PC에서 클라이언트 여러개 실행시 멈추는 현상 (Firestore)
  • Unity : 관리자 콘솔 구현 및 프리징 현상 개선
  • Unity Network : Photon Pun2 - PhotonView, IPunObservable, RPC
  • Unity Network : Photon Pun 2 - Lobby / Room
ellug
ellug
Web / App / Game Dev
  • ellug
    dev.ellug
    ellug
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • Javascript (React, Next) (1)
      • C# (66)
      • Graphics (1)
      • Unity (25)
      • 프로그래머스 (0)
        • Lv.0 (0)
        • Lv.1 (0)
        • Lv.2 (0)
        • Lv.3 (0)
      • AI Agent (0)
      • StableDiffusion (0)
      • ETC (1)
      • 잡담 (0)
      • 유머 (0)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    useState
    function
    최적화
    스택
    알고리즘
    Photon
    터미널
    delegate
    unity
    게임
    inputsystem
    큐
    네트워크
    C#
    추상 클래스
    Design Pattern
    Network
    콘솔
    class
    interface
    struct
    firebase
    클래스
    list
    유니티
    자료구조
    stack
    Abstract
    Queue
    console
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
ellug
Unity : Firebase 등록 및 Auth로 (이메일/소셜) 로그인 구현
상단으로

티스토리툴바