본문 바로가기

TIL

[TIL] Kotlin Firebase Authentication [ 1 ] 회원가입 DB 저장하기

Kotlin Firebase Authentication [ 1 ] 회원가입 DB 저장하기

 

 

 

 

[ 0 ] Firebase Project 생성하기

 

[ 0 - 1 ] Firebase Console에 접속 후 Project를 생성해준다.

 

Firebase | Google’s Mobile and Web App Development Platform

Discover Firebase, Google’s mobile and web app development platform that helps developers build apps and games that users will love.

firebase.google.com

 

 

Analytics를 활성화 하게 될 경우 사용자의 동작 및 성능에 대한 데이터를 자동으로 수집하고 분석해주는 기능 등의 부가적으로 여러 기능들을 제공한다. 아래에 간단하게 설명된 기능 외에도 여러 기능들이 있다.

  • 이벤트 트리거
    • 앱 내에서 발생하는 사용자 이벤트 ( 버튼 클릭, 화면 전환 등 ) 을 추적할 수 있다. 이벤트 추적을 통해 앱의 특정 기능 또는 사용자 상호작용에 대한 데이터를 수집하고 분석할 수 있다.
  • 사용자 속성 관리
    • 사용자에 대한 추가 정보( ID, 나이, 성별 등 ) 을  저장하여 세분화된 분석과 타겟팅을 위한 속성으로 관리할 수 있다.
  • 문제 보고서
    • Firebase Analytics와 통합된 Crashlytics를 사용하여 앱의 충돌 데이터를 수집하고 분석할 수 있어 충돌의 원인을 확인하여 충돌 원인 해결에 용이하다.
  • A/B 테스팅
    • 기존 데이터와 별개로 특정 사용자 그룹에 별도로 다른 요소들 ( UI 디자인, 콘텐츠, 버튼 위치 등 ) 을 적용해서 각각의 다른 요소들에 대한 모니터링을 통해 데이터를 수집하여 비교를 할 수 있도록 한다.

 

 

[ 0 - 2 ] Firebase Android 기본 설정

  • Authentication의 경우 Google Login을 지원할 경우 SHA - 1 인증키가 필요하므로 Android Studio 프로젝트를 생성하고 SHA -1 Key를 발급해서 적용해보도록 하자.

 

SHA - 1 Key 발급 방법

Ctrl 키 2번 누르면 Run Anything 명령창에 gradle signingReport 입력 후 Enter 

 

  • SHA1 Key 복사해서 Firebase 설정 sha-1 key란에 입력해주기.

 

 

 

Firebase Project 과 Android Studio Project 생성이 완료 되었으면 Firebase Console의 아래에 표시한 android 아이콘을 클릭해서 Firebase Project에 Android를 적용해주기

 

Android 앱에 Firebase 추가

패키지 이름

  • Android 아이콘 클릭 시 다음과 같은 Android 앱 설정란이 나온다. 생성 해둔 프로젝트 명, SHA - 1 Key 입력해주고 2. 구성파일 다운로드 후 프로젝트 app 디렉토리( 폴더 ) 안에 넣어준다.

좌, 우 둘중 편한 방법으로 다운로드 받은 json 파일을 넣어주면 된다.

  • 3. Firebase SDK 추가는 뒤에서 추가로 설정할 것이므로 일단은 건너뛰자.

 

 

 

 

 

Authentication 추가 & 설정

  • 프로젝트 대쉬보드 또는 제품 메뉴에서 Authentication 시작하기

 

 

 

 

Firebase Authentication Sign-in method 추가

  • Authentication 의 sign-in method 탭에서 원하는 로그인 형식을 지정해줄 수 있다.
  • Email, Password 를 통해 회원가입 할 수 있도록 Firebase Authentication 의 SIgn-In method 의 이메일 / 비밀번호 로그인 메소드를 사용 설정 체크해주도록 하자.

 

 

 

 

 

Firebase 콘솔 설정 끝


 

 

 

