티스토리 뷰

반응형

빠른 빌드를 위한 10가지 팁

1. 최신 안드로이드 그래들 플러그인을 사용합니다.
안드로이드 스튜디오 팀에서는 빌드 속도와 버그수정을 위해 그래들 플러그인을 계속 업데이트 하고 있습니다. 그래들 3.0 부터는 구글 메이븐 저장소를 통해 그래들이 배포됩니다. 따라서 메이븐 구글 저장소를 추가해주고, dependencygradle 3.0.0 혹은 그 이후 버전을 추가해줍니다.

buildscript {
    repository {
        jcenter()
        maven { url 'https://maven.google.com' }
    }
    dependency {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
    }
}

2. 레거시 멀티덱스를 피하도록 합니다.
멀티덱스 사용 시 minSdkVersion < 21인 경우 레거시 멀티덱스가 적용됩니다. 그리고 이 레거시 멀티덱스는 빌드 속도를 심각하게 다운 시킵니다. 안드로이드 스튜디오 2.3+ 부터는 런 버튼을 클릭해서 앱을 실행하면, 연결된 디바이스나 에물레이터의 API 버전을 감지해서 가능하면 네이티브 멀티덱스를 적용해준다고 합니다. 참고로 커맨드라인으로 빌드하는 경우엔 이렇게 자동으로 버전을 감지해서 최적화 해주는 기능은 동작하지 않습니다.

만약 프로덕트가 api 레벨 21 미만의 단말도 지원해야 한다면 아래와 같이 빌드 변형 구성을 이용해 개발용 빌드의 minSdkVersion을 21로 설정할 수 있습니다.
productFlavors {
    development {
        minSdkVersion 21
        ...
    } 
}

즉, 개발 할때만 잠시 minSdkVersion을 올려두는 것입니다.

3. 멀티 APK 사용을 피합니다.
멀티 APK는 ABI나 density에 따라 apk를 다르게 빌드하는 기능입니다. 한 프로젝트에 대해 여러 APK가 생성되지만, 각 빌드의 결과물로 나오는 APK 크기가 작아지는 장점이 있습니다. 하지만 개발중에는 필요없는 기능이기 때문에 멀티 APK 기능을 아래와 같이 끄기 바랍니다.

android {
    if (project.hasProperty('devBuild')) {
        splits.abi.enable = false
        splits.density.enable = false
    }
}

위의 그래들 빌드 스크립트를 보면 ‘devBuild’란 속성을 확인하는데 저 속성은 커맨드라인 빌드 시 아래와 같이 넘겨줍니다.

./gradlew santa-tracker:assembleDevelopmentDebug -PdevBuild

이걸 안드로이드 스튜디오에 적용한다면 preference -> Build, Execution, Deployment -> Compiler -> Command-line Option 에 -PdevBuild을 적어주면 됩니다.

4. 최소한의 리소스만 포함시킵니다.
앱이 다국어를 지원한다면 여러 스트링 리소스를 포함합니다. 다국어를 지원하지 않더라도 대부분의 앱은 하나 이상의 스크린 density를 지원하는 경우가 많습니다. 안드로이드 빌드 시 기본 설정은 모든 버전의 리소스를 빌드에 포함시키도록 되어있습니다. 하지만 아래와 같이 특정 버전의 리소스들만 포함시키도록 할 수 있습니다. 아래는 개발용 빌드에 특정 리소스만 포함 시키도록 하는 그래들 설정 예시입니다.

productFlavor {
    developement {
        minSdkVersion 21
        resConfigs ("en", "xxhdpi")
        ...
    }
}

5. 개발 빌드에는 PNG 최적화를 끕니다.

안드로이드 빌드 툴은 PNG 크기 최적화를 기본으로 수행합니다. 따리서 PNG 파일이 많으면 빌드 시 많은 시스템 자원을 사용하게 됩니다. 릴리즈 시에는 APK 크기를 줄여주므로 중요한 기능이지만 역시 개발중에는 별 필요 없는 기능입니다. 아래와 같이 그래들 빌드 스크립트를 이용해 설정을 끄기 바랍니다.

productFlavor {
    developement {
        minSdkVersion 21
        resConfigs ("en", "xxhdpi")
        aaptOptions.cruncherEnabled = false
        ...
    }
}

아니면 아예 webP 포맷을 사용하는 것도 좋은 방법입니다. webP는 PNG 파일보다 최대 25% 작은 크기를 갖는 포맷입니다. 안드로이드 스튜디오 2.3+ 부터는 IDE에서 PNG를 webP로 변환하는 기능을 지원합니다. 불투명 이미지는 안드로이드 API 15+, 투명도를 갖는 이미지는 API 18+부터 지원합니다.

6. 인스턴트 런을 적극 사용합니다.

