24.02.23 FireBase로 로그인 회원가입하기

KSang·2024년 2월 23일
0

TIL

목록 보기
69/101

프로젝트를 기획했는데, 서버가 필요하다.

팀프로젝트를 원하는 인원들끼리 매칭하고, 팀 결성을 도와주는 앱을 만들건데

게시물 작성, 유저 정보등 데이터를 저장해야한다.

그런데 팀에 백엔드 개발자가 없고 전부 안드로이드 개발자 밖에 없다.

그러면 서버를 어떻게 해결 할까?

안드로이드에선 FireBase를 지원한다.

서버에 대한 지식이 없어도 간단하게 서버를 구축할수 있기 때문에 FireBase를 공부하기로 했다.

FireBase에서 우리 프로젝트에서 쓸건, 계정 정보를 관리하는 Auth, 데이터를 저장하는 FireStore, 채팅처럼 실시간으로 변하는 데이터를 감지할 realTimeDataBase,
이미지를 저장할 Store를 사용할 것이다.

오늘은 Auth로 사용자의 로그인을 관리하는 부분을 정리할 것이다.

Authentication

파이어 베이스에서 사용자 인증을 관리하는 서비스다.

사용하려면 이메일과 비밀번호 기반 인증, google, facebook, twitter 등 다양한 외부 인증 제공 업체를 통한 인증 또는 전화번호 인증 등을 손쉽게 구현할 수 있다.

Firebase Authentication은 사용자 관리를 위한 백엔드 서비스 없이도 안전한 인증 시스템을 빠르게 구축할 수 있게 해준다.

주요 기능

  1. 다양한 인증 방법 지원: 이메일/ 비밀번호 인증, 소셜 미디어 계정을 통한 인증, 전화번호 인증 등 다양한 방법을 지원한다.
  2. 통합된 사용자 관리: Firebase 콘솔을 통해 사용자 계정을 관리할 수 있으며, 사용자의 로그인 상태, 활동등을 추적할 수 있다.
  3. 보안 밑 인증 규칙 설정: Firebase Authentication은 사용자 데이터의 보안을 유지하기 위해 강력한 보안 기능을 제공한다. 인증 규칙을 통해 데이터 접근을 제어할 수 있다.

구현

회원 가입

파이어 베이스에 앱을 프로젝트에 등록을 하고 앱에서 SDK를 추가하면 사용 할 수 있다.

파이어 베이스는 안드로이드에서 메소드를 지원하기 때문에 레트로핏 같은 라이브러리가 없어도 tool창에서 파이어 베이스를 연결하고 손쉽게 구현 할 수 있다.

class AuthRepositoryImpl @Inject constructor(
    private val firebaseAuth: FirebaseAuth,
) : AuthRepository {
    override suspend fun register(email: String, password: String) =
        suspendCoroutine { continuation ->
            firebaseAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        continuation.resume(DataResultStatus.SUCCESS)
                    }
                }
                .addOnFailureListener { e ->
                    if (e is FirebaseAuthException) {
                        val errorCode = e.errorCode
                        continuation.resume(DataResultStatus.FAIL.apply {
                            this.message = errorCode
                        })
                    } else {
                        continuation.resume(DataResultStatus.FAIL.apply {
                            this.message = e.message ?: "Unknown error"
                        })
                    }
                }
        }

우선 계정을 등록하는 부분을 만들었다.

FireAuth를 이용해서 email과 password를 형식에 맞춰서 저장하면된다.

password같은 경우 파이어 베이스에서 6자이상으로 저장해야 된다.

auth에서 createUserWithEmailAndPassword 함수를 사용하면 이메일정보와 패스워드로 계정을 등록할 수 있다.

성공시 addOnCompleteListener 로 구현 되어있는대, task.isSuccessful로 성공과 실패를 구별 할 수 있다.

나는 보다 명확히 구별하기 위해 등록부분 외에는 addOnSuccessListener와, addOnFailureListener로 나눠서 구현했다.

그리고 enum을 이용해서 성공과 실패 했을때 메세지를 반환하게 했다.

로그인

    override suspend fun signIn(email: String, password: String) = suspendCoroutine { continuation ->
        firebaseAuth.signInWithEmailAndPassword(email, password)
            .addOnSuccessListener {
                continuation.resume(DataResultStatus.SUCCESS)
            }
            .addOnFailureListener { e ->
                if (e is FirebaseAuthException) {
                    val errorCode = e.errorCode
                    continuation.resume(DataResultStatus.FAIL.apply {
                        this.message = errorCode
                    })
                } else {
                    continuation.resume(DataResultStatus.FAIL.apply {
                        this.message = e.message ?: "Unknown error"
                    })
                }
            }
    }

