Android Studio

Kotlin - Firebase Auth로 간단한 로그인 구현

내손은개발 🐾 2024. 3. 8. 21:01

 

실제 이메일은 아니고 앱 내에서 가상 이메일과 비밀번호로 회원가입하고 입력한 정보를 통해 로그인할 수 있는 기능을 구현해볼 것이다.

1) 일단 Firebase에서 Authentication 기능을 추가.

사진처럼 Authentication에는 다양한 인증으로 로그인이 가능하다.

이메일/비밀번호만 구현.

 

추가를 하면 이렇게 나온다. 네 Firebase에서는 끝이다.

2) 이제 auth를 implementation.

 

FirebaseUI로 손쉽게 Android 앱에 로그인 추가

의견 보내기 FirebaseUI로 손쉽게 Android 앱에 로그인 추가 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. FirebaseUI는 Firebase 인증 SDK를 바탕으로 구축된 라이브

firebase.google.com

공식문서에서 버전을 확인할 수 있다.

 

 

3) 로그인 화면 제작.

이메일과 비밀번호를 받을 editText를 2개만들어주고

로그인과 회원가입 버튼 2개를 만들어줬습니다.

 

EditText

이메일 : emailEditText

비밀번호 : passwordEditText

 

Button

로그인 : signInOutButton

회원가입 : signUpButton

 

4) 코드 작성

회원가입과 로그인을 구현하면 된다.

정말 쉽게도 사용할 코드가 그대로 나와있다.

 

 

 

Android에서 Firebase 인증 시작하기  |  Firebase Authentication

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Android에서 Firebase 인증 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하

firebase.google.com

 

이정도면 그냥 공식문서주소만 올리면 될 정도이다..

그래도 코드 설명을 해보자면

 

4_1) 회원가입

회원가입 버튼을 눌렀을 경우로 시작하고

이메일과 비밀번호는 필수로 입력 받아야한다.

    private fun setupSignUpButton() {

        binding.signUpButton.setOnClickListener {
            val email = binding.emailEditText.text.toString()
            val password = binding.passwordEditText.text.toString()

            if (email.isEmpty() || password.isEmpty()) {
                Snackbar.make(binding.root, "이메일 또는 패스워드를 입력해주세요.", Snackbar.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            Firebase.auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        Snackbar.make(binding.root, "회원가입에 성공했습니다.", Snackbar.LENGTH_SHORT).show()
                        initViewToSignInState()
                    } else {
                        Snackbar.make(binding.root, "회원가입에 실패했습니다.", Snackbar.LENGTH_SHORT).show()
                    }
                }.addOnFailureListener {
                    it.printStackTrace()
                }
        }
    }

 

 

코드 설명

더보기
val email = binding.emailEditText.text.toString()
val password = binding.passwordEditText.text.toString()

이메일과 비밀번호를 Firebase에 넘겨주기 위해서 저장한다.

 

Firebase.auth.createUserWithEmailAndPassword(email, password)
	.addOnCompleteListener { task ->
		if (task.isSuccessful) {
			Snackbar.make(binding.root, "회원가입 성공!!", Snackbar.LENGTH_SHORT).show()
			initViewToSignInState()
		} else {
			Snackbar.make(binding.root, "회원가입 실패!!", Snackbar.LENGTH_SHORT).show()
		}
	}.addOnFailureListener {
		it.printStackTrace()
	}

이 부분은 공식문서에서 Snackbar만 추가해준 정도이다.

 

 

if (email.isEmpty() || password.isEmpty()) {
	Snackbar.make(binding.root, "이메일 또는 패스워드를 입력해주세요.", Snackbar.LENGTH_SHORT).show()
	return@setOnClickListener
}

예외처리가 필요하다. 이메일이나 패스워드는 반드시 입력해야하는데 입력하지 않느면 입력하라고 Snackbar를 띄운다.

 

 

 

 

 

 

4_2) 로그인

로그인이 있다면 로그아웃도 있어야하죠!

    private fun setupSignInOutButton() {
        binding.signInOutButton.setOnClickListener {
            val email = binding.emailEditText.text.toString()
            val password = binding.passwordEditText.text.toString()

            if (Firebase.auth.currentUser == null) {
                // 로그인
                if (email.isEmpty() || password.isEmpty()) {
                    Snackbar.make(binding.root, "이메일 또는 패스워드를 입력해주세요.", Snackbar.LENGTH_SHORT).show()
                    return@setOnClickListener
                }

                Firebase.auth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful) {
                            initViewToSignInState()
                        } else {
                            Snackbar.make(binding.root, "로그인에 실패했습니다. 이메일 또는 패스워드를 확인해주세요.", Snackbar.LENGTH_SHORT).show()
                        }
                    }
            } else {
                Firebase.auth.signOut()
                initViewToSignOutState()

            }
        }
    }

    private fun initViewToSignInState() {
        binding.emailEditText.setText(Firebase.auth.currentUser?.email)
        binding.emailEditText.isEnabled = false
        binding.passwordEditText.isVisible = false
        binding.signInOutButton.text = getString(R.string.signOut)
        binding.signUpButton.isEnabled = false
    }

    private fun initViewToSignOutState() {
        binding.emailEditText.text.clear()
        binding.emailEditText.isEnabled = true
        binding.passwordEditText.text.clear()
        binding.passwordEditText.isVisible = true
        binding.signInOutButton.text = getString(R.string.signIn)
        binding.signUpButton.isEnabled = true
    }

 

