웬만한 Exception은 거의 만나봤다고 생각했지만 역시 한참 멀었다.
Unable to create call adapter for interface g5.h for method a.r
Call return type must be parameterized as Call<Foo> or Call<? extends Foo>
처음보는 에러를 만나게 되었고, 구글링을 통해 R8과 Retrofit에 대한 문제라는 것을 확인했다.
✅ R8 ?
R8은 기존 Proguard를 대체하는 공식 최적화 도구이다.
● 그럼 Proguard는 뭐에요?
주로 앱을 release 버전으로 배포할때 사용하며,
소스를 난독화 · 최적화하여 보안성을 높이고 용량을 줄여주는 도구다.
즉, 2가지 도구의 역할은 유사하며 기존에는 Proguard가 해오던 일을 이제는 R8이 한다고 생각하면 된다.
Proguard · R8은 개발자 입장에서 별도로 세팅할 필요 없이, AGP 버전에 따라 자동 적용된다.
build.gradle 파일에 다음과 같이 작성하여 사용한다.
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
isDebuggable = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
release 관련 옛 포스팅에 사용했던 예제이니 자세한 내용은 해당 포스팅을 참고 바란다 ↓
[Android] release 모드 빌드하기 / Build Variants / Signing Configs
당신의 앱에 별다른 설정을 하지 않았다면 항상 debug 모드로 빌드되고 있을 것이다.앱을 release 모드로 빌드하는 방법을 알아본다. ✅ APK 빌드하기 APK를 빌드하는 최종 목적은 Signing Conf
oscarstory.tistory.com
✅ 에러 발생 원인
R8은 AGP 3.4 버전부터 도입되었으며 Proguard와 호환 모드로 동작했기 때문에
Retrofit2와 같은 서드 파티 라이브러리들은 자동으로 최적화 대상에서 예외 처리되었다.
하지만 AGP 8.0 버전부터는 R8이 full mode로 기본 적용되고 기존의 Proguard는 동작하지 않는다.
R8의 full mode는 기존 Proguard와의 호환 모드보다 공격적으로 최적화가 진행되는데,
Retrofit에서 사용하는 제네릭 정보까지 제거하면서 Retrofit의 Call<Foo>가 단순히 Call로 변경되어
Retrofit이 메서드 반환 타입을 해석할 수 없어서 발생한 에러라고 해석할 수 있다.
안드로이드 스튜디오를 최신 버전으로 업데이트 하면서(호환 최소 버전 기준 때문에)
AGP 또한 버전업을 진행하게 되었고, 결국 자연스레 만날 수 밖에 없던 에러였던 것...
✅ 해결 방법
이 문제는 gradle.properties 파일에 다음 코드 한 줄만 작성해주면 의외로 간단히(?) 해결할 수 있다.
android.enableR8.fullMode=false
위에서 설명했던 full mode를 사용하지 않겠다는 방법이다.
이제 Retrofit으로 통신을 진행해도 위 에러가 발생하지 않는다.
...라고 할 뻔 했지만 정상적으로 해결되지는 않았다.
다른 사람들은 여기서 해결됐다는데 나만 억까당해
이 또한 성장의 발판이다.
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif)
✅ Proguard 규칙 추가
에러는 더 이상 발생하지 않지만, Retrofit을 통해 데이터를 서버로 전송하는 과정에서
데이터가 증발하는(?) 문제가 발생했다.
"test123" 이라는 문자열을 요청 파라미터에 담아서 전송했는데
서버쪽에서 받은 데이터는 빈 문자열("")이었던 것이다.
아무래도 R8의 full mode 옵션이 제대로 꺼지지 않았거나,
R8의 최적화가 너무나 강력하여 그걸 이겨내고 데이터를 삭제시킨 것으로 추정된다.
결국 proguard-rules.pro 파일을 열고 규칙을 직접 추가해줬다.
쉽게 말하자면, Retrofit 관련 클래스를 최적화에서 제외하는 방법이다.
# Retrofit 및 Gson 관련 클래스 보호
-keep class retrofit2.** { *; }
-keep class com.google.gson.** { *; }
# 직접 만들어준 Interface 및 DTO 관련 파일 보호
-keep interface com.example.testapp.ApiInterface.** { *; }
-keep class com.example.testapp.dto.** { *; }
# 제네릭 타입 제거 방지
-keepattributes Signature
위에 작성된 내용들은 R8에 의해 최적화 · 난독화되지 않는다.
그렇기에 데이터도 정상적으로 전송되는 것을 확인할 수 있었다.
AGP 버전업을 진행했을 때 발생한 에러를 해결해보았다.
역시 안드로이드 스튜디오 버전은 업그레이드할 때마다 멀쩡히 돌아갔던 적이 없던 것 같다 ㅎㅎ;
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/021.gif)
'Android (안드로이드)' 카테고리의 다른 글
[Android] Build Variants (1) - 빌드 변형 구성으로 앱 파생하기 / ProductFlavors / BuildTypes (1) | 2025.02.07 |
---|---|
[Android] SMS / 문자 메시지 앱 연결 / 문자 메시지 전송 (2) | 2025.01.17 |
[Android] 전화 앱 연결하기 / 내 앱에서 전화걸기 (0) | 2025.01.16 |
[Android] DrawerLayout / 서랍장 화면 (0) | 2025.01.15 |
[Android] Snackbar / 스낵바 사용해보기 (2) | 2025.01.14 |