[ 1 ]  App 프로젝트 구성하기

   build.gralde 및 Manifest에서 프로젝트 설정을 할 때, build.gradle dependency 적용 방법이 BoM플랫폼을 통해 적용하는 방법과 Android Tools의 Firebase 탭을 통한 SDK 적용하는 방법이 있다. 아래에 주의점을 확인하고 편한 방법으로 선택하면 될 것 같다.

  • Android Studio의 Tools → Firebase를 통해 SDK를 추가한 경우 BoM 플랫폼을 통한 버전 관리가 지원되지 않는 firebase service의 자체적인 버전이 들어가기 때문에 auth, database 각각의 Service마다의 버전 관리가 필요해진다.
  • BoM 플랫폼으로 적용하지 않고 Android Tools를 통해 SDK 를 적용하는 것은 당장 적용이 편할 수 있으나 나중에 귀찮아 지는 것 같다.

 

 

BoM 플랫폼으로 적용하기

아래 링크에서 BoM 플랫폼에 대한 추가 정보 확인가능.

 

Android 및 Firebase 자세히 알아보기  |  Firebase for Android

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

firebase.google.com

dependencies {

    implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    implementation("com.google.firebase:firebase-analytics-ktx")
    implementation("com.google.firebase:firebase-auth-ktx")
    
    ...
    
}

 

Firebase Tools로 설정하는 방법
  • [ 0 - 2 ] 에서 FirebaseProject json 파일을 정상적으로 해당 프로젝트에 app File에 넣거나, Tools의 Firebase에서 Connect 해주는 방법도 있다.

Android Studio 상단에 Tools → Firebase 클릭

 

 

Authenticate using Google 선택

 

 

② Add the Firebase Authentication SDK to your app 클릭

Firebase가 정상적으로 App 프로젝트 안에 추가 되었다면 ① 에 Connect to Firebase가 ✅Connected 로 보여질 것 이다.

 

 

이번 프로젝트는 BoM플랫폼을 통한 버전 관리를 적용할 것이다.

 

build.gradle.(프로젝트)
plugins {
    ...
    id("org.jetbrains.kotlin.android") version "1.9.10" apply false
    id("com.google.gms.google-services") version "4.4.0" apply false
}
  • google-services Plugin 추가

 

build.gradle( module )
plugins {
    ...
    id("kotlin-android")
    id("com.google.gms.google-services")
}

dependencies {

    ...

    // Firebase
    implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    implementation("com.google.firebase:firebase-auth-ktx")


}
  • Module의 build.gradle에도 google-services 플러그인을 추가해주고 dependencies에 firebase-bom 과 auth, ui-auth를 추가해준 뒤 sync now

 

 

Manifest
  • INTERNET Permission 적용해주기
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />
    <application

       .. >

 

 

CLI - 선택사항 ( Node.js 등 백엔드 의 지식이 필요해보여 이번 글에서는 다루지 못함 )

  • Codelap 예제를 학습하다가 당장 사용하지도 못하는 기능인 줄 모르고 다운받고 설정까지는 해놓았는데  배경 지식이 부족해서 추후에 시도해 볼 예정
참고용 Firebase CLI 블로그 글
 

Firebase 사용 방법

이 gist 에서는 firebase 의 feature 중 hosting 및 functions 을 이용하기 위한 시작과정을 설명합니다.https://firebase.google.com/, https://firebase.google.com/docs/, h

velog.io

  • Google Codelap 으로 예제 생성을 하다가 CLI 이라는 것이 있길래 추가해보았는데 개발단계에서 필요한 것으로 보이지 않는다는 의견이 있어서 추후에 백엔드 공부를 하게될 때 건드리지 않을까 싶다...
  • 위에 블로그는 CLI에 대해서 추가적으로 학습하고 싶으면 참조하기

 

 

LogInActivity

 

  • LogIn Activity를 생성해준 뒤, Manifest에서 시작 Activity를 LogInActivity로 설정해준다
        <activity
            android:name=".LogInActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  • 회원가입, 로그인 기능 구현을 완료 한 뒤에는 앱을 실행하면 최초로 시작되는 LoginActivity에 onStart에서 기존에 로그인 했던 유저 정보를 받아서, 유저 정보가 있다면 MainActivity가 실행되는 로직을 추가할 것이다.
  • LogInActivity의 경우 이메일 로그인, SNS 로그인 등의 로그인 옵션을 선택할 수 있도록 해주고 Email,Password를 통한 로그인, 회원가입을 진행하기 위해 LogInFragment, SignUpFragment를 생성해준다.

 

