개발+IT

Kotlin으로 Moshi 사용시 앱 난독화 오류 문제

결론부터 말하자면 잘못된 Annotation 사용 때문

Android 프로젝트에서 JSON을 다루는데 있어 가장 많이 쓰이는 라이브러리를 꼽자면 단연 GSON이다. 그리고 아마 그 다음으로 많이 쓰이는 것이 Moshi가 아닐까 싶은데, 개인적으로 Kotlin을 주 언어로 쓰는 프로젝트에서는 Moshi를 쓰는 편이 조금 더 편하지 않나 생각이 든다. 현재 개발중인 프로젝트에서도 Moshi를 쓰고 있는데, 빌드 설정에서 proguard와 minify를 적용한 채로 빌드를 하니 이런저런 오류를 뿜어내며 실패하는 것이 아닌가. 오류 메시지를 읽어보니 난독화가 적용된 클래스의 특정 필드를 인식하지 못하겠다 뭐 이런 내용이었다.

처음에는 빌드 설정, 그 중에서도 특히 proguard 설정이 문제일 것이라고 생각해서 이쪽에 있을법한 문제를 찾아보았는데(Moshi에서 자동으로 Adapter를 생성하는 data class를 난독화하지 않도록 한다던가...) 이 방법 저 방법 아무리 써봐도 해결되지 않는 게 아닌가. 결국 이거는 빌드 설정 문제는 아닌 것 같다는 결론을 내렸다. 그렇다면 도대체 왜 빌드가 안되는 것인지 판단하기 위해, 문제의 빌드 오류를 뿜어내는 난독화(가 적용된) 클래스가 무엇인지를 정확하게 알아내야 했다. 그리고 저 위에서 예상했던 대로 Moshi가 Json Deserialize하게 만든 data class가 문제였다. 대충 다음과 같이 구현되어있었다.

아마 Kotlin Annotation 문법에 익숙한 사람이라면 보자마자 문제를 눈치챘을 것이다. 근데 내가 별로 익숙하지 않다보니 문제가 생긴 것인데...결론부터 얘기하자면 Kotlin의 data class에서 필드를 선언할 때 생성자 내에서 선언하도록 되어있다 보니 생긴 문제였다. 무슨 소린고 하니, 각 필드에 선언했다고 생각한 Annotation @Json이 실제로는 생성자 내에 선언되어있다보니 JVM에서 저 @Json이 생성자 범위에서 적용되는 애라고 인식한 것이다. 실제로 Android Studio를 통해 위 코드를 Bytecode로 변환하고 다시 Java 코드로 디컴파일하면 다음과 같이 나온다.

위 코드에서 확인할 수 있다시피 @Json이 생성자에 갖다 박혀있는 것을 볼 수 있다. 그렇다면 어떻게 해야 Annotation이 필드에 적용되는 거라고 컴파일러에게 알려줄 수 있을까? 방법은 간단하다. @Json을 @field:Json으로 바꿔주면 된다. 바로 다음과 같이.

위와 같이 선언해두면 컴파일러에게 얘는 필드에 쓰이는 거다 라고 알려줄수 있다. 자세한 내용은 Kotlin 공식 문서 중 Annotation의 세부 항목인 Annotation Use-site Targets를 확인해보자.

여튼 저렇게 선언해두고 다시 Java 코드로 디컴파일해보면 각 필드가 다음과 같이 달라져있는 것을 볼 수 있다.

이제 다시 빌드해보면 아무런 문제 없이 빌드 성공하는 것을 볼 수 있다. 참...어떻게 보면 아주 초보적인 실수다. Java에서 Kotlin으로 넘어와서 개발하다보면 이래저래 비슷한 부분이 많다보니 제대로 파악하지 않은채 간과하고 개발하게 되는 지점이 있는데, 바로 이 경우가 그게 아닌가 싶다(변명 맞다).

여튼 이 역시 말한대로 초보적인 실수이나 뭐가 문제인지 알아내기 전까지는 그야말로 오리무중인 문제일 것이다. 만약 나와 같은 경우에 곤란함을 겪고 있는 사람이 있다면이 포스팅이 도움이 되길 바란다. 해피 코딩!

GAE BAL JA

구본본 님의 창작활동을 응원하고 싶으세요?

hell yeah, world
hell yeah, world
구독자 101
멤버십 가입

1개의 댓글

SNS 계정으로 간편하게 로그인하고 댓글을 남겨주세요.
새로운 알림이 없습니다.