선생님, 개발을 잘하고 싶어요.

[OAuth] 카카오 로그인 안드로이드 kotlin, coroutine 구현 가이드, 플랫폼 설정 부터 coroutine utility 까지 본문

개발/android 개발

[OAuth] 카카오 로그인 안드로이드 kotlin, coroutine 구현 가이드, 플랫폼 설정 부터 coroutine utility 까지

알고싶은 승민 2022. 6. 3. 12:25

카카오 로그인을 설명한다.

도입

어떤 프로젝트를 해도 사용자 인증은 중요한 키워드다. 그리고 사용자의 쉬운 접근을 위해서는 소셜 로그인 지원은 거의 필수적이다.

이번에는 카카오 로그인에 대해서 a-to-z까지 따라만 하면 성공하는 형태로 포스팅을 쓴다. (유용한 gists 도 제공한다!)

절차

준비물

카카오 로그인을 설정하기 위해선 다음을 미리 준비하자.

  • 카카오 개발자 계정
  • 카카오 로그인 적용을 위한 안드로이드 프로젝트

카카오 디벨로퍼 페이지에서 준비하기

카카오 디벨로퍼 페이지에서 사용할 애플리케이션을 등록하자. https://developers.kakao.com/console/app

애플리케이션 추가하기

애플리케이션 추가하기 버튼을 눌러준다.

애플리케이션 추가하기

앱 이름, 사업자명을 지정한 다음 저장하기를 누른다.

애플리케이션 생성 완료

SampleOauthLogin 애플리케이션이 추가된 걸 확인할 수 있다.

이렇게 애플리케이션 생성을 완료 했으면 카카오 로그인을 위한 설정을 추가로 마무리하자.

카카오 로그인 활성화

Redirect URI 를 아무것도 지정하지 않으면 소셜 로그인 과정에서 다음 스텝으로 나아가지 못한다. 그냥 https://sample.com/oauth처럼 아무렇게나 지정해놓자.

 

이렇게 해서 카카오 애플리케이션이 카카오 로그인을 사용할 준비가 끝났다.

이제 안드로이드 애플리케이션과 연동을 위해서 플랫폼을 등록해야 한다.

 

플랫폼 관리

플랫폼 탭에서 Android 플랫폼 등록을 누른다.

안드로이드 플랫폼 등록 상세

3번을 수행할 때는 자신의 OS에 따라서, 디버그 용인지 릴리즈 용인지에 따라서 별도의 Key Hash를 생성해야 한다. 키 해시 등록하기에 케이스 별로 정리되어 있으니 참고해서 설정을 마무리하자.

안드로이드 프로젝트 세팅하기

이걸로 카카오 디벨로퍼 사이트에서 설정할 내용이 거의 끝났다.

이제 준비된 안드로이드 프로젝트와 카카오 SDK를 연동하자.

의존성 설정하기

카카오가 제공하는 SDK를 다운로드하는 과정을 설명한다.

 

settings.gradle 파일에 kakao sdk maven 저장소를 추가하자. 이걸 추가해야 build.gradle 파일을 통해서 sdk를 다운로드할 수 있다.

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // 이 라인을 추가하자.
        maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
    }
}

 

app level build gradle (build.gradle (:app))에 다음 의존성을 추가하자.

dependencies {
    ...

    // 이 라인을 추가하자.
    implementation "com.kakao.sdk:v2-user:2.10.0"
}

 

준비가 완료되었으니 gradle sync 하고 의존성을 다운로드하자.

추가로 proguard-rules.pro 파일에 proguard rule을 추가하자. 디버그 과정에서는 아무런 차이가 없지만 난독화 빌드에서 이상한 버그가 발생할 수 있으니 그냥 추가하는 걸 추천한다.

# https://developers.kakao.com/docs/latest/en/getting-started/sdk-android#configure-for-shrinking-and-obfuscation-(optional)
-keep class com.kakao.sdk.**.model.* { <fields>; }
-keep class * extends com.google.gson.TypeAdapter

카카오 SDK 초기화해서 사용 준비하기

SDK를 우리의 애플리케이션 생명주기에 편입시킨다. 그를 위해서 SDK를 초기화해야 한다.

 

SDK를 초기화하기 위해서는 네이티브 앱 키가 필요하다. 다시 카카오 디벨로퍼 페이지에서 내가 설정하는 애플리케이션을 찾아 들어가자.

요약 정보 > 앱 키 > 네이티브 앱 키를 복사하자.

 

이를 등록하기 위해서 strings resource를 만든다. kakao_strings.xml 이란 이름으로 res/values 폴더 아래에 다음을 추가한다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="kakao_native_app_key">2a1a7906b63b7976d84423a4c9f63967</string>
    <!-- kakao${kakao_native_app_key} 의 구조다. -->
    <string name="kakao_redirection_scheme">kakao2a1a7906b63b7976d84423a4c9f63967</string>