LogInActivity 전체 코드

  • 현재는 Email, Password 로그인 기능만 추가 된 코드 
class LogInActivity : AppCompatActivity() {
    private lateinit var binding: ActivityLogInBinding

    private lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        auth = Firebase.auth
        binding = ActivityLogInBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnLogin.setOnClickListener {
            supportFragmentManager.beginTransaction()
                .add(R.id.login_frame_layout,LoginFragment())
                .commit()
        }
    }


    override fun onStart() {
        super.onStart()
        if (auth.currentUser != null){
            startActivity(Intent(this,MainActivity::class.java))
            finish()
            return
        }
    }
}

 

 

LogInFragment [ 1 ]

 

  • FirebaseAuth 객체 정의 및 초기화, Binding 적용.
  • 아직 회원가입 기능을 제공하지 않으므로, 회원가입 Fragment로 이동하는 Btn 클릭 리스너만 생성해주고 SignUpFragment로 넘어간다
class LoginFragment : Fragment() {

    private var _binding: FragmentLoginBinding? = null
    private val binding get() = _binding!!

    private lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        auth = Firebase.auth

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentLoginBinding.inflate(inflater, container, false)

        binding.signUpBtn.setOnClickListener {
            parentFragmentManager.beginTransaction().replace(R.id.login_frame_layout,SignUpFragment()).addToBackStack(null).commit()
        }


        return binding.root
    }
}

 

 

SignUpFragment

 

 private fun createAccount(email: String, password: String) {
        if (email.isNotEmpty() && password.isNotEmpty()) {
            auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        val intent = Intent(activity, MainActivity::class.java)
                        startActivity(intent)
                        requireActivity().finish()
                    } else {
                        Toast.makeText(requireContext(), " 회원 정보를 알맞게 다시 입력해주세요 ",Toast.LENGTH_SHORT).show()
                    }
                }
            Log.d("xxxx", "createAccount Successful")
        }
    }
  • 먼저 createAccount 함수를 정의해주고 onViewCreated 내부의 회원가입 버튼 이벤트로 지정해주도록 하자.
  • email, password를 파라미터로 받는 createAccount 함수를 정의해주고 함수 내부에는 auth.createUserWithEmailAndPassword 메서드를 통해 파라미터로 받은 Email, Password로 FirebaseAuth에 회원 정보를 추가해주도록 한다.
  • addOnCompleteListener는 auth.create ~ 함수가 실행 되었을 때 별도로 로직을 추가할 수 있도록 해준다. 해당 코드에서는 회원 정보가 정상적으로 FirebaseAuth에 추가 되었을 경우, 현재 LoginActivity를 종료하고 MainActivity를 실행할 수 있도록 해준다.
  • auth.create ~ 메서드를 통해 회원정보를 생성할 경우 자동으로 해당 FirebaseAuth객체의 currentUser 값이 마지막으로 추가된 회원정보로 적용된다.

 

SignUpFragment 전체 코드

  • onViewCreated의 ClickListener 내부에서 유효검사 처리를 해주면 된다.
class SignUpFragment : Fragment() {
    private lateinit var auth: FirebaseAuth
    private var _binding: FragmentSignupBinding? = null
    private val binding get() = _binding!!


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentSignupBinding.inflate(inflater, container, false)

