[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 24회차 미션 시작합니다.

03. Firebase 네트워크 - 02, 03 챕터를 진행합니다.




Firebase 설정하기

1. Firebase에 가입하기

기본 Spark 무료 요금제이며, 실시간 데이터베이스의 사용량이 늘어나면 사용 제한이 걸리는 방식. Blaze 유료 종량제도 10G 까지는 과금되지 않음.




2. 프로젝트 추가하기.

콘솔로 이동 - 사용중인 프로젝트 목록이 나옵니다.

프로젝트를 "FastCampusDev"라는 이름으로 생성합니다. Google 애널리틱스 구성도 사용으로 하고, 다른 것들은 기본으로 하여 생성합니다.





3. 앱 추가하기: Unity -> Android

관리 메인 화면에서 "Unity" 앱 생성을 클릭하여 사용할 앱을 등록합니다.

"[v] Register as Android app"을 선택하고 Android 패키지 이름을 "comfastcampusdev.firebase"라고 작성합니다.
앱 닉네임은 "FastCampus Android Firebase"라고 작성합니다.





4. 구성 파일 다운로드

Firebase 콘솔에서도 다시 다운로드 가능합니다. 다운로드 파일을 Unity의 "Assets"에 적용하라는 안내도 보여주고 있네요.

 


google-services.json 파일을 다운로드 하고 편집기에서 열어서 살펴봅니다.


firebase_url이 중요합니다. firebase_url을 이용하여 database나 cloud storage등을 접근하여 사용하게 됩니다.
storage_bucket은 cloud storage에 파일 접근을 할 수 있게 해주는 주소입니다. 밑에 내용들은 Mobile에서 사용되는 Client 관련 정보라고 보면 됩니다.



해당 파일을 Unity Project의 "Assets"에 추가하여 줍니다.




5. Firebase SDK 다운로드

마찬가지로 Firebase Console에서 언제든 다운로드 가능합니다.




위의 그림과 같이 사용자 인증 설정하기를 진행해 주어야 합니다.

이메일/비밀번호, 전화, Google, Play게임, 게임 센터, Facebook, Twitter, GitHub, Yahoo, Microsoft, Apple, 익명 등 다양한 방법의 로그인을 제공합니다. 대단합니다. 항상 반복적으로 개발해와야 했던 내용이었 것만... 어느 반복이 너무 싫은 천재 개발자의 아이디어에서 시작된 것 같네요..

여기서는 테스트를 위해 "이메일/비밀번호" 방식을 "사용 설정"으로 변경하고 진행합니다.



Unity SDK 설치하기입니다.

Unity 상단 메뉴의 "Assets - Import Package - Custom Package..."를 클릭하여 Import 탐색기 다이알로그가 나타납니다.

여기서 아까 다운받은 firebase_unity_sdk_x.xx.x 폴더로 이동하면 dotnet3, dotnet4 폴더를 볼 수 있고, dotnet4로 진입합니다.

꼭 설치해야 하는 것은 FirebaseAnalytics입니다. 해당 기본 패키지를 설치합니다.

그리고 사용자 인증을 진행할 것이기 때문에 FirebaseAuth 패키지도 설치해줍니다.




사용자 인증 관련 주요 함수들입니다.

Singleton Pattern으로 구현되어 있기 때문에 DefaultInstance를 가져다가 사용하면 됩니다.

StreamingAssets 폴더에 google-services-desktop 파일이 생성되어 있다면 잘 된 것입니다.





Unity에서 사용할 Login UI입니다. 시간 관계상 구성된 상태로 진행합니다.

Email & Password 방식으로 로그인하고, 신규 가입이나 로그아웃 버튼 등이 추가된 상태입니다.


이제 인증을 위한 스크립트를 생성합니다.

public class FirebaseAuthController
{
    // Singletone
    private static FirebaseAuthController instance = null;
    public static FirebaseAuthController Instance {
        get {
            if (instance == null) instance = new FirebaseAuthController();
            return instance;
        }
    }
    
    private FirebaseAuth auth;
    private FirebaseUser user;
    
    private string displayName;
    private string emailAddress;
    private Uri photoUrl;
    
    public string UserId => user?.UserId ?? string.Empty;
    public string DisplayName => displayName;
    public string EmailAddress => emailAddress;
    public Uri PhotoUrl => photoUrl;
    
    public Action<bool> OnChangedLoginState;
    
    public void InitializeFirebase() {
        auth = FirebaseAuth.DefaultInstance;
        auth.StateChanged += OnAuthStateChanged;
        OnAuthStateChanged(this, null);
    }
    
    public void CreateUser(string email, string password) {
        auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
            if (task.IsCanceled) { Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled."); return; }
            if (task.IsFaulted) { // 에러 발생된 경우 처리
                Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
                int errorCode = GetFirebaseErrorCode(task.Exception);
                switch (errorCode) {
                case (int)AuthError.EmailAlreadyInUse:
                    Debug.LogError("Email Already In Use");
                    break;
                case (int)AuthError.InvalidEmail:
                    Debug.LogError("Invalid Email");
                    break;
                case (int)AuthError.WeakPassword:
                    Debug.LogError("Weak Password");
                    break;
                }
                return;
            }
            
            FirebaseUser newUser = task.Result; // 성공 결과
            Debug.LogFormat("Frebase user created successfully: {0} ({1})", newUser.DisplayName, newUser.UserId);
        });
    }
    
    public void SignIn(string email, string password) {
        auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
            if (task.IsCanceled) { Debug.LogError("SignInWithEmailAndPasswordAsync was canceled."); return; }
            if (task.IsFaulted) { // 에러 발생된 경우 처리
                Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
                int errorCode = GetFirebaseErrorCode(task.Exception);
                switch (errorCode) {
                case (int)AuthError.WrongPassword:
                    Debug.LogError("Wrong Password");
                    break;
                case (int)AuthError.UnverifiedEmail:
                    Debug.LogError("Unverified Email");
                    break;
                case (int)AuthError.InvalidEmail:
                    Debug.LogError("Invalid Email");
                    break;
                }
                return;
            }
            
            FirebaseUser newUser = task.Result; // 성공 결과
            Debug.LogFormat("Frebase user signed in successfully: {0} ({1})", newUser.DisplayName, newUser.UserId);
        });
    }
    
    public void SignOut() {
        auth.SignOut();
    }
    
    // Firebase의 exception id 가져오기
    private int GetFirebaseErrorCode(AggregateException exception) {
        FirebaseException firebaseException = null;
        foreach (Exception e in exception.Flatten().InnerExceptions) {
            firebaseException = e as FirebaseException; // Firebase Exception인 경우만 처리
            if (firebaseException != null) break;
        }
        return firebaseException?.ErrorCode ?? 0;
    }
   
    private void OnAuthStateChanged(object sender, EventArgs eventArgs) {
        if (auth.CurrentUser != user) {
            bool signedIn = (user != auth.CurrentUser && auth.CurrentUser != null);
            if (!signedIn && user != null) {
                Debug.Log("Signed out: " + user.UserId);
                OnChangedLoginState?.Invoke(false); // 로그아웃 이벤트 전달
            }
            
            user = auth.CurrentUser;
            if (signedIn) {
                Debug.Log("Signed in: " + user.UserId);
                displayName = user.DisplayName ?? string.Empty;
                emailAddress = user.Email ?? string.Empty;
                photoUrl = user.PhotoUrl ?? null;
                OnChangedLoginState?.Invoke(true); // 로그인 이벤트 전달
            }
        }
    }
}