로그인 같은 경우에도 등록과 아주 유사하다

auth를 사용하고 signInWithEmailAndPassword를 이용해 로그인 하게 하면 된다.

사용자의 이메일과 패스워드를 받고 저장된 정보가 있는지 확인을 한다.

전부 메소드를 지원해주기 때문에 너무 간단하다.

명칭도 굉장히 직관적이다 생각 들었다.

현재 로그인 유저정보

Auth로 한번 로그인을 하거나 회원가입을 하게 되면 앱 내에서는 자동적으로 로그인 한 상태가 된다.

앱을 껐다 켜도 유지가 된다.

당연히 그런 로그인한 유저의 정보도 얻을 수 가 있다.

auth로 회원가입을 하게 되면 각 유저별로 고유의 키값 uid를 얻을 수 있는데,

이를 통해서 유저의 데이터를 구별하고 불러올 수 있다.

    override suspend fun getCurrentUser(): DataResultStatus {
        return if (firebaseAuth.currentUser != null) {
            DataResultStatus.SUCCESS.apply { message = firebaseAuth.currentUser!!.uid }
        } else {
            DataResultStatus.FAIL.apply {
                this.message = "No user"
            }
        }
    }

굉장히 간단하다.

auth에서 currentUser를 사용하기만 하면 현재 유저의 정보를 가져올 수 있다.

public interface UserInfo {
    @Nullable
    Uri getPhotoUrl();

    @Nullable
    String getDisplayName();

    @Nullable
    String getEmail();

    @Nullable
    String getPhoneNumber();

    @NonNull
    String getProviderId();

    @NonNull
    String getUid();

    boolean isEmailVerified();
}

유저의 정보는 프로필 이미지, 이름, 이메일, 폰 넘버 등등으로 저장되어 있는데

유저 정보를 별도의 엔티티로 따로 저장할 것이기 때문에 저기서 식별자인 uid만 받아오면 된다.


data class UserEntity(
    val uid: String? = "",
    val email: String? = "",
    val name: String? = "",
    val photoUrl: String? = "https://firebasestorage.googleapis.com/v0/b/colink-a7c3a.appspot.com/o/img%2Fic_profile.png?alt=media&token=64207054-6439-4275-b7be-cd13c626f081",
    val phoneNumber: String? = null,
    val level: Int? = 0,
    val mainSpecialty: String? = "",
    val specialty: String? = "",
    val grade: Double? = 5.0,
    val skill: List<String>? = emptyList(),
    val git: String? = null,
    val blog: String? = null,
    val link: String? = null,
    val info: String? = null,
    val registeredDate: String = LocalDateTime.now().convertLocalDateTime(),
    val communication: Float? = null,
    val technicalSkill: Float? = null,
    val diligence: Float? = null,
    val flexibility: Float? = null,
    val creativity: Float? = null,
    val evaluatedNumber: Int = 0,
    val participantsChatRoomIds: List<String>? = emptyList(),
    @get:Exclude @set:Exclude var chatRoomKeyList: List<String>? = null
)

현재 우리 앱에서 필요한 각 유저의 데이터가 이런식으로 구성 되어있으니

uid를 사용해 식별자만 받아오고 그걸 이용해서 유저를 구분, 추가적인 데이터를 저장해 줄 것이다.

그렇기 때문에 결과에서 uid만 빼내서 반환하게 만들었다.

로그아웃

    override suspend fun signOut() {
        FirebaseAuth.getInstance().signOut()
    }

로그인이 자동으로되니 당연히 로그아웃을 하는 방법도 있다.

auth에서 getInstance를 하면 서비스에 접근하기 위한 진입점을 제공하는데 이를 이용해서 로그인을 할 수 있다.

너무나도 직관적이게 signOut을이용하면 로그아웃 처리를 할 수 있게 된다.

그후 사용자는 더 이상 인증되지 않은 상태가 되며, 인증이 필요한 리소스에 접근 할 수 없게된다.

메소드를 지원해줘서 너무나도 직관적이고 손쉽게 서버를 이용할 수 있었다.

NoSql이라 현업에선 잘 안사용하는 걸로 알고 있는데, 이유가 정확히 뭘까?

다음에 한번 알아 봐야 겠다.

0개의 댓글