안드로이드

[Android] 코루틴을 활용해 카카오 로그인 콜백 지옥에서 탈출하기

easyhz 2024. 10. 2. 17:28

개요

전에 소셜 로그인 (구글 로그인) 구현할 때 전략패턴을 적용했었다. (관련 링크)

프로젝트 백로그 중에 카카오 로그인 도입이 있어, 공부했던 코루틴을 잘 적용한 과정을 글로 남기려 한다.

 

카카오 로그인 도입 그리고..

카카오 로그인은 예전에 도입해본 경험이 있어, 어렵지 않게 코드를 작성했다. 또한, 전략 패턴을 이용했었기에 크게 수정하는 부분 없이 쉽게 도입할 수 있었다. 그러나 필자가 해야할 숙제는 `콜백 지옥에서 탈출하기`이다. 

 

우선, 카카오 로그인 메서드를 들여다 보았다.

/* 카카오톡으로 로그인 */
fun loginWithKakaoTalk(
    context: Context,
    requestCode: Int = AuthCodeClient.DEFAULT_REQUEST_CODE,
    nonce: String? = null,
    channelPublicIds: List<String>? = null,
    serviceTerms: List<String>? = null,
    callback: (token: OAuthToken?, error: Throwable?) -> Unit
) { .. }

/* 카카오 계정으로 로그인 */
fun loginWithKakaoAccount(
    context: Context,
    prompts: List<Prompt>? = null,
    loginHint: String? = null,
    nonce: String? = null,
    channelPublicIds: List<String>? = null,
    serviceTerms: List<String>? = null,
    callback: (token: OAuthToken?, error: Throwable?) -> Unit
) { .. }

 

사용할 메서드 두 개에서 주의깊게 본 파라미터는 `context`, `callback` 이었다. 전략패턴을 적용할 때 `context` 는 파라미터로 받고 있어 든든했고, 내가 풀어야할 숙제는 `callback` 파라미터이다.

 

콜백을 탈출하기 전에

콜백을 탈출하기 전에, `suspendCoroutine` , `suspendCancellableCoroutine`을 살펴보도록 하자

둘이 비슷하지만 다른데, 일단 이름을 살펴보면 "중단 코루틴 / 중단 취소 가능한 코루틴" 이랜다

하나씩 알아보자

suspendCoroutine

기본적인 일시 중단 함수로, 비동기 작업을 처리하기 위해 코루틴을 일시 중단하고, 작업이 완료되면 코루틴을 재개한다.

그냥 `Continuation` 객체를 사용하기 때문에 취소 기능이 없다. 즉, 코루틴이 취소되어도 비동기 작업은 계속 실행된다. 비동기 작업 중에 코루틴이 취소되더라도 작업이 종료될 때까지 기다리게 된다.

 

예제는 다음과 같다.

콜백을 적용한 메서드가 있다면이를 기다려서 결과를 얻어낸다.

suspend fun request(): String = suspendCoroutine { continuation ->
    /* 비동기 작업이 완료되면 코루틴을 재개 */
    requestExampleApi { result ->
        continuation.resume(result)  /* 작업 성공 시 실행 */
    }
}

suspendCancellableCoroutine

취소 가능한 일시 중단 함수이다. `CancellableContinuation` 객체를 사용하기 때문에 코루틴이 취소되면 해당 작업도 취소 가능하게 처리할 수 있다. 취소 처리 시 코루틴이 취소되면 비동기 작업을 중단하거나 콜백을 해제할 수 있는 기능을 제공한다. 취소 가능성 때문에 작업이 취소되면 즉시 코루틴이 종료되고, 필요하다면 비동기 작업도 정리할 수 있다.

 

예제는 다음과 같다.

코루틴이 취소되면 취소를 감지하고 적절한 작업을 처리할 수 있다.

suspend fun request(): String = suspendCancellableCoroutine { continuation ->
    /* 비동기 작업이 완료되면 코루틴을 재개 */
    val callback = requestExampleApi { result ->
        if (continuation.isActive) {
            continuation.resume(result)  /* 작업 성공 시 */
        }
    }

    /* 코루틴이 취소되면 비동기 작업도 취소되도록 처리 */
    continuation.invokeOnCancellation {
        cancelCallback(callback)  /* 취소 시 콜백 해제 */
        /* 자원 정리 등 추가적인 리소스 관리 */
    }
}

 

이는 비동기 작업이 취소되었을 때 즉시 중단하거나 정리해야 하는 경우 사용할 수 있다. 예를 들어, 네트워크 요청이나 파일 다운로드 작업과 같은 상황에서 요청이 취소되면 불필요한 리소스를 낭비하지 않도록 작업을 취소하고 싶을 때 유용하다.

 

 

콜백 탈출하기

필자는 `suspendCoroutine` 을 사용했는데  그 이유는 카카오 로그인 SDK는 따로 자원 정리가 필요하지 않기 때문이다.

그래서 아래와 같이 코드를 짜주었다.  메서드 안의 when 절도 공통된 부분이라 더 리팩토링도 가능할 것 같다.!

/**
 * 카카오톡으로 로그인
 *
 * @param context Context
 * @return [OAuthToken] 로그인 성공 시 발급되는 토큰
 */
private suspend fun loginWithKakaoTalk(context: Context): OAuthToken = suspendCoroutine { continuation ->
    UserApiClient.instance.loginWithKakaoTalk(context) { token, error ->
        when {
            error != null -> continuation.resumeWithException(error)
            token != null -> continuation.resume(token)
            else -> continuation.resumeWithException(IllegalStateException("Unexpected error during KakaoTalk login"))
        }
    }
}

/**
 * 카카오 계정으로 로그인
 *
 * * 카카오톡에 연결된 카카오 계정이 없을 경우 카카오 계정 로그인 시도
 *
 * @param context Context
 * @return [OAuthToken] 로그인 성공 시 발급되는 토큰
 */
private suspend fun loginWithKakaoAccount(context: Context): OAuthToken = suspendCoroutine { continuation ->
    UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
        when {
            error != null -> continuation.resumeWithException(error)
            token != null -> continuation.resume(token)
            else -> continuation.resumeWithException(IllegalStateException("Unexpected error during KakaoAccount login"))
        }
    }
}

 

 

 

그 결과, 콜백에서 탈출 할 수 있었고 문제없이 카카오 로그인을 추가할 수 있었다.!

 

 

해당 코드는 아래에서 보실 수 있습니다

https://github.com/Team-Notitime/NOFFICE-ANDROID/blob/feat/sign/197-kakao-login/data/auth/src/main/java/com/easyhz/noffice/data/auth/strategy/KakaoStrategy.kt

 

NOFFICE-ANDROID/data/auth/src/main/java/com/easyhz/noffice/data/auth/strategy/KakaoStrategy.kt at feat/sign/197-kakao-login · T

넌 무슨 알림봤다는 말을 노피스 없을 때 하니🍛. Contribute to Team-Notitime/NOFFICE-ANDROID development by creating an account on GitHub.

github.com