proguard는... 컴파일된 앱 패키지의 바이트 코드를 난독화해서 

디컴파일로 까(?)봤을 때 해독하기 엄청 어렵게 만드는 일종의 보안 장치다.

자바 스크립트 minifier와 유사한 도구라고 보면 된다.


>> 참조: https://developer.android.com/studio/build/shrink-code?hl=ko


상세한 설명이나 사용 방법은 인터넷 검색어 치면 수없이 나오니 굳이 나까지 또 언급할 필요는 없고.


[build.gradle]

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

    }
}


첫 번째로 중요한 것은 위 minifyEnabled값이 true인 경우에만 proguard가 적용된다는 점.

false인 경우에는 전혀 적용되지 않으니 적용하지 않겠다고 설정 자체를 지울 필요는 없다.


또, 위 참조에서 보듯 추가로 리소스 축소 옵션(shrinkResources)도 있지만... 

쓸데없이 이것저것 막 집어넣어서 만든 프로젝트가 아니라면 그닥 효과도 없고 의미도 없다.




두 번째로 중요한 것은, 아니 실질적으로 가장 중요한 것은

proguard-rules.pro 파일에서 예외처리하는 내용인데, 

사용된 라이브러리에 따라 적용할 일반 규칙은 인터넷에 수없이 중복 노출되어 있으니 참고하면 되고...


>> 참고: http://square.github.io/retrofit/


대표적으로 문제가 가장 많이 발생하는(필요한) 라이브러리인 retrofit2 적용 시의 예외 규칙은 

위 사이트에 링크된 내용(본문 중 아래쪽 "this file")을 그대로 적용하면 된다.


그런데, 그게 끝이 아니다.


retrofit2 라이브러리를 이용해서 웹 호출을 하는 경우, 

일반적으로 넘겨주거나 받는 파라미터 형식이 기본 형식이거나 JsonObject 형식인 경우에는

위 규칙 적용(+gson 규칙)으로 끝난다. 추가로 예외 처리해야 할 내용이 없기 때문이다.

그런데, 프로젝트 내에 정의된 클래스 형식으로 넘겨주거나 받는 형식이 있다면

반드시 예외 처리해서 난독화가 되지 않도록 해야 한다.


예를 하나 들자면,


[com.example.network.api]

@POST("")
Call<JsonObject> checkAppVerion(@Url String url,
                                @Header("os") String os,
                                @Query("mode") String mode);


이런 호출의 경우에는 문제가 없다. 모든 파라미터가 기본 형식이거나 gson 규칙으로 난독화 예외 처리가

이미 되어 있기 때문이다. (물론 proguard-rules.pro 파일에 해당 규칙들이 들어 있어야 하지만.)


그런데,

@POST("")
Call<UpdateInfoResponseVO> checkAppVerion(@Url String url,
                                @Header("os") String os,
                                @Query("mode") String mode);


이런 식으로 프로젝트 내부에 정의된 클래스 형식 UpdateInfoResponseVO가 사용된 경우라면

해당 retrofit2 호출 클래스와 사용 클래스(및 내부 클래스)가 모두 proguard 규칙에 예외 처리되어야 한다.


여기서 UpdateInfoResponseVO의 정의가 아래와 같이 되어 있다고 하면,

package com.example.vo;

public class UpdateInfoResponseVO {
    public String ResultCode;
    public String ResultMessage;
    public UpdateInfoVO Data;
}


UpdateInfoResponseVO 뿐만 아니라 내부 멤버 클래스인 UpdateInfoVO까지도 규칙에 추가되어야 한다.

(규칙에는 와일드카드 사용이 가능하므로 이 경우에는 두 클래스를 하나의 표현으로 묶을 수 있다.)


아래와 같은 방식으로.

-keep class com.example.network.api { *; }

-keep class com.example.vo.UpdateInfo* { *; }


왜 그런지는 앱을 패키징한 다음 Analyze로 열어보면 알 수 있다.

retrofit2에서는 Json 형태로 주거나 받는 데이터를 실제 클래스와 매핑/변환하는 작업을 처리하는데

사용된 클래스들이 난독화되어 있으면 그 때 전혀 파싱 처리를 못하여 오류를 발생하게 된다.

따라서 해당 클래스들은 반드시 예외 처리(-keep) 해 주어야 한다.


추가.

retrofit2 뿐만 아니라 Generic 형식이 사용된 경우 해당 클래스들은 모두 예외 처리해야 한다.

주로 Vector<Class_Type> 형식으로 사용되는데, 이 때 Class_Type은 모조리 예외 처리 대상.




Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]