오늘도 더 나은 코드를 작성하였습니까?

안드로이드 빌드 과정(Android APK build process)를 이해하자! 본문

카테고리 없음

안드로이드 빌드 과정(Android APK build process)를 이해하자!

hik14 2024. 6. 15. 00:55

1. Complier 이란 무엇일까?

컴파일러(compiler 해석기, 번역기)는 특정 프로그래밍 언어로 쓰여 있는 문서를 다른 프로그래밍 언어로 옮기는 언어 번역 프로그램을 말한다. 컴파일러는 고급 프로그래밍 언어(java, kotlin)를 실행 프로그램으로 만들기 위해 저급 프로그래밍 언어(예, 어셈블리 언어, object 코드, machine code)로 바꾸는 데 사용된다.

 

.kt / .java 파일은 각각의 컴파일러에 의해 .class(Bytecode)로 변환이후, .jar로 패키징된다.

 

.class 자바 클래스 파일(Java class file)은 JVM에서 실행 가능한 자바 바이트코드를 포함하는 파일이다. 

Java 바이트코드는 => JVM(Java Virtual Machine)의 명령어 세트

 

JAR(Java Archive, 자바 아카이브)는 여러개의 자바 클래스 파일과, 클래스들이 이용하는 관련 리소스(텍스트, 그림 등) 및 메타데이터를 하나의 파일로 모아서 자바 플랫폼 응용 소프트웨어 라이브러리를 배포하기 위한 소프트웨어 패키지 파일 포맷이다.

 

Kotlin runtime  코틀린 자체 표준 라이브러리 클래스와 자바 API의 기능을 확장한 내용이 들어있다. 

코틀린 컴파일러로 컴파일한 코드는 코틀린 런타임 라이브러리에 의존성을 가지기 때문에 애플리케이션을 배포할 때는 코틀린 런타임을 넣어 같이 배포한다.

 

* JVM - 자바 바이트 코드를 플랫폼(window, mac, android..) 독립적으로 실행을 가능하게 해준다.

* JIT (Just-In-Time) 컴파일러는 런타임 시 바이트 코드를 원시 시스템 코드로 컴파일하여 Java 애플리케이션의 성능을 향상시키는 런타임 환경의 컴포넌트입니다

2. Android Build Process

Android build 란??

 

소프트웨어 빌드 프로세스는 소스 코드를 사용자에게 배포할 수 있는 독립 실행형 결과물로 변환하는 프로세스입니다.

Android 빌드 시스템은 앱 리소스 및 소스 코드를 컴파일하고 개발자가 테스트, 구축, 서명 및 배포할 수 있는 APK 또는 Android App Bundle(AAB)로 패키징합니다.

 

빌드의 결과물은 여러가지 일 수 있습니다.

App Project Build -  사용자에게 배포, 테스트 또는 출시할 수 있는 앱의 디버그나 출시 APK 또는 AAB를 생성합니다.

Third Party Liberary Build -  Android Archive 파일 (AAR) 또는 Java Archive 파일 (JAR) 라이브러리를 생성합니다.

 

Dalvik, ART

 

Android OS를 탑재한 모바일기기는 여러 제조사에 생산이 되며, 각 제조사에서 사용하는 CPU는 서로 다릅니다.

예를 들면,  arm, x86등 그렇기 때문에  CPU 아키텍처에 독립적으로 자바 바이트 코드를 실행하기 위해서 JVM이 필요했습니다.

 

JVM을 사용하면 다양한 유형의 CPU 아키텍처를 처리하는 문제가 해결됩니다. 하지만 JVM은 대용량 저장 공간과 전력을 갖춘 시스템용으로 설계된 반면 Android OS를 탑재한 모바일기기는 메모리와 배터리 용량이 비교적 낮습니다.

그래서 Google은 Dalvik이라는 Android JVM(AVM)을 채택했습니다.

 

Android 4.4(키켓)까지 Dalvik은 이용되었고 이후 점차  Android 5.0(롤리팝)이후 ART으로 대체됩니다!

Dalvik VS ART은 따로 설명하겠습니다.

 

Dalvik 바이트 코드가 포함된 단일 class.dex 파일로 변환을 하여 Anroid Run Time시 실행이 가능합니다.

 

 

빌드과정 한 눈에 보기

ApplicationModule

 

- Source code

src 폴더의 Java 및 Kotlin 파일

 

- Resource File

res 폴더에 있는 파일

 

- AIDL(Android Interface Definition Language) File

클라이언트와 서비스가 IPC를 사용하여 통신하기 위한 프로그래밍 인터페이스를 정의. *IPC(Inter-Process Communication) 프로세스 간 통신

Dependencies

 

- Library Modules

Java 또는 Kotlin 클래스, Android component 및 리소스가 포함되어 있지만 Asset은 포함되지 않습니다. 
라이브러리 프로젝트의 코드와 리소스는 애플리케이션과 함께 컴파일되고 패키징됩니다.
따라서 라이브러리 모듈은 컴파일 타임 Atrifact 간주될 수 있습니다.

 

- AAR Library

Android 앱 모듈에 대한 종속성으로 사용할 수 있는 AAR(Android Archive) 파일로 컴파일됩니다.
AAR 파일에는 Android 리소스와 매니페스트 파일이 포함될 수 있습니다.

Java 또는 Kotlin 클래스 및 메소드 외에도 Layout 및 Drawable 과 같은 공유 리소스로 묶을 수 있습니다.

 

- JAR Library

JAR은 Java 라이브러리이며 AAR과 달리 Android 리소스와 매니페스트를 포함할 수 없습니다.

 

Compiler( ) .dex로의 컴파일 프로세스 

 