public class FirebaseAuthUIController : MonoBehaviour
{
    public TMP_InputField emailInputField;
    public TMP_InputField passwordInputField;
    public TMP_Text outputText;
    
    void Start() {
        FirebaseAuthController.Instance.OnChangedLoginState += OnChangedLoginState;
        FirebaseAuthController.Instance.InitializeFirebase();
    }
    
    public void CreateUser() {
        string email = emailInputField.text;
        string password = passwordInputField.text;
        FirebaseAuthController.Instance.CreateUser(email, password);
    }
    
    public void SignIn() {
        string email = emailInputField.text;
        string password = passwordInputField.text;
        FirebaseAuthController.Instance.SignIn(email, password);
    }
    
    public void SignOut() {
        FirebaseAuthController.Instance.SignOut();
    }
    
    private void OnChangedLoginState(bool signedIn) {
        outputText.text = signedIn ? "Signed in: " : "Signed out: ";
        outputText.text += FirebaseAuthController.Instance.UserId;
    }
}





Unity Canvas에서 위와 같이 설정해 줍니다.




Unity 플레이를 진행하여 시작합니다.

eMail과 Password를 입력하고 "Create User"를 클릭하면 "Signed in: qFNEYxxxxxxxx"라는 사용자 아이디를 볼 수가 있는데, Hash 암호화가 되어 있기 때문에 특수 문자열처럼 표시되었습니다.



Firebase Console로 접근하여 보면 생성된 계정 정보를 확인할 수 있습니다.

그리고 동일 Email 생성 에러 및 암호 에러 등의 테스트를 진행해보면 Firebase를 통한 로그인 시스템이 정상적으로 잘 동작함을 확인할 수 있습니다.

 

회원 가입 및 로그인 등의 시스템이 간단하던 시절에는 개발시 문제가 되지 않았지만 지금처럼 연동 로그인이나 보안 등 복잡한 시스템이 되어가면서는 간단하지 않은 시스템이 되어 고민하게되는 부분이 많게 되는데, 이처럼 자동화되니 참 좋은 세상이네요. 물론 사용량에 따라 돈을 내야할 수 있겠지만 말이지요. ㅎㅎ





<위의 코드들은 제가 보면서 주요한 함수, 코드를 확인하기 위해 타이핑한 용도로, 전체 소스코드가 아님에 주의해 주세요. 전체 코드는 교육 수강을 하면 완벽하게 받으실 수가 있답니다 ^^>

패스트캠퍼스 - 올인원 패키지 : 유니티 포트폴리오 완성 bit.ly/2R561g0

 

유니티 게임 포트폴리오 완성 올인원 패키지 Online. | 패스트캠퍼스

게임 콘텐츠 프로그래머로 취업하고 싶다면, 포트폴리오 완성은 필수! '디아블로'와 '배틀그라운드' 게임을 따라 만들어 보며, 프로그래머 면접에 나오는 핵심 개념까지 모두 잡아 보세요!

www.fastcampus.co.kr

 

+ Recent posts