이번 시간에는 계속해서 '어따세워' 앱의 회원가입 및 로그인 기능을 구현해보자!
로그인 부분은 크게 2가지로,
'파이어베이스를 통한 구글, 페이스북 로그인', '카카오 SDK를 사용한 카카오 간편 로그인 기능' 을 구현할 수 있다.
(이 외에도 더 다양한 로그인 방법이 존재하지만, 프로젝트에서는 크게 2가지로 국한시킵니다.)
이 포스팅에서는 구글 로그인만 포스팅을 할 것이며, 다른 로그인 기능들은 추후 이어서 포스팅할 계획이다.
우선, 미리 디자인 해놓은 레이아웃 화면이다.
포토샵을 사용하여 버튼을 적절히 디자인하였고, 배경 GIF는 상업용 사이트에서 다운받았다.
제목과 부제목란은 임의로 디자인하였다. (추후 변경 예정)
디자인은 나름 만족한다. (❁´◡`❁)
이제 파이어베이스를 들어가서 회원가입에 필요한 세팅을 진행해야 한다.
https://firebase.google.com/?hl=ko
(해당 포스팅은 기존에 이미 프로젝트를 생성했다고 가정한다.)
프로젝트 페이지에 진입하였다면, 빌드 메뉴의 'Authentication'을 클릭한다.
말 그대로 인증! 기능을 담당한다.
Authentication 페이지에 들어왔다면 상단에 이런 메뉴들이 보일 것이다.
바로 'Sign-in method'를 클릭한다.
그럼 이렇게 우측 상단에 '새 제공업체 추가' 버튼이 있을텐데, 버튼을 누르면 다양한 로그인 방식을 지원하는 걸 볼 수 있다.
이 많은 기능들 중, 우리는 대중적인 플랫폼인 Google, Facebook을 사용할 것이다.
설정을 마쳤다면 바로 기본 세팅부터 들어가보자!
dependencies {
// Firebase Auth
implementation platform('com.google.firebase:firebase-bom:29.0.0')
implementation 'com.google.firebase:firebase-auth'
}
우선 build.gradle(app level)의 dependencies 블럭에 Firebase 라이브러리를 추가해준다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="패키지명">
...
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
그리고 Manifest 파일에 들어가서 인터넷 사용권한을 체크해주면 기본 세팅은 끝이난다.
이제 가장 중요한 로그인 기능을 구현할 차례이다.
'어따세워'는 MVVM 패턴으로 프로젝트를 진행중이므로 본인의 프로젝트에 알맞게 코드를 적절히 수정하여 활용하면 된다.
<ImageButton
android:id="@+id/google_login_button"
android:layout_width="240dp"
android:layout_height="50dp"
android:background="@drawable/img_login_google"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:onClick="@{() -> viewModel.loginWithGoogle()}" />
// activity_login.xml
fun loginWithGoogle() {
// 로그인을 로딩상태
isLoading.value = true
// 사용자의 기본정보를 얻을 수 있는 객체 (userID, profile)
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken("리퀘스트 아이디 토큰")
.requestEmail()
.build()
// SignIn 클라이언트 객체 받아오기
val googleSignInClient: GoogleSignInClient = GoogleSignIn.getClient(App.context, gso)
// 구글 로그인 화면을 띄우기 위한 startActivityForResult를 위해 view로 googleSignInClient객체 전달
loginCallback?.onClickLoginButton(googleSignInClient, LoginType.GOOGLE)
}
// LoginViewModel.class
우선, ViewModel의 loginWithGoogle() 메서드를 만들어주었다.
이 함수는 DataBinding으로 구글 로그인 버튼을 클릭하면 호출되는 메서드이다.
버튼을 누르면, MutableLiveData인 isLoading의 값을 true로 바꿔주고(true일때 프로그레스바가 보임.),
GoogleSignInOptions을 생성하여 클라이언트에 전달하고 콜백을 통해 LoginActivity로 클라이언트 객체를 전달해준다.
private lateinit var googleLoginResultLauncher: ActivityResultLauncher<Intent>
// start activity result
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
googleLoginResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val signInTask = GoogleSignIn.getSignedInAccountFromIntent(result.data)
try {
val account = signInTask.getResult(ApiException::class.java)
viewModel.onGoogleSignInAccount(account)
} catch (e: ApiException) {
Timber.e(e.message)
}
}
viewModel.isLoading.value = false // 로그인 로딩 종료
}
// 로그인 버튼 커스텀 콜백
override fun onClickLoginButton(others: Any?, loginType: LoginType) {
when (loginType) {
LoginType.GOOGLE -> signInWithGoogle(others as GoogleSignInClient)
}
}
// 구글 로그인 화면 출력
private fun signInWithGoogle(googleSignInClient: GoogleSignInClient) {
googleSignInClient.signInIntent.run {
googleLoginResultLauncher.launch(this)
}
}
// 구글 계정 로그인(회원가입) 메소드
fun onGoogleSignInAccount(account: GoogleSignInAccount?) {
if (account != null) {
val credential = GoogleAuthProvider.getCredential(account.idToken,null)
// 구글 로그인 성공시
FirebaseAuth.getInstance().signInWithCredential(credential).addOnCompleteListener { task -> // task : 사용자 및 결과 정보를 가지고 있음
onLoginGoogleAuthTask(task) // 로그인 성공 후 수행할 메소드 호출
}
}
}
// LoginViewModel.class
그렇게 호출한 onClickLoginButton에서 만약 로그인 방식이 'Google' 로그인이라면 signInWithGoogle() 메서드 호출을 통해 구글로 로그인을 수행하도록 한다.
로그인을 성공적으로 마치면 ActivityResultLauncher에서 계정 데이터를 받아올 수 있다.
그럼 ViewModel에게 '이제 회원가입을 마쳤으니 구글 계정으로 로그인해~!' 라는 의미의 onGoogleSignInAccount() 메서드를 호출한다.
(ActivityResultLauncher에 대해 처음 접하는 분들은 아래 링크에 정리해두었으니 참고 바랍니다..!)
https://itstory1592.tistory.com/44
// 구글 계정 로그인(회원가입) 메소드
fun onGoogleSignInAccount(account: GoogleSignInAccount?) {
if (account != null) {
val credential = GoogleAuthProvider.getCredential(account.idToken, null)
// 구글 로그인 성공시
FirebaseAuth.getInstance().signInWithCredential(credential).addOnCompleteListener { task -> // task : 사용자 및 결과 정보를 가지고 있음
onLoginGoogleAuthTask(task) // 로그인 성공 후 수행할 메소드 호출
}
}
}
// 파이어베이스 구글 로그인 성공시 수행할 메소드
private fun onLoginGoogleAuthTask(task: Task<AuthResult>) {
viewModelScope.launch {
if (task.isSuccessful) { // Google로 로그인 성공
// repository를 통해 회원가입 요구(중복 계정일 경우 백엔드에서 처리)
userRepository.register(User(auth.uid!!, auth.currentUser?.email, auth.currentUser?.displayName!!, LoginType.GOOGLE.name))
Timber.d("Register completed, Trying Signining google...")
isLoading.value = false // 로딩바 멈추기
// 로그인 콜백을 호출하여 다음 액티비티 실행
loginCallback?.onSignIn(LoginType.GOOGLE, ResultType.SUCCESS)
} else { // Google로 로그인 실패
Timber.e("Firebase Login Failure.")
}
}
}
// LoginViewModel.class
onGoogleSignInAccount()를 호출하면 이제야 구글 로그인을 시도한다.
만약 구글 로그인에 에러없이 성공한다면, Repository의 register() 메서드를 호출하여, 개인 서버의 DB에 유저의 기본 정보를 저장한다.
그리고 콜백으로 View에게 구글 로그인을 성공했다는 것을 알려주어 로그인 이후의 작업을 수행하도록 구현하면 된다.
보통은 회원가입과 로그인을 모두 마쳤으므로 다음 화면으로 이동하는 로직을 작성할 것이다. (나 포함..ㅎㅎ!)
서버에 회원정보 등록시 백엔드 시점(프로젝트 팀원 블로그)
사실 패턴에 대한 지식이 없을땐 모두 Activity에 코드를 때려박아 코드 작성은 수월하였다.
하지만 이렇게 MVVM 패턴을 적용하여 코드를 작성하니 View와 ViewModel의 역할이 각각 나누어져 있어 후에 유지보수를 하기 편할 거라는 생각이 들었다. (MVVM 패턴 짱..!!)
내용에 오류가 있거나, 질문 사항 및 이해가 어려우신 분들은 댓글을 부탁드리겠습니다! 😉
'Project > 어따세워' 카테고리의 다른 글
[Android][어따세워] 앱 아이콘 제작 / 해상도별 사이즈 조절(포토샵) (0) | 2021.12.09 |
---|---|
[Android][어따세워] Retrofit2를사용하여 주차장 공공 데이터를 가져오자! (0) | 2021.12.04 |
[Android][어따세워] 메타버스 스터디룸(게더타운) 개설! (0) | 2021.11.30 |
[Android][어따세워] 토이 프로젝트 주제 정하기 (6) | 2021.11.29 |