Android 카카오 로그인 관련 proguard 이슈

이지훈·2024년 2월 1일
0
post-thumbnail

서두

경험상 Android에서 카카오 로그인을 구현할 경우 경우 debug builg type에선 문제가 없는데, release 로 빌드 할 경우 문제가 생기는 경우가 많다. 그래서 많은 분들이 앱을 스토어에 출시한 이후 이와 같은 버그를 발견해서 이를 급하게 핫픽스 하곤 한다.

나도 예전에 앱을 처음 출시했을 때, 같은 경험을 했었는데, 그때는 카카오 로그인 파트를 내가 직접 담당을 한 것은 아니었기에, 간접적으로 체감한 문제였다. 오늘은 이 문제에 대해서 다뤄보도록 하겠다.

문제 발생

카카오 로그인을 공식 문서를 참고하여 구현한 이후, debug build type 에서 정상적으로 로그인을 통해 accessToken 과 사용자의 닉네임, 프로필 사진 url 을 가져와지는 것을 확인하였다. 작업을 완료하고 PR을 올린 후, CI 가 돌아가는 것을 확인하는 도중, 다음과 같은 에러가 발생하는 것을 확인할 수 있었다.

이후 서버에 accessToken 을 넘겨 해당 토큰의 validation 을 진행 후, accessToken 과 refreshToken 을 받아오는 작업도 진행해야 하지만, 아직 현 시점에서 해당 프로젝트는 서버가 붙지 않아, 위 작업만 진행하고 PR 을 올렸다.

ERROR: Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in /home/runner/work/ilab-android/feature/login/build/outputs/mapping/release/missing_rules.txt.

