ANDROID/Android 개발 이슈 & 해결
[Android] Compose에서 Kakao 로그인 구현하기
주 녕
2024. 10. 4. 16:09
반응형
사이드나 회사 플젝에서도 그렇고 한번도 그 흔한 Kakao 로그인을 구현해볼 기회가 없었는데, 이번 기회에 구현해보게 되었다.
우선 Kakao Developer 페이지의 설명과 다른 개발 블로그들의 설명이 충분히 친절하기 때문에 과정은 패스하고,
이번 개발 스펙은 Compose이기 때문에 Compose에서 Kakao 로그인을 구현하는 과정에서의 이슈를 정리하고자 한다.
이슈 1 : 왜 Kakao 로그인 화면에서 다시 앱으로 돌아가지 않는 것인가?
답변 : Redirect URL을 설정하지 않았다
Manifest에서 Redirect URL 설정하는 부분을 빼먹었다.
<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" />
<data
android:host="oauth"
android:scheme="kakao${KAKAO_NATIVE_KEY}" />
</intent-filter>
</activity>
- android:scheme에 사용된 ${KAKAO_NATIVE_KEY}는 local property에 저장된 값을 불러온 코드
- kakao{KAKAO 네이티브 앱 키} (공식문서 내용)
- API key는 외부에 유출이 되면 안되기 때문에 보통 local.property 파일에서 관리한다
build.gradle
- Manifest에서 사용할 local.property 값은 다음과 같이 설정해주면 된다
- Manifest에서 사용할 string 값은 local.property에 선언할 때 " "(쌍따옴표)를 제거해야 한다
android {
...
defaultConfig {
...
manifestPlaceholders["KAKAO_NATIVE_KEY"] = getLocalProperties("KAKAO_NATIVE_KEY")
}
}
fun getLocalProperties(key: String): String {
return gradleLocalProperties(rootDir, providers).getProperty(key)
}
이슈 2 : 왜 로그인 창이 Chrome으로 열리는 것인가?
답변 : Context를 잘못 지정했다
기존 코드
- Kakao 로그인을 처리하는 비즈니스 로직을 ViewModel에서 처리하고 싶었다
- ViewModel에서 Context를 처리하는 것이 좋지 않다는 사실은 모두... 익히 알고 있는 사실 (GC 문제 발생 가능성)
- 그래서 Application Context를 가지고 처리하는 방법을 선택했다
@HiltViewModel
class SignInViewModel @Inject constructor(
application: Application,
private val buildConfig: AppBuildConfig
) : AndroidViewModel(application), ContainerHost<SignInState, SignInSideEffect> {
override val container: Container<SignInState, SignInSideEffect> = container(SignInState())
...
private val kakaoSignInCallBack: (OAuthToken?, Throwable?) -> Unit = { token, error ->
if (error != null) {
failedToKakaoSignUp(error)
} else if (token != null) {
successToKakaoSignUp(token)
}
}
fun signInWithKakao() {
val context = getApplication<Application>().applicationContext
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
UserApiClient.instance.loginWithKakaoTalk(context) { token, error ->
if (error != null) {
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
return@loginWithKakaoTalk
}
UserApiClient.instance.loginWithKakaoAccount(
context = context,
callback = kakaoSignInCallBack
)
} else if (token != null) {
successToKakaoSignUp(token)
}
}
} else {
UserApiClient.instance.loginWithKakaoAccount(context, callback = kakaoSignInCallBack)
}
}
...
}
결과
- 에러 : Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
- Activity가 아닌 곳에서 startActivity()를 호출했다는데... 제가유?
- 플래그(flag)와 부가 데이터(Extra Data)에 대해서 복습하려고 다시 제 블로그를 타고 들어갔는데, 이 플래그는 없었다
- Root Activity로만 존재하며, 1개의 인스턴스만 생성 가능
- Task 내 해당 Activity 1개만 속할 수 있어, 다른 Activity를 실행시키면 새로운 Task가 생성됨
- 나의 경우 flag 추가가 아닌 ViewModel에서 호출하기 위해 Application Context를 사용한 것이 원인이었기 때문에 Screen 쪽으로 코드 위치를 변경하고 Activity의 context를 이용하여 해결했다.
Reference >
반응형