[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 디렉토리( 폴더 ) 안에 넣어준다.
- 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 해주는 방법도 있다.
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