ERROR: Missing class java.lang.invoke.StringConcatFactory(referenced from: void com.nexters.ilab.android.feature.login.LoginScreenKtLoginRouteLoginRoutekakaoCallback$1$1.invoke(com.kakao.sdk.user.model.User, java.lang.Throwable and 3 other contexts)

우선 CI 에서 Build with Gradle 이라는 step 은 ./gradlew build command 를 실행하는 step 이고, 내가 알고 있는 바로는, 프로젝트에 존재하는 모든 build variants, 따로 추가하지 않았다면 debug, release 를 통해 빌드가 정상적으로 이뤄지는지 테스트 하는 단계이다.

gradle 은 알겠는데 gradlew는 무엇인지 등 더 자세한 내용은 하단의 블로그 링크를 참고하면 좋을 것 같다. [Android] Gradle Task 종류 및 사용법

debug build type 에서 빌드했을 경우엔 문제가 없었으나, 에러 로그의 minifyReleaseWithR8 Faled 와 같이 release 에서 문제가 있음을 파악할 수 있었고 프로젝트 파일에서 사용하는 com.kakao.sdk.user.model.User... 을 보고 kakao sdk 관련 문제임을 알 수 있었다.

이전엔 프로젝트에 CI 환경을 구축하지 않았기에, 해당 문제를 출시 후에 알게되었는데, 이번 프로젝트에선 develop 및 main에 PR 을 올릴 경우 CI 돌아가도록 환경을 구축 해놓은 덕분에, 문제를 조기에 발견할 수 있었다.

문제 해결?

경험상 minify R8 과 같은 키워드를 통해 proguard 쪽에 문제지 않나 생각했다. release 로 빌드시 isMinifyEnabled = true 옵션을 통해 코드 축소(minification) 및 난독화(obfuscation)가 진행되기 때문에, 난독화가 되지 말아야할 파일이 난독화가 되어, 해당 파일을 파악할 수 없어서 에러가 발생하는 클리셰가 있기 때문이다.

따라서 카카오 데브톡을 참고하여

app 모듈의 proguard-rules.pro 파일내에 에 다음과 같은 구문을 추가를 해주었다.

# kakao login
-keep class com.kakao.sdk.**.model.* { <fields>; }

보통

# kakao login
-keep class com.kakao.sdk.**.model.* { <fields>; }
-keep class * extends com.google.gson.TypeAdapter

이렇게 세트로 추가를 해주던데, 해당 프로젝트에선 gson 을 사용하지 않기 때문에 추가해주지 않았다.

하지만... 같은 에러가 여전히 발생하였다.
문제가 되는 키워드는 Missing class java.lang.invoke.StringConcatFactory~ 인 것을 추측할 수 있는데, 관련해서 추적 중인 이슈가 있는지 검색하여 issue Tracker 문서 다른 분들의 해결 방법들을 적용해보아도, 별 다른 소용이 없었다.

그렇게 위기를 겪던 도중, 에러의 다른 부분에 주목을 하였는데,

ERROR: Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in /home/runner/work/ilab-android/feature/login/build/outputs/mapping/release/missing_rules.txt.

해당 에러 구문은 에러의 원인과 그것에 대한 해결 방법 자체를 제안해주고 있었다!

https://stackoverflow.com/questions/70037537/proguard-missing-classes-detected-while-running-r8-after-adding-package-names-in

말 그대로 missing_rule 를 찾아다가 proguard 에 추가(복붙)하면 되는 것이다!

따라서 제안 해준대로 ./gradlew build 커멘드를 통해 생성된 outputs 파일 중 missing_rules.txt 내에 포함된 rules 들을 문제가 발생하고 있는 :feature-login 모듈의 proguard 에 추가해주었다.

missing_rules txt 파일엔

-dontwarn java.lang.invoke.StringConcatFactory

해당 rule 하나만 존재하였고, 따라서 :feature/login 모듈에 proguard-rules.pro txt 파일을 생성하고

:feature/login 모듈 (app 모듈에 추가해줄 소용 없음)

-dontwarn java.lang.invoke.StringConcatFactory

설레는 마음에 release 로 빌드를 해보았는데.. 오 이젠 빌드 타임에서 에러가 발생하진 않고 앱이 실행되는 것을 확인할 수 있었다. 해치웠나?

그러고 바로 런타임에 앱이 죽었다...

문제 해결

런타임에서 앱이 터지면, 에러를 남기기에 이를 확인해보았고, 다음과 같았다.

음.. 딱 보았을 땐, 도저히 감이 잡히질 않는 에러이다.
그래도 이를 통해 구글링 해본 결과, 비슷한 문제를 찾을 수 있었다.

왠 Retrofit? 지금 아직 쓰지도 않는데 무슨? 하고 지금 발생한 에러와 무관할 것이라 생각했는데 아니었다...

카카오 데브톡 을 참고 했을때, 지금 내 상황에서 발생한 에러와 살짝은 달랐지만, 덧글의 해결 방법을 적용해보았고,

(app 모듈 proguard-rules.pro)

# kakao login
-keep class com.kakao.sdk.**.model.* { <fields>; }

# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>

release build type 에서도 정상적으로, 앱이 빌드되고 실행되어 카카오 로그인이 정상적으로 수행되었고, CI 도 통과할 수 있었다.

이전엔

-keep class com.kakao.sdk.**.model.* { <fields>; } 

이 구문만 추가해줘도 별 이상이 없었던 것 같은데, 이번엔 추가적으로 해줘야할 것이 많았다. 멀티 모듈 환경에서의 proguard 설정 관련, gradle 관련한 지식의 필요성을 느끼게 된 하루였다.

그래도 CI 가 아니었으면 출시 직전 혹은 출시한 이후 알게되었을 치명적인 문제이기에, 다시한번 CI 의 중요성을 깨닫게 되었다.

kakao sdk 와 retrofit 과의 어떤 긴밀한 연관 관계가 있는 것인지.. 어려운 proguard...
-> 내부 코드를 확인해보았는데, retrofit을 사용하는 것을 확인할 수 있었다.

참고 자료)

R8 and ProGuard: Missing class error in data class that is using @Keep annotation

Proguard Missing classes detected while running R8 after adding package names in proguard-rules.pro

안드로이드 카카오로그인 연동시 method AuthApi.issueAccessToken 에러

https://github.com/square/retrofit/blob/trunk/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro

https://issuetracker.google.com/issues/250197571

profile
실력은 고통의 총합이다. Android Developer

3개의 댓글

comment-user-thumbnail
2024년 3월 18일

고생했는데 덕분에 해결했어요 ㅎㅎ
좋은 글 감사합니다 :)

1개의 답글
comment-user-thumbnail
2024년 3월 18일

고생했는데 덕분에 해결했어요 ㅎㅎ
좋은 글 감사합니다 :)

답글 달기