Skip to content

학습‐desugaring이란

Lee JI HAK edited this page Nov 5, 2024 · 1 revision

desugaring이란?

desugaring을 한국어로 번역하면 설탕을 없애다 뜻이다.

프로그래밍에서는 syntatic sugar를 제거하여 기초적인 형태로 변환하는 과정을 의미한다.

Python을 예로 들어보면 list comprehension 이 있다.

다음과 같은 코드가 있다고 해보자

squares = [x**2 for x in range(5)]

이 코드는 0부터 4까지의 숫자를 제곱한 [0, 1, 4, 9, 16] 의 값을 반환한다.

그렇지만 이 문법을 일반 for loop 로도 바꿀 수 있다.

squares = []
for x in range(5):
    squares.append(x**2)

list comprehensionsyntatic sugar 역할을 하여 코드가 간결해보이지만 반복문을 사용하여 리스트를 생성하는 방식으로 변환될 수 있는 것이다.

이처럼 안드로이드에서의 desugaring도 마찬가지의 의미이다.

Android SDK24 에서는 java8의 일부 기능만 지원을 하고 어떤 것은 호환이 되지 않는다. 안드로이드 개발에서 사용하는 Java 버전은 항상 최신 버전을 따라가지 않기 때문에 이 기능을 호환이 가능하도록 해줘야 한다.

java8의 주요 기능으로는 Lambda Expression, Method References, java.time 등이 있다.

desugaring 과정은 아래 사진과 같이 진행된다.

image

AGP는 java8의 일부 기능을 기본적으로 지원해준다.

하지만 java.time 과 같은 기능을 사용하려면 Java 기능을 더 기본적인 형태로 변환하는 bytecode 변환 과정을 거쳐야한다.

이렇게 변환된 코드는 안드로이드가 지원하는 DEX 코드로 컴파일되어서 하위 버전의 안드로이드에서도 실행될 수 있다.

이 AGP의 desugar과정은 D8/R8 Compiler 수행한다. D8/R8 Compiler는 안드로이드의 byte코드를 DEX코드로 컴파일 하는 도구이다. 이 과정에서 java8 기능을 사용 가능하도록 변환해주기 때문에 자유롭게 사용할 수 있다.

설정도 매우 간단하다.

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled = true
    }

    compileOptions {
        // Flag to enable support for the new language APIs

        // For AGP 4.1+
        isCoreLibraryDesugaringEnabled = true
        // For AGP 4.0
        // coreLibraryDesugaringEnabled = true

        // Sets Java compatibility to Java 8
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    // For AGP 7.4+
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
    // For AGP 7.3
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.3")
    // For AGP 4.0 to 7.2
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.9")
}

이렇게 설정을 해주고 gradle sync를 해주면 된다.

공식문서에서는 뭔가 java8버전에 대한 설명이 대부분이여서 java8까지만 지원하는 것 같아서 테스트를 진행해봤다.

sourceCompatibilitytargetCompatibility 그리고 kotlin jvmTarget을 17로 바꿔보고서 진행을 했다.

아래와 같이 Java14버전부터 나오고 17부터 안정화된 switch case 문을 작성하였다.

Test.java

public class Test {
    public static int getDayValue(String day) {
        return switch (day) {
            case "MONDAY", "FRIDAY", "SUNDAY" -> 6;
            case "TUESDAY" -> 7;
            default -> 0;
        };
    }
}

그리고서 이 코드를

@Composable
fun Greeting(
    name: String,
    modifier: Modifier = Modifier,
) {
    val x = Test.getDayValue("MONDAY")
    Column {
        Text(
            text = "Hello $name!",
            modifier = modifier,
        )
        Text(
            text = "Hello $x!",
            modifier = modifier,
        )
        Text(
            text = "Hello $name!",
            modifier = modifier,
        )
        Button(
            onClick = {
                Log.d("TAG", "Button clicked")
            },
            modifier = modifier,
        ) {
            Text("Click me")
        }
    }
}

이렇게 사용해봤다.

이렇게 한뒤 API 26으로 실행결과

image

문제 없이 잘 나오는 것을 확인할 수 있었다.

마찬가지로 java17 버전부터 나온 record 문법을 사용해도 빌드는 잘 되는 것을 확인했다.

그런데 여러가지 실험을 하는 중에 java17 문법부터 추가된 stream.toList()가 실행이 안되는 것을 알 수 있었다. 이 부분에 대해서는 추측이지만 17버전 문법도 전부다 지원하지는 않는 것 같다.

Reference https://developer.android.com/studio/write/java8-support

Clone this wiki locally