</resources>

깃 허브를 통해서 public 하게 공개할 경우 이런 app key가 공개되는 것은 바람직하지 않다. 따라서 kakao_strings.xml을

src/main/res/values/kakao_strings.xml

 

이제 네이티브 키를 사용해서 카카오 SDK 초기화를 하자.

 

제일 처음 할 것은 KakaoSdk.init를 호출하는 것이다. 이를 우리 애플리케이션이 실행되는 시점에 호출하기 위해서 커스텀 애플리케이션 클래스를 만들고 매니페스트에 추가했다.

class SampleApp : Application() {
    override fun onCreate() {
        super.onCreate()
        KakaoSdk.init(this, getString(R.string.kakao_native_app_key))
    }
}

 

카카오 로그인은 당연히 인터넷 연결이 필요할 것이다. 매니페스트에 인터넷 퍼미션을 추가한다.

<uses-permission android:name="android.permission.INTERNET" />

카카오 SDK는 내부적으로 OAuth 토큰을 우리 애플리케이션으로 전달하기 위해서 DeepLink를 활용한다. 그래서 미리 정의된 DeepLink 처리용 Activity를 메니페스트에 추가해주자. (그냥 설정만 하고 넘어가도 무방하다. 카카오 SDK 내부적으로 사용될 Activity이기에 우리가 직접 켤 일은 없다.)

<activity
    android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
    android:launchMode="singleTask"
    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" />

        <data
            android:host="oauth"
            android:scheme="@string/kakao_redirection_scheme" />
    </intent-filter>
</activity>

공식 문서에는

android:launchMode="singleTask"

를 설정하는 코드가 누락되어 있는데 필자는 이를 설정하지 않아서 로그인 처리가 안됬었다. 추가하자.

로그인을 위한 View 구현

로그인을 처리하기 위해서 MainActivity를 변형하겠다.

<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_kakao_login"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="카카오로그인" />
</LinearLayout>
class MainActivity : AppCompatActivity() {

    private lateinit var kakaoLoginButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        kakaoLoginButton = findViewById(R.id.button_kakao_login)
        kakaoLoginButton.setOnClickListener {
            //TODO: 카카오 로그인 요청
        }
    }
}

버튼 하나 있는 간단한 화면으로 설명한다.

Kakao SDK 래핑 한 유틸리티 추가하기

카카오가 제공하는 인터페이스는 callback, rxJava 구현체가 있다. 필자는 coroutine을 활용한 구현체 유틸리티를 공유하려고 한다.

다음 코드를 UserApiClientExt.kt 파일로 추가하자. (코드 의존성은 프로젝트 상황에 맞춰서 직접 import 해야 할 것이다.)

간단히 함수를 설명하자.

  • loginWithKakaoTalk: 카카오톡 애플리케이션을 활용해서 로그인을 시도한다.
  • loginWithKakaoAccount: 카카오 계정을 활용해서 로그인을 시도한다. 카카오 앱이 아니라 별도의 크롬 탭이 켜지는 형태로 동작한다.
  • loginWithKakao: 카카오톡이 설치되어 있다면 카카오톡 로그인을 시도하고, 그렇지 않다면 카카오 계정 로그인을 시도한다.

각 함수는 UserApiClient.Companion의 확장 함수로 사용법은 Java의 static 함수를 사용하는 것과 같다.

UserApiClient.loginWithKakao(context)
UserApiClient.loginWithKakaoTalk(context)
UserApiClient.loginWithKakaoAccount(context)

애플리케이션에서 간단하게 Kakao Login 구현하기

coroutine을 활용해서 kakao login을 구현할 것이므로 다음 편의를 위해 의존성을 build.gradle (:app)에 추가하자.

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"

이제 다시 서비스 코드(MainActivity)로 돌아와서 카카오 로그인을 추가하자.

class MainActivity : AppCompatActivity() {

    private lateinit var kakaoLoginButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        kakaoLoginButton = findViewById(R.id.button_kakao_login)
        val context = this
        kakaoLoginButton.setOnClickListener {
            lifecycleScope.launch {
                try {
                    // 서비스 코드에서는 간단하게 로그인 요청하고 oAuthToken 을 받아올 수 있다.
                    val oAuthToken = UserApiClient.loginWithKakao(context)
                    Log.d("MainActivity", "beanbean > $oAuthToken")
                } catch (error: Throwable) {
                    if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
                        Log.d("MainActivity", "사용자가 명시적으로 취소")
                    } else {
                        Log.e("MainActivity", "인증 에러 발생", error)
                    }
                }
            }
        }
    }
}

여기까지 쉽게 카카오 로그인 구현이 완료되었다.

참고 링크

Comments