로그인 구현 방법을 소개할 예정이다!!
카카오 로그인 구현에 필요한 로그인 버튼 이미지는 [도구] > 리소스 다운로드에서 제공해준다.
Android SDK를 사용한 카카오 로그인 구현 방법은 두 가지로 나뉜다.
구현 방법 | 메서드 | 설명 |
---|---|---|
카카오톡으로 로그인(권장) | loginWithKakaoTalk() | 카카오톡에 연결된 카카오계정 및 인증 정보를 사용 사용자가 카카오계정 정보를 직접 입력하지 않아도 간편하게 로그인 가능 |
카카오계정으로 로그인 | loginWithKakaoAccount() | 기본 웹 브라우저(Default Browser)를 통해 카카오계정 정보를 입력하고 로그인 사용자가 카카오계정 정보를 직접 입력하는 단계를 거침 사용자가 여러 개의 카카오계정을 사용하는 서비스, 카카오톡 미설치 또는 미지원 디바이스에서 사용 |
카카오 로그인 기능을 구현하기 위해서는 리다이렉션(Redirection)을 통해 인가 코드를 받아야 한다.
이를 위해 AndroidManifest.xml에 액티비티(Activity) 아래와 같은 설정이 필요하다.
<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Redirect URI: "kakao${NATIVE_APP_KEY}://oauth" -->
<data android:host="oauth"
android:scheme="kakao${NATIVE_APP_KEY}" />
</intent-filter>
</activity>
카카오 인증 서버가 지정된 Redirect URI로 인가 코드를 보내면, Android SDK가 인가 코드를 받아 토큰 받기를 요청합니다. 자세한 과정은 이해하기를 참고합니다.
시작하기 전에 다운로드 받았던 로그인 버튼 이미지를 레이아웃 파일에 추가하여 화면 중앙에 버튼을 배치해볼 예정이다.
<androidx.constraintlayout.widget.ConstraintLayout>
<ImageButton
android:background="@drawable/kakao_login_medium_narrow"
android:id="@+id/btn_kakao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
로그인이 성공되면 화면을 이동하여 '로그인 성공'과 '로그아웃 버튼'을 배치해보겠다.
<androidx.constraintlayout.widget.ConstraintLayout>
...
<TextView
android:id="@+id/tv_login"
android:text="로그인 성공!!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="로그아웃"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
UserApiClient의 loginWithKakaoTalk()을 호출하기 전 isKakaoTalkLoginAvailable()로 카카오톡 실행 가능 여부를 확인할 것을 권장하기 때문에 아래와 같이 입력한다.
btnKakaoLogin.setOnClickListener {
// kakao 실행 가능 여부
if (UserApiClient.instance.isKakaoTalkLoginAvailable(this)) {
// 가능하다면 카카오톡으로 로그인하기
UserApiClient.instance.loginWithKakaoTalk(this) { token, error ->
if (error != null) {
Toast.makeText(this, "카카오톡으로 로그인 실패!", Toast.LENGTH_SHORT).show()
Log.e("test", "카카오톡으로 로그인 실패! " + error.message)
// 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우,
// 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기)
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
return@loginWithKakaoTalk
}
} else if (token != null) {
Toast.makeText(this, "카카오톡으로 로그인 성공!", Toast.LENGTH_SHORT).show()
Log.d("test", "카카오톡으로 로그인 성공! " + token.accessToken)
val intent = Intent(this, LoginSuccessActivity::class.java)
startActivity(intent)
finish()
}
// kakao로 로그인 하지 못 할 경우 계정으로 로그인 시도
UserApiClient.instance.loginWithKakaoAccount(this, callback = callback)
}
} else {
UserApiClient.instance.loginWithKakaoAccount(this, callback = callback)
}
}
callback은 이메일 로그인의 callback인데, 두 군데에서 로그인이 사용되기 때문에 따로 callback을 변수로 만들어 코드를 간결하게 만들었다.
val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
if (error != null) {
Toast.makeText(this, "카카오 계정으로 로그인 실패!", Toast.LENGTH_SHORT).show()
Log.e("test", "카카오 계정으로 로그인 실패! " + error.message)
} else if (token != null) {
Toast.makeText(this, "카카오 계정으로 로그인 성공!", Toast.LENGTH_SHORT).show()
Log.d("test", "카카오 계정으로 로그인 성공! " + token.accessToken)
val intent = Intent(this, LoginSuccessActivity::class.java)
startActivity(intent)
finish()
}
}
로그인이 성공되면 아래와 같은 화면이 나타난다. 후후....
사용자 액세스 토큰과 리프레시 토큰을 모두 만료시켜, 더 이상 해당 사용자 정보로 카카오 API를 호출할 수 없도록 하는 것이다.
UserApiClient의 logout()을 호출해 로그아웃을 요청할 수 있다.
로그아웃은 요청 성공 여부와 관계없이 토큰을 삭제 처리한다.
// 성공 여부와 관계 없이 토큰 삭제.
UserApiClient.instance.logout { error ->
if (error != null) {
Log.e("test", "로그아웃 실패. SDK에서 토큰 삭제됨", error)
} else {
Log.e("test", "로그아웃 실패. SDK에서 토큰 삭제됨", error)
}
}
카카오 플랫폼 안에서 앱과 사용자 카카오계정의 연결 상태를 해제한다. UserApiClient의 unlink()를 호출합니다.
연결이 끊어지면 기존의 토큰은 더 이상 사용할 수 없으므로, 연결 끊기 요청 성공 시 로그아웃 처리가 함께 이뤄져 토큰이 삭제된다.
UserApiClient.instance.unlink { error ->
if (error != null) {
Log.e("test", "연결 끊기 실패", error)
} else {
Log.i("test", "연결 끊기 성공. SDK에서 토큰 삭제 됨")
}
}
로그아웃 vs 연결끊기
앱 시작 시 첫 로그인할 때 사용자 정보 동의를 하는데,
이때 연결끊기를 하면 사용자 정보 동의 창이 다시 뜨게 된다.
즉, 앱과 사용자 계정의 연결을 끊어주는 의미이다.
카카오 로그인 끗