오늘 알아볼 내용은 Firebase를 통해서 인증된 사용자만 로그인 할 수 있도록 구현하는 방법에 대해서 알려드리겠습니다.
1) Firebase 프로젝트 만들기
프로젝트를 생성하는데 Google 애널리틱스는 사용설정 권장으로 해 둔 상태지만 전 없는 비활성화한 상태로 진행하겠습니다.
2) 안드로이드를 추가해서 시작합니다.
3) 안드로이드 선택해서 Firebase 추가할 때 Android 패키지이름(AndroidManifest에 있음)을 넣어줍니다.
그 외 선택사항은 스킵해두겠습니다.
AndroidManifest에 혹시 없으면 액티비티 아무거나 들어가면 package가 맨 상단에 정의되어 있습니다.
4) google-services.json 파일 다운로드 후 앱 수준의 루트 디렉토리에 넣어두기
google-services.json 파일에는 개인적인 정보가 있기 때문에 깃허브에 public으로 올리는 것은 지양해야합니다.
.gitignore로 추가해 올리거나 private remote repository에 올리도록 합니다.
5) 프로젝트 수준에서의 build.gradle.kts에 gms.google-services 추가하기
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
id("com.google.gms.google-services") version "4.4.2" apply false
}
6) 앱 수준의 build.gradle.kts에 플러그인 & 디펜던시 추가하기
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id("com.google.gms.google-services")
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
// Firebase
implementation(platform("com.google.firebase:firebase-bom:33.2.0"))
implementation ("com.google.firebase:firebase-auth-ktx")
implementation ("com.google.firebase:firebase-database-ktx")
implementation ("com.google.firebase:firebase-messaging-ktx")
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
이렇게 하면 우선 Firebase와 안드로이드 프로젝트간의 환경 셋팅은 얼추 다했습니다.
다음 Firebase에서 활용하는 서비스에 대해서 연동 작업을 할 것입니다.
위에 implementation 한 건 realtime-database, firebase-messaging, firebase-auth 이 세 가지를 이용하기 위해 미리 해둔 것인데, 이번 포스팅에서는 인증과 관련된 걸 할 것이기 때문에 firebase-auth 부분은 필히 implementation 해야합니다.
Firebase-Auth
1) Firebase console에 앞서 생성한 프로젝트를 열고 들어가서 제품 카테고리칸에서 Authentication을 선택한다.
2) 인증 방법이 다양하지만, Firebase 이메일로 인증하는걸 진행한다.
3) 이렇게 만들어진 Authentication은 이제 환경 셋팅은 완료된 상태입니다.
다음엔 프로젝트엥서 LoginActivity.kt와 그에 딸린 리소스 파일을 만들겠습니다.
build.gradle에서는 뷰바인딩을 허용하도록 합니다.
viewBinding {
enable = true
}
전체적인 코드 먼저 셋팅해서 설명하겠습니다.
[activity_login.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/emailEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="email"
android:inputType="textEmailAddress"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7" />
<EditText
android:id="@+id/passwordEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textPassword"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailEditText"
app:layout_constraintVertical_bias="0.1"
tools:text="password" />
<Button
android:id="@+id/loginButton"
android:layout_width="match_parent"
android:backgroundTint="#49CD4E"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/passwordEditText"
tools:text="로그인"
android:text="로그인"/>
<Button
android:id="@+id/signInButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#2196F3"
app:layout_constraintTop_toBottomOf="@+id/loginButton"
tools:text="회원가입"
android:text="회원가입"/>
</androidx.constraintlayout.widget.ConstraintLayout>
단순히 EditText로 이메일, 비밀번호만 입력할 수 있도록 셋팅만 해주고 로그인/회원가입 버튼만 간단히 두도록 하겠습니다.
[LoginActivity.kt]
여기서 사용될 개념은 Firebase-auth에 비밀번호 인증 과정을 넣어둘 것입니다. (아래 링크 참조)
https://firebase.google.com/docs/auth/android/password-auth?hl=ko
LoginActivity.kt에서 로그인 버튼 기능부터 구현해보겠습니다.
// 회원가입
binding.signUpButton.setOnClickListener {
val email = binding.emailEditText.text.toString()
val password = binding.passwordEditText.text.toString()
if(email.length < 8 || email.isEmpty()) {
Toast.makeText(applicationContext, "이메일 형식을 지켜주세요.", Toast.LENGTH_SHORT).show()
return@setOnClickListener // 클릭 리스너로 돌아가기
}
if(password.isEmpty()){
Toast.makeText(applicationContext, "비밀번호를 입력해주세요.", Toast.LENGTH_SHORT).show()
return@setOnClickListener // 클릭 리스너로 다시 돌아가기
}
Firebase.auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this){task ->
if(task.isSuccessful){
// 로그인 성공
Toast.makeText(this, "회원가입 성공! 로그인을 해주세요.", Toast.LENGTH_SHORT).show()
} else {
// 회원가입 실패
Toast.makeText(this, "회원가입 실패", Toast.LENGTH_SHORT).show()
}
}
}
binding을 통해서 로그인 버튼을 눌렀을 때 리스너를 수행하도록 합니다.
입력한 EditText로부터 이메일, 비밀번호를 가져와 사용하고 간단하게 이메일/비밀번호 입력에 대한 조치를 수행해둡니다.
정규식을 통해 더 완벽하게 하는 것이 좋겠지만 그것보다 더 중요한 것들을 해야하기에 간단히 조치하겠습니다.
회원가입에서는 createUserWithEmailAndPassword 함수는 제공되고 있기에 그대로 사용하면 됩니다.
이는 위에 참조한 링크에서도 확인이 가능합니다.
이거에 대한 리스너로 addOnCompleteListener를 사용하며 Task 자체를 받기에 현 컨텍스트에서 사용하며
task로 결과인자를 사용하면 됩니다.
// 로그인
binding.signInButton.setOnClickListener {
val email = binding.emailEditText.text.toString()
val password = binding.passwordEditText.text.toString()
if(email.length < 8 || email.isEmpty()) {
Toast.makeText(applicationContext, "이메일 형식을 지켜주세요.", Toast.LENGTH_SHORT).show()
return@setOnClickListener // 클릭 리스너로 돌아가기
}
if(password.isEmpty()){
Toast.makeText(applicationContext, "비밀번호 입력해주세요.", Toast.LENGTH_SHORT).show()
return@setOnClickListener // 클릭 리스너로 다시 돌아가기
}
Firebase.auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this){task ->
val currentUser = Firebase.auth.currentUser
if(task.isSuccessful && currentUser != null){
val userId = currentUser.uid
val user = mutableMapOf<String, Any>()
user["userId"] = userId
user["username"] = email
// 미국으로 안하게되면 database("url")
// 예:) Firebase.database("https://~~~~~~~")
// child에 Key로 해서 가져오는데 이건 많이 쓰이기 때문에 상수값으로 넣어둠
// userId -> 내 아이디 (채팅방 관리할 때 쓰임) 알고 있기 때문에 child로 해서 다시 접근
Firebase.database.reference.child(DB_USERS).child(userId).updateChildren(user)
// 회원가입 성공
startActivity(Intent(this, MainActivity::class.java))
finish()
} else {
// 회원가입 실패
Toast.makeText(this, "로그인에 실패하였습니다.", Toast.LENGTH_SHORT).show()
Log.d("LoginActivity", task.exception.toString())
}
}
}
로그인은 signInWithEmailAndPassword라는 함수를 또 제공해줍니다.
마찬가지로 addOnCompleteListener를 달아서 결과인자로 task를 두고 수행하면 됩니다.
task.exception으로 로그를 찍게되면 왜 로그인이 실패했는지 오류 내용이 로그에 남습니다.
Firebase.auth.currentUser는 현재 사용하는 유저를 불러오는 것으로 Firebase를 import 해오면 됩니다.
현재 코드에서는 다음 포스팅에서 다룰 RealTime Database 부분도 추가되어 있습니다. (스포주의)
다음 로그인 액티비티에서 잘 수행된 경우 MainActivity.kt로 이동하게 될 것입니다.
이렇게 회원가입을 먼저 진행하게 된다면 앞서 Firebase 프로젝트에서 Authentication 부분에서
사용자가 추가될 것입니다.
그리고 로그인 버튼을 눌러서 signInWithEmailAndPassword를 통해 인증된 사용자로 로그인 될 수 있을 것입니다.
다음 내용에서는 UI 구성과 화면 목록 정리 그리고 앞서 스포한 RealTime Database에 대해서 다루겠습니다.
감사합니다..!
'Android' 카테고리의 다른 글
Network / Service (feat. Retrofit) (11) | 2024.08.29 |
---|---|
Network - OkHttpClient / Socket 통신 (0) | 2024.08.25 |
WebView & ViewPager2 / Fragment (0) | 2024.08.16 |
ViewPager2와 TabLayout (0) | 2024.08.14 |
Permission 처리와 ListAdapter 활용법 (0) | 2024.08.01 |