Primary/Android

Android 개발 과정에서 Java가 사용되는 곳

해스끼 2023. 9. 23. 15:44

안드로이드 개발 과정에서 코드 자체는 Kotlin으로 작성하는 경우가 많아졌지만, 안드로이드 개발에서 Java가 완전히 퇴출된 건 아니다. 애초에 Kotlin이 JVM 언어이기도 하고, 코드를 작성하고 빌드하는 수많은 과정에서 Java가 여전히 사용되고 있기 때문이다.

 

이 글에서는 안드로이드 개발 과정 곳곳에서 보이는 Java 버전의 의미를 살펴본다.

Android Studio를 실행하는 Java

Android Studio와 Android Studio의 기반 IDE인 IntelliJ IDEA는 Java로 개발되었다. 따라서 Android Studio를 실행하려면 Java가 필요하다. 사실 IntelliJ 기반 IDE에는 해당 IDE를 개발하고 테스트하는 데 사용된 JBR(JetBrains Runtime)이라는 자바 런타임이 동봉되어 있다. 따라서 IDE를 실행할 때 JBR을 사용하는 것이 가장 좋다.

 

별다른 설정을 하지 않았다면 JBR이 기본적으로 사용된다. 다른 런타임을 직접 지정할 수도 있지만, 이 글에는 적지 않겠다. Android Studio Giraffe의 기본값은 jbr-17이다.

Gradle 빌드를 실행하는 JDK

Android Studio의 UI를 통해 Gradle 빌드를 실행하면 Android Studio 설정에서 지정한 JDK가 사용되며, 터미널에서 빌드를 실행한 경우 ``JAVA_HOME`` 환경 변수에 지정된 JDK가 사용된다. ``JAVA_HOME``이 정의되지 않았다면 ``PATH`` 환경변수의 ``java`` 커맨드를 통해 빌드가 실행된다.

 

빌드의 일관성을 위해 동일한 JDK를 사용하자. 환경 변수를 설정하는 방법은 다들 알 것이고, Android Studio에서 Gradle JDK를 설정하는 방법은 다음과 같다.

Gradle은 daemon이라는 프로세스를 통해 빌드를 실행한다. Daemon은 동일한 Gradle JDK로 빌드하는 한 계속 재사용될 수 있어 시간과 메모리를 절약할 수 있다. 다른 Gradle JDK로 빌드 작업을 실행하면 새로운 daemon이 만들어지므로 비효율적이다.

 

이 페이지를 참고하여 Android Gradle Plugin의 요구사항에 맞는 적절한 JDK를 고르자. 팀 프로젝트라면 팀원들 모두 동일한 Gradle JDK를 사용하는 것을 강력히 추천한다. JDK 버전 때문에 에러가 날 수도(또는 안 날수도) 있기 때문. 참고로 실화다.

코드에서 사용할 수 있는 Java API

안드로이드 앱에서는 JDK에 선언된 대부분의 API를 사용할 수 있지만, 모든 API를 사용할 수 있는 건 아니다. Android에서 사용할 수 있는 Java API의 집합을 Android SDK라고 한다. ``build.gradle``에서 볼 수 있는 ``compileSdk`` 변수가 바로 이 SDK 버전을 지정한다.

android {
    ...
    compileSdk 33
}

Android SDK는 하위호환성이 보장된다. 예를 들어 Android 14(API 34)부터는 JDK 17을 지원하지만, SDK 34 버전에는 JDK 11 API도 당연히 포함되어 있다.

 

어떤 API가 ``compileSdk``에는 포함되지만 ``minSdk``에는 포함되지 않는다면, ``desugar``라는 과정을 통해 해당 API를 ``compileSdk``보다 낮은 버전에서도 사용할 수 있다. 

소스 코드를 컴파일하는 JDK

Java toolchain JDK는 임의의 Java 코드를 컴파일하는 컴파일러를 포함한다. 이 JDK는 Kotlin 컴파일러와 테스트 코드를 실행할 때도 쓰인다.

 

Toolchain JDK는 기본적으로 Gradle을 실행할 때 쓰이는 JDK와 동일하다. 따라서 서로 다른 기기에서 빌드를 실행하면, 각각 서로 다른 JDK를 사용하여 빌드될 가능성이 있다. 위에서도 얘기했지만 여러 기기에서 일관된 결과를 얻으려면 빌드에 사용되는 JDK를 통일하는 것이 좋다. 팀원들과 상의하여 빌드에 사용할 JDK 버전을 하나로 통일하자.

 

Android 공식 문서에서는 추가로 toolchain 버전까지 명시하는 것을 강력하게 권장하고 있다. 앱에 Kotlin 코드가 포함되어 있다면 다음과 같이 명시할 수 있다.

kotlin {
    jvmToolchain(17)
}

Gradle JDK와 toolchain JDK는 서로 같은 버전을 사용하는 것이 좋지만, 이 둘의 목적은 전혀 다름을 기억하자. (Gradle 빌드 실행 vs. 코드 컴파일)

Java 코드에서 사용할 수 있는 language feature

Kotlin과는 관련없는 얘기이므로 앱에서 Java를 사용하지 않는다면 이 부분은 스킵해도 좋다.

 

Java 컴파일 과정에서 사용할 language feature는 ``sourceCompatibility`` 변수를 통해 지정할 수 있다.

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Java 바이트코드에서 사용될 수 있는 Java binary feature

Java와 Kotlin 코드를 컴파일한 ``.class`` 파일의 버전도 지정할 수 있다. Java 코드는 ``targetCompatibility`` 변수의 값을, Kotlin 코드는 ``jvmTarget`` 변수의 값을 따른다. ``targetCompatibility``의 기본값은 ``sourceCompatibility``이며, ``jvmTarget``의 기본값은 toolchain 버전이다.

android {
    compileOptions {
        targetCompatibility JavaVersion.VERSION_17 // Java
    }
    kotlinOptions {
        jvmTarget '17'                             // Kotlin
    }
}

Java가 지원하지 않아 Kotlin 자체적으로 구현하여 쓰던 기능을 이후의 Java 버전에서 지원하는 경우도 있다. 따라서 더 높은 ``jvmTarget`` 값을 사용하면 이런 API의 성능이 개선될 수도 있다.

 

웬만하면 위에서 설명한 모든 JDK를 동일한 것으로 사용하는 게 좋을 듯.

참고문헌

Java versions in Android builds  |  Android Studio  |  Android Developers

 

Java versions in Android builds  |  Android Studio  |  Android Developers

How to select which JDKs are used in your build.

developer.android.com