코드 설명

더보기
val email = binding.emailEditText.text.toString()
val password = binding.passwordEditText.text.toString()

 똑같이 이메일과 비밀번호를 받아오고

 

 

if (Firebase.auth.currentUser == null) {
// 로그인
	...생략..

Firebase.auth.signInWithEmailAndPassword(email, password)
	.addOnCompleteListener { task ->
		if (task.isSuccessful) {
			initViewToSignInState()
		} else {
			Snackbar.make(binding.root, "로그인에 실패했습니다. 이메일 또는 패스워드를 확인해주세요.", Snackbar.LENGTH_SHORT).show()
			}
	}
} else {
	Firebase.auth.signOut()
	initViewToSignOutState()
}

 첫번째 줄에 Firebase.auth.currentUser == null 이면 auth에 저장된 회원정보가 없다면 로그인을 하는 과정이고

아니면 로그아웃을 하는 과정이다.

 

Firebase.auth.signInWithEmailAndPassword(email, password)를 통해서 이메일과 비밀번호를 넘겨준다.

그 뒤 task가 isSuccessful이면 로그인하게 한다.

 

Firebase.auth.signOut()을 받아서 로그아웃을 한다.

 

 

 로그인의 경우 이메일을 비활성화(isEnabled), 비밀번호는 isVisible을 false로 안보이게한다.

    private fun initViewToSignInState() {
        binding.emailEditText.setText(Firebase.auth.currentUser?.email)
        binding.emailEditText.isEnabled = false
        binding.passwordEditText.isVisible = false
        binding.signInOutButton.text = getString(R.string.signOut)
        binding.signUpButton.isEnabled = false
    }

 또한 로그인이라는 text를 로그아웃으로 바꾼다.

 

    private fun initViewToSignOutState() {
        binding.emailEditText.text.clear()
        binding.emailEditText.isEnabled = true
        binding.passwordEditText.text.clear()
        binding.passwordEditText.isVisible = true
        binding.signInOutButton.text = getString(R.string.signIn)
        binding.signUpButton.isEnabled = true
    }

 로그아웃은 반대로~

 

 

 

4_3) 로그인 유지

    override fun onStart() {
        super.onStart()

        if(Firebase.auth.currentUser == null) {
            initViewToSignOutState()
        } else {
            initViewToSignInState()
        }
    }

음 예를들어 설명하면 다른 화면으로 이동하거나 view의 상태가 초기화되었을 때가 있는데 이를 방지하는 코드이다.

 

 

 

 

 

전체코드

더보기
import android.os.Bundle
import android.view.View
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import com.example.kotlin_sai.databinding.FragmentAuthBinding
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase

class AuthFragment: Fragment(R.layout.fragment_auth) {
    private lateinit var binding: FragmentAuthBinding
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding = FragmentAuthBinding.bind(view)

        setupSignUpButton()
        setupSignInOutButton()
    }

    override fun onStart() {
        super.onStart()

        if(Firebase.auth.currentUser == null) {
            initViewToSignOutState()
        } else {
            initViewToSignInState()
        }
    }


    private fun setupSignUpButton() {

        binding.signUpButton.setOnClickListener {
            val email = binding.emailEditText.text.toString()
            val password = binding.passwordEditText.text.toString()

            if (email.isEmpty() || password.isEmpty()) {
                Snackbar.make(binding.root, "이메일 또는 패스워드를 입력해주세요.", Snackbar.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            Firebase.auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        Snackbar.make(binding.root, "회원가입 성공!!", Snackbar.LENGTH_SHORT).show()
                        initViewToSignInState()
                    } else {
                        Snackbar.make(binding.root, "회원가입 실패!!", Snackbar.LENGTH_SHORT).show()
                    }
                }.addOnFailureListener {
                    it.printStackTrace()
                }
        }
    }

    private fun setupSignInOutButton() {
        binding.signInOutButton.setOnClickListener {
            val email = binding.emailEditText.text.toString()
            val password = binding.passwordEditText.text.toString()

            if (Firebase.auth.currentUser == null) {
                // 로그인
                if (email.isEmpty() || password.isEmpty()) {
                    Snackbar.make(binding.root, "이메일 또는 패스워드를 입력해주세요.", Snackbar.LENGTH_SHORT).show()
                    return@setOnClickListener
                }

                Firebase.auth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful) {
                            initViewToSignInState()
                        } else {
                            Snackbar.make(binding.root, "로그인에 실패했습니다. 이메일 또는 패스워드를 확인해주세요.", Snackbar.LENGTH_SHORT).show()
                        }
                    }
            } else {
                Firebase.auth.signOut()
                initViewToSignOutState()

            }
        }
    }

    private fun initViewToSignInState() {
        binding.emailEditText.setText(Firebase.auth.currentUser?.email)
        binding.emailEditText.isEnabled = false
        binding.passwordEditText.isVisible = false
        binding.signInOutButton.text = getString(R.string.signOut)
        binding.signUpButton.isEnabled = false
    }

    private fun initViewToSignOutState() {
        binding.emailEditText.text.clear()
        binding.emailEditText.isEnabled = true
        binding.passwordEditText.text.clear()
        binding.passwordEditText.isVisible = true
        binding.signInOutButton.text = getString(R.string.signIn)
        binding.signUpButton.isEnabled = true
    }

}

 

결과