javac(자바 컴파일러)

kotlinc(코틀린 컴파일러)

AAPT2(Android Asset Packging Tool)

R8, D8

Proguard 

 

- javac(자바 컴파일러), kotlinc(코틀린 컴파일러)

각각의 xx.java xx.kt 파일을 자바 바이트 코드로 변환한다.

 

- AAPT2(Android Asset Packging Tool)

AndroidManifest 및 리소스 파일을 단일 APK로 컴파일합니다.

AAPT2는 drawable 및 XML 파일과 같은 모든 Android Resource type의 컴파일을 지원합니다.

 

리소스 파일들은 해당 리소스 파일을 참조할 수 있는 ID가 부여되어 R.java라는 클래스안에 담기게 됩니다.

proguard-rules도 생성할 수 있습니다.


컴파일과 링크의 두 단계로 나누어집니다. 파일 하나만 변경된 경우 해당 파일 하나만 다시 컴파일하고 'link' 명령을 사용하여 모든 중간 파일을 연결하면 되므로 성능이 향상됩니다. 링크 단계에서는 컴파일 단계에서 생성된 모든 중간 파일(xx.flat)을 병합하고 하나의 .apk 파일을 출력합니다.

 

resources.arsc

위의 결과물인 .apk 파일에는 dex 파일이 포함되어 있지 않고, signed 되지 않았기 때문에 실행할 수 없는 APK입니다.

APK에는 AndroidManifest, 바이너리 XML 파일 및 resources.arsc가 포함되어 있습니다.

 

resources.arsc에는 패키지에 있는 resource에 대한 모든 메타정보(all of resource index)가 포함되어 있습니다.

 

- D8 and R8

Android Studio 3.1부터 D8이 기본 컴파일러로 지정되었습니다.
D8은 이전 dx와 비교할 때 더 나은 성능으로 더 작은 dex 파일을 생성할 수 있다.

 

*R8은 D8을 포함하고 있습니다.

R8이 나오기전에는  D8이 독립적으로 .class(자바 바이트 코드)를 .dex(DEX)코드로 변경해주는 역할

 

- D8

클래스 파일을 DEX 파일로 변환하는 dexer 역할

Java 8 기능을 Android에서 실행할 수 있는 바이트코드로 변환하는 desugar 역할

 

* desugar란?
Java의 새로운 버전이 계속 출시됨으로서, Java의 core에 새로운 API나 문법들이 추가가 되었습니다.

오래된 java.util.Date java.util.Calendar 보다는 Java 8의 java.time의 API 들인LocalDateTime , LocalDate , ZonedDateTime을 사용하는 것이 더 좋습니다. 하지만, MinimumSdkVersion에 따라 사용하지 못할 수 있습니다.

 

D8 컴파일러가 컴파일 과정에서 desugaring을 이용한다면, 가능합니다.

Sugaring - java.time 을 사용할 수 있게 해주는 것

Desugaring - D8이 MinimumSdkVersion 보다 낮은 기기에서 해석할 수 있는 .dex 코드로 변환시켜주는 것

 

 

- R8

dex 바이트코드를 더욱 최적화합니다.

최적화, 난독화, 사용하지 않는 클래스 제거와 같은 기능을 제공합니다.

코드를 분석해서 최종 APK파일의 크기를 줄이는 최적화를 진행

class.dex라는 하나의 DEX 파일을 출력합니다.

 

Code 축소

소스 코드나 라이브러리의 코드에서 실제로 사용되지 않는 클래스들, 필드들, 메소드들, 속성들을 제거합니다. 사용되지 않는 코드를 제거 하여 APK의 크기를 줄입니다. 또한, 1 개의 dex 파일에는 참조 라이브러리를 포함하여 적용 메소드 개수가 65,536개를 초과하면 빌드 오류가 발생합니다. 이를 방지하려면 애플리케이션의 종속성을 검토하고 R8을 사용하여 사용하지 않는 코드를 제거하거나 Multidex를 사용해야 한다.

 

Resource 축소

사용되지 않는 리소스들을 제거합니다.

 

Obfuscation(난독화)

앱 클래스, 메서드 및 필드의 이름을 단축하여 , DEX 파일 크기를 줄입니다.

mapping.txt 라는 매핑 파일(어떤 클래스의 이름이 어떻게 변경되었는 지)을 생성해준다.

난독화 도구중 하나인 Proguard에 대해서는 다른 글에서 다루겠습니다.

 

Signing the APK

 

모든 APK는 기기에 설치하거나 업데이트하기 전에 디지털 서명이 필요합니다.

디버그 빌드의 경우 Android Studio는 실행할 때 Android SDK 도구에서 생성된 디버깅 인증서(debug certificate)를 사용하여 앱에 자동으로 서명합니다. debug Keystore와 debug certificate는 자동으로 생성된다.

릴리스 빌드의 경우 키 저장소가 필요하며 키를 업로드하여 서명된 앱을 빌드합니다. apkbuilder를 사용하여 APK 파일을 만들고 cmd에서 zipalign을 사용하여 최종적으로 최적화하거나 Android Studio에서 '생성된 서명된 APK 옵션'을 사용하여 이를 처리하도록 할 수 있습니다.

 

Gradle에 설정상

debug일때는 zipAlig false

release일때는zipAlig true 이다.

 

keystore: .keystore 혹은 .jks의 확장자를 가진 파일로, key를 발급한다.

  • upload key는 플레이스토어에 앱을 등록할때 사용되는 key
  • signing key는 단말에 실제로 설치될 apk에 서명을 위해 사용되는 key

signing을 통하여 누가 만든 결과물인지 확인한다.