        auth = Firebase.auth

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        fun isEmailValid(email: String): Boolean {
            val emailPattern = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+"
            return email.matches(emailPattern.toRegex())
        }
        binding.btnSignup.setOnClickListener {
            val signUpEmail = binding.editEmail.text.toString()
            val signUpPassword = binding.editPassword.text.toString()
            if (isEmailValid(signInEmail)) {
                if (signUpNickname.length >= 2) {
                    if (signUpPassword.length > 5) {
                        createAccount(signUpEmail, signUpPassword)
                    } else {
                        Toast.makeText(requireContext(), "비밀번호는 6글자 이상이어야 합니다", Toast.LENGTH_SHORT)
                            .show()
                    }

                } else {
                    Toast.makeText(requireContext(), " 닉네임은 2글자 이상이어야 합니다.", Toast.LENGTH_SHORT)
                        .show()
                }

            } else {
                Toast.makeText(requireContext(), "이메일 형식이 올바르지 않습니다.", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun createAccount(email: String, password: String) {
        if (email.isNotEmpty() && password.isNotEmpty()) {
            auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        val intent = Intent(activity, MainActivity::class.java)
                        startActivity(intent)
                        requireActivity().finish()
                    } else {
                        Toast.makeText(requireContext(), " 회원 정보를 알맞게 다시 입력해주세요 ",Toast.LENGTH_SHORT).show()
                    }
                }
            Log.d("xxxx", "createAccount Successful")
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
}
  • 다음과 같이 SignUp Fragment를 작성이 완료되었다면 정상적으로 회원 정보가 DB에 생성이 될 것이다 Firebase Console을 통해 회원가입 정보를 확인하거나 Log로 확인 등 현재 currentUser를 통해 추가로 확인 가능하다.
Log.d("xxxx", "onCreate: ${Firebase.auth.currentUser}")

 

 

DB 저장확인

  • Authentication → Users 에서 생성된 회원 목록을 조회할 수 있다.

 

 

LogInFragment [ 2 ]

 

LogInFragment onViewCreated 내부에 아래의 코드 작성

        binding.btnLogin.setOnClickListener {
            val email: String = binding.editEmail.text.toString()
            val password : String = binding.editPassword.text.toString()

            if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password)){
                Toast.makeText(requireContext(),"이메일과 비밀번호는 필수 입력사항 입니다",Toast.LENGTH_SHORT).show()
            } else {
                auth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful) {
                            startActivity(Intent(requireActivity(),MainActivity::class.java))
                            requireActivity().finish()
                        } else {
                            Toast.makeText(requireActivity(),"입력하신 정보와 일치하는 회원 정보가 없습니다",Toast.LENGTH_SHORT).show()
                            binding.editPassword.text.clear()
                        }
                    }
            }
        }

 

  • auth.signInWithEmailAndPassword 메서드를 통해 FirebaseAuth에 저장된 인증정보와 일치하는 Email, Password를 입력할 시 로그인 ( = SignIn ) 처리가 되며,  currenUser 값이 로그인한 사용자의 정보로 자동으로 변경된다.

 

 

MainActivity - SignOut ( 로그아웃 ) 추가
class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding

    private lateinit var auth : FirebaseAuth
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflate)
        setContentView(binding.root)

        auth = Firebase.auth
        
        binding.btnHome.setOnClickListener {
            var builder = AlertDialog.Builder(this)
                .setTitle("로그아웃")
                .setMessage("로그아웃 하시겠습니까?")

            val listener = object : DialogInterface.OnClickListener{
                override fun onClick(dialog: DialogInterface?, which: Int) {
                    when(which){
                        DialogInterface.BUTTON_POSITIVE ->
                            signOut()
                        DialogInterface.BUTTON_NEGATIVE ->
                            return
                    }
                }
            }
            builder.setPositiveButton("확인",listener)
            builder.setNegativeButton("취소",listener)

            builder.show()
        }
    }
    private fun signOut() {
        auth.signOut()
        startActivity(Intent(this,LogInActivity::class.java))
        finish()
    }
}

 

[오늘 복습한 내용]

1. 버전 업 된 Java 다운로드 후 환경변수로 지정해줄 때 bin 안넣어서 30분 날렸다...

 

 

 


[오류,에러 등등]

1. CLI 적용 시 JAVA 버전이 11미만이면 Firebase에 CLI 적용할 때 아래의 코드로 적용할 수 없어서 업데이트 해줬다

firebase emulators:start --project=demo-friendlychat-android

 

 

 


[느낀 점]

1. Firebase에 익숙해지려면 시간이 조금 걸릴 것 같다.

 

2. Firebase - 익숙하지 않아서 어렵긴 한데 익숙해지면 간단할 것 같은 느낌

 

3. 복습 좀 해야겠다

 

 


[Reference]

 

// Firebase - RealTime DB / QuickStart

https://github.com/firebase/quickstart-android