안드로이드 스튜디오 3.0에 적용된 인스턴트 런은 처음 런칭된 2.0 때와 비교해 매우 진일보 하였습니다. 

참고로 안드로이드 스튜디오 3.0부터의 인스턴트 런은 연결된 단말의 버전이 21이상이어야 합니다.

안드로이스 스튜디오 3.0 이상에서는 인스턴트 런과 일반 빌드를 쉽게 구분하기 위해 런 버튼을 RunApply Changes 두 개로 분리했습니다.

Run 버튼을 클릭하면 콜드 스왑을 시도하고 앱은 재실행 됩니다. 반면 Apply Changes 버튼을 클릭하면 hot or warm swap을 시도합니다. Cold, hot, warm swap에 대한 내용은 아래 링크에서 자세히 알 수 있습니다.
https://developer.android.com/studio/run/

인스턴트 런을 실행하면 연결된 디바이스의 API, 스크린 density 등을 분석해서 자동으로 필요한 최적화를 수행합니다.

7. 의도치 않은 수정은 피합니다.
def buildDateTime = new Date().format('yyMMddHHmm').toInteger()

android {
    defaultConfig {
        versionCode buildDateTime
        ...
    }
}

위의 코드는 매 빌드가 유일한 버전코드를 갖도록 시간을 통해 버전 코드를 설정하고 있습니다. 별거 아닌 것 같은 코드이지만 이 코드는 매번 빌드를 할 때 마다 AndroidManifest를 변경합니다. 자세히 얘기하면 versionCode 같은 값들은 그래들 빌드 스크립트에 기술되어 있지만 실제 빌드가 되는 과정에서 AndroidManifest.xml에 합쳐집니다.

위의 코드를 통해 매번 빌드 할때마다 versionCode가 변경되며 이로 인해 AndroidManifest의 uses-sdk 속성도 매번  변경됩니다.

이  문제를 개선하기 위해서는 앞서 멀티 APK를 끄기 위한 방법을 이용하면 됩니다.

def buildDateTime = project.hasProperty('devBuild')? 100: new Date().format('yyMMddHHmm').toInteger()

android {
    ...
    defaultConfig {
        ...
        versionCode buildDateTime
        ...
    }
    ...
}

8. 다이나믹 버전 사용을 지양합니다.
다이나믹 버전은 아래와 같이 그래들에 외부 라이브러리를 임포트 할 때, 뒤에 +를 붙여서 가장 최근 버전의 라이브러리를 가져올 수 있게 하는 기능입니다.

이 기능이 라이브러리의 새 버전을 추가로 확인하게 만들기 때문에 의존성 결정(dependency resolution) 시간을 증가시킵니다.

android {
    dependencies {
        compile 'com.android.support:appcompat-v7:+'    
    }
}

또 하나의 문제는 이 설정이 코드의 수정이 전혀 없더라도 라이브러리의 새 버전이 나오면 빌드가 달라지게 한다는 것 입니다. 따라서 다이나믹 버전의 사용은 자제하는게 좋습니다.

9. 메모리 설정을 잘 해줍니다.
그래들에 할당하는 메모리
#gradle.property 파일
org.gradle.jvmargs=-Xmx1536m

덱스 처리 시 사용하는 메모리
#build.gradle 파일
dexOptions {
    javaMaxHeapSize = "4g"
}

그래들에 할당하는 메모리의 적정량은 프로젝트 마다 다릅니다. 무조건 크다고 좋은 것이 아니며, 무작정 메모리를 많이 할당하면 오히려 성능이 떨어질 수도 있습니다. 본인 시스템의 메모리 용량에 따라 잘 맞춰서 설정해야 합니다.

두번째는 덱스 프로세스의 자바 힙 크기를 설정하는 방법입니다. 덱스 프로세스가 기존에는 out-process로 동작했으나 안드로이드 스튜디오 2.1 부터 기본 값이 in-process로 변경되어 해당 설정은 이제 의미가 없습니다. 따라서 그냥 지우기 바랍니다.

10. 그래들 캐시를 사용합니다.

그래들의 새 캐싱 메카니즘 설정으로 모든 작업 결과를 캐시할 수 있습니다. 안드로이드 스튜디오 2.3에 소개됐던 빌드 캐시와 다른 점은 빌드 캐시는 pre-dexed external libararies만 캐시하는데 이것은 가장 최근 빌드 뿐만 아니라 이전 빌드에 대한 캐시도 가지고 있습니다. 또한 브랜치를 오가며 빌드하는 경우에도 캐시가 되고 캐싱된 것을 배포 할 수도 있습니다. 아래와 같이 해당 옵션을 켜 주시기 바랍니다.

# Set this in gradle.properties
org.gradle.caching=true


반응형
댓글
공지사항
최근에 올라온 글