사전 준비
안드로이드에서 구글 로그인을 구현하기 위해서는 준비해야 될 게 몇 가지가 있습니다. 구글 클라우드에 들어가서 OAuth 클라이언트 아이디를 만들고 그 과정에서 본인의 앱을 등록해야 합니다. 그러므로 구체적으로 무엇을 먼저 준비해야 하는지 알아보겠습니다.
파이어베이스에 앱을 등록해서 관리하는 것까지 할 예정이니 파이어베이스 과정이 필요없다면 해당 부분은 스킵하세요!
1. 구글 클라우드에서 클라이언트 아이디 생성
구글 클라우드에 들어가서 오른쪽 상단의
콘솔
을 클릭합니다.API 및 서비스
로 들어갑니다. (만약 프로젝트가 없다면 새 프로젝트부터 만들고 시작)왼쪽에 메뉴가 다섯 가지가 존재하는데 거기서
사용자 인증 정보
를 클릭합니다.+ 사용자 인증 정보 만들기
를 눌러서OAuth 클라이언트 ID
를 클릭해서 아이디를 생성합니다. 여기서 애플리케이션 유형을 선택할 수 있는데 웹 애플리케이션, Android 이 두 개를 각각 만들어야 합니다.
2. SHA-1 값 찾기
웹 애플리케이션 유형은 그냥 생성하면 되므로 Android 유형 만드는 방법을 중점으로 알아보겠습니다. 여기서는 중요한 게 패키지 이름과 SHA-1 인증서 디지털 지문
입니다. 패키지 이름은 본인 프로젝트의 패키지 이름을 그대로 적으면 됩니다.
인증서 디지털 지문은 그래들 태스크를 이용해서 찾을 수 있습니다. 그래들 태스크는 다음과 같이 두 가지 방법으로 실행할 수 있습니다. 태스크를 실행시켰다면 gradle signingreport
를 입력해서 실행시키면 됩니다. 그러면 터미널 창에서 SHA1
을 확인할 수 있습니다.
- 안드로이드 스튜디오 오른쪽 메뉴를 클릭한 다음, 터미널 아이콘을 클릭해서 그래들 태스크를 실행합니다.
- 안드로이드 스튜디오 오른쪽 상단의 검색 아이콘을 눌러
Gradle Task
를 검색해서 그래들 태스크를 실행합니다.
파이어베이스에 앱 등록하기
파이어베이스에 가서 프로젝트를 새로 만드시고 프로젝트에 들어가서 앱 추가를 해주세요. 당연히 안드로이드로 해주시면 됩니다. 그러면 구글 클라이언트 아이디 생성할 때와 똑같이 패키지 이름과 SHA-1
값을 요구할 겁니다. 동일하게 작성하고 완료하면 됩니다. 다 만들면 google-services.json
파일을 다운받을 수 있을텐데 이거를 프로젝트 폴더 내 app
에 붙여넣기 해주세요.
의존성 추가
그래들 앱 수준 - Module:app
에서 추가해야 하는 의존성 및 플러그인입니다.
1
2
3
plugins {
id("com.google.gms.google-services") // <- 추가
}
1
2
3
4
5
dependencies {
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
implementation("com.google.firebase:firebase-auth-ktx")
implementation("com.google.android.gms:play-services-auth:20.7.0")
}
그래들 프로젝트 수준 - Project:{본인 프로젝트명}
에서 추가해야 하는 플러그인입니다.
1
2
3
plugins {
id("com.google.gms.google-services") version "4.4.0" apply false // <- 추가
}
구글 아이디 토큰 발급하기
이제 코드를 작성할 단계입니다. 파이어베이스에 로그인 유저 관리를 하기 위해서는 먼저 구글 아이디 토큰이란 것을 받아와야 합니다. 아이디 토큰을 이용해서 파이어베이스에 연결하기 때문에 이 작업을 먼저 처리해야 합니다.
GoogleSignInOptions
을 생성합니다. 저는 아이디 토큰 요청, 이메일 요청만 추가했지만 다른 옵션이 더 필요하다면 추가하면 됩니다. 여기서requestIdToken
에 넘기는 인자가 웹 클라이언트 유형으로 만들었던 클라이언트 아이디 값입니다.1 2 3 4
private val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(BuildConfig.GOOGLE_CLIENT_ID) .requestEmail() .build()
GoogleSignInClient
을 생성합니다.1
val googleSignInClient = GoogleSignIn.getClient(this, gso)
사용자가 구글 로그인을 요청했을 때 결과를 처리하는 코드를 작성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
val googleLogInRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { if (it.resultCode == RESULT_OK) { val task = GoogleSignIn.getSignedInAccountFromIntent(it.data) try { val account = task.getResult(ApiException::class.java) account?.let { user -> user.idToken?.let { idToken -> Timber.d("Get Account idToken! : ${account.idToken}") } } } catch (e: ApiException) { Timber.d(e) } } }
사용자가 구글 로그인 버튼을 클릭했을 때 이벤트를 처리하는 코드 작성
1 2 3
_binding.btnRequestGoogleLogin.setOnClickListener { googleLogInRequest.launch(googleSignInClient.signInIntent) }
파이어베이스에 연결하기
아이디 토큰을 받았다면 이제 해당 토큰을 가지고 파이어베이스에 연결을 해야 합니다. 그러기 위해서 먼저 파이어베이스 auth
를 생성합니다.
1
2
3
4
5
6
7
8
class MainActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
// ...
auth = Firebase.auth
}
}
그리고 아이디 토큰을 가지고 파이어베이스에 연결을 시도합니다.
1
2
3
4
5
6
7
8
9
private fun handleGoogleIdToken(idToken: String) {
val firebaseCredential = GoogleAuthProvider.getCredential(idToken, null)
auth.signInWithCredential(firebaseCredential)
.addOnCompleteListener(this) {
if(it.isSuccessful) {
// 정상 완료
}
}
}
정리
지금까지 구글 로그인 연결을 위해 필요한 과정들을 알아봤습니다. 최종적으로 구한 아이디 토큰이나 파이어베이스 auth
가 가지고 있는 값들을 프로젝트에 연결된 서버에 전송하여 유저 등록을 하게 됩니다. 지금까지의 코드를 간단하게 정리한 예시를 끝으로 마치겠습니다. 감사합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class MainActivity : AppCompatActivity() {
private val viewModel: GoogleLoginViewModel by viewModel()
private lateinit var _binding: ActivityMainBinding
private lateinit var auth: FirebaseAuth
private val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(BuildConfig.GOOGLE_CLIENT_ID)
.requestEmail()
.build()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
setContentView(_binding.root)
_binding.vm = viewModel
auth = Firebase.auth
val googleSignInClient = GoogleSignIn.getClient(this, gso)
val googleLogInRequest =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(it.data)
try {
val account = task.getResult(ApiException::class.java)
account?.let { user ->
user.idToken?.let { idToken ->
Timber.d("Get Account idToken! : ${account.idToken}")
handleLoginResponse()
viewModel.googleLoginByToken(idToken)
}
}
} catch (e: ApiException) {
Timber.d(e)
}
}
}
_binding.btnRequestGoogleLogin.setOnClickListener {
googleLogInRequest.launch(googleSignInClient.signInIntent)
}
_binding.btnRequestGoogleSignOut.setOnClickListener {
googleSignInClient.signOut().addOnCompleteListener {
if(it.isComplete) {
viewModel.googleSignOut()
toast("Complete sign out!")
}
else { toast("Failure sign out!") }
}
}
}
private fun handleLoginResponse() {
viewModel.account.observe(this) { _binding.accountInfo = it }
}
private fun handleGoogleIdToken(idToken: String) {
val firebaseCredential = GoogleAuthProvider.getCredential(idToken, null)
auth.signInWithCredential(firebaseCredential)
.addOnCompleteListener(this) {
if(it.isSuccessful) {
// 정상 완료
}
}
}
}