본문 바로가기
Kotlin/What's new

[Kotlin 번역] What's new in Kotlin 1.8.0

by 노력남자 2023. 9. 17.
반응형

2022년 12월 28일

 

Kotlin 1.8.0 릴리스가 출시되었으며, 주요 하이라이트는 다음과 같습니다:

  • JVM용 새로운 실험적 함수: 디렉터리 내용을 재귀적으로 복사하거나 삭제하는 기능 추가
  • kotlin-reflect 성능 향상
  • 더 나은 디버깅 경험을 위한 새로운 -Xdebug 컴파일러 옵션 추가
  • kotlin-stdlib-jdk7 및 kotlin-stdlib-jdk8이 kotlin-stdlib로 통합
  • Objective-C/Swift 상호 운용성 개선
  • Gradle 7.3과의 호환성


IDE 지원


Kotlin 1.8.0을 지원하는 Kotlin 플러그인은 다음 IDE에서 사용 가능합니다:

 


IntelliJ IDEA 2022.3에서는 IDE 플러그인을 업데이트하지 않고도 프로젝트를 Kotlin 1.8.0으로 업데이트할 수 있습니다.

IntelliJ IDEA 2022.3에서 기존 프로젝트를 Kotlin 1.8.0으로 마이그레이션하려면 Kotlin 버전을 1.8.0으로 변경하고 Gradle 또는 Maven 프로젝트를 다시 가져와야 합니다.

 

Kotlin/JVM


버전 1.8.0부터 컴파일러는 JVM 19에 해당하는 바이트코드 버전의 클래스를 생성할 수 있습니다. 이 새로운 언어 버전에는 다음이 포함되어 있습니다:

  • JVM 어노테이션 타겟 생성을 끄는 컴파일러 옵션
  • 최적화를 비활성화하기 위한 새로운 -Xdebug 컴파일러 옵션
  • 이전 백엔드 제거
  • 롬복의 @Builder 어노테이션 지원

TYPE_USE 및 TYPE_PARAMETER 어노테이션 타겟 생성을 비활성화할 수 있는 기능


Kotlin 어노테이션이 Kotlin 타겟 중 하나로 TYPE를 포함하는 경우, 해당 어노테이션은 Java 어노테이션 타겟 목록에서 java.lang.annotation.ElementType.TYPE_USE로 매핑됩니다. 마치 TYPE_PARAMETER Kotlin 타겟이 java.lang.annotation.ElementType.TYPE_PARAMETER Java 타겟으로 매핑되는 것과 같습니다. 이는 API 레벨이 26 미만인 Android 클라이언트에 대해 문제가 됩니다. 이러한 타겟이 API에 없기 때문입니다.

Kotlin 1.8.0부터는 새로운 컴파일러 옵션 -Xno-new-java-annotation-targets를 사용하여 TYPE_USE 및 TYPE_PARAMETER 어노테이션 타겟 생성을 회피할 수 있습니다.


새로운 컴파일러 옵션으로 최적화 비활성화


Kotlin 1.8.0은 새로운 -Xdebug 컴파일러 옵션을 추가하여 최적화를 비활성화할 수 있게 했습니다. 현재로서는 이 옵션이 코루틴에 대한 "최적화됨" 기능을 비활성화합니다. 미래에는 더 많은 최적화 기능을 추가한 후 이 옵션은 이러한 최적화도 비활성화할 것입니다.

"최적화됨" 기능은 suspend 함수를 사용할 때 변수를 최적화합니다. 그러나 최적화된 변수가 있는 코드는 변수의 값을 확인할 수 없으므로 최적화된 변수가 포함된 코드를 디버깅하기 어렵습니다.

이 옵션은 절대로 프로덕션 환경에서 사용하지 마십시오. -Xdebug를 통해 이 기능을 비활성화하면 메모리 누수가 발생할 수 있습니다.

이전 백엔드 제거


Kotlin 1.5.0에서 IR 기반 백엔드가 안정적으로 지원되면서 Kotlin 1.4.*의 이전 백엔드가 폐기되었다고 발표했습니다. Kotlin 1.8.0에서는 이전 백엔드를 완전히 제거했습니다. 따라서 컴파일러 옵션인 -Xuse-old-backend 및 Gradle useOldBackend 옵션도 제거되었습니다.

롬복의 @Builder 어노테이션 지원


커뮤니티에서 Kotlin Lombok: Support generated builders (@Builder) YouTrack 이슈에 대해 충분한 투표가 많이 들어와서 @Builder 어노테이션을 지원하게 되었습니다.

아직 @SuperBuilder 또는 @Tolerate 어노테이션을 지원할 계획은 없지만, 충분한 사람들이 @SuperBuilder 및 @Tolerate 이슈에 투표한다면 다시 고려할 것입니다.

롬복 컴파일러 플러그인을 구성하는 방법을 알아보세요.

 

Kotlin/Native


Kotlin 1.8.0은 Objective-C 및 Swift 상호 운용성 변경, Xcode 14.1 지원 및 CocoaPods Gradle 플러그인 개선 사항을 포함하고 있습니다.


Xcode 14.1 지원


Kotlin/Native 컴파일러는 이제 최신 안정 버전인 Xcode 14.1을 지원합니다. 호환성 개선 사항은 다음과 같습니다.

  • watchOS 대상의 watchosDeviceArm64 프리셋이 추가되었으며, ARM64 플랫폼에서 Apple watchOS를 지원합니다.
  • Kotlin CocoaPods Gradle 플러그인은 이제 Apple 프레임워크의 기본값으로 비트코드 임베딩이 없습니다.
  • Apple 대상을 위한 Objective-C 프레임워크 변경 사항을 반영하기 위해 플랫폼 라이브러리가 업데이트되었습니다.

 

개선된 Objective-C/Swift 상호 운용성


Kotlin을 Objective-C 및 Swift와 더 상호 운용 가능하게 만들기 위해 세 가지 새로운 어노테이션이 추가되었습니다.

- @ObjCName: Kotlin 선언을 Swift 또는 Objective-C에서의 보다 의미 있는 이름으로 지정할 수 있습니다. Kotlin 선언을 이름을 바꾸는 대신 더 의미 있는 Swift 또는 Objective-C 이름으로 지정할 수 있습니다.

 

이 어노테이션은 Kotlin 컴파일러에게 이 클래스, 프로퍼티, 매개변수 또는 함수에 대한 사용자 지정 Objective-C 및 Swift 이름을 사용하도록 지시합니다.

@ObjCName(swiftName = "MySwiftArray")
class MyKotlinArray {
    @ObjCName("index")
    fun indexOf(@ObjCName("of") element: String): Int = TODO()
}

// Usage with the ObjCName annotations
let array = MySwiftArray()
let index = array.index(of: "element")


- @HiddenFromObjC: Kotlin 선언을 Objective-C에서 숨길 수 있습니다. 이 어노테이션은 Kotlin 컴파일러에게 함수나 프로퍼티를 Objective-C 및 Swift에 내보내지 않도록 지시합니다. 이로써 Kotlin 코드를 Objective-C 및 Swift 친화적으로 만들 수 있습니다.

-  @ShouldRefineInSwift: Kotlin 선언을 Swift에서 작성된 래퍼로 대체하는 데 유용합니다.

 

이 어노테이션은 Kotlin 컴파일러에게 생성된 Objective-C API에서 함수 또는 프로퍼티를 swift_private로 표시하도록 지시합니다. 이러한 선언은 __ 접두사를 받아 Swift 코드에서는 보이지 않게 됩니다.

 

여전히 Swift 코드에서 이러한 선언을 사용하여 Swift 친화적 API를 만들 수는 있지만, 예를 들어 Xcode의 자동 완성에서 제안되지 않을 것입니다.

Objective-C 선언을 Swift에서 미세 조정하는 자세한 내용은 공식 Apple 문서를 참조하십시오.


이러한 새 어노테이션은 옵트인(opt-in)이 필요합니다.

Kotlin 팀은 이러한 어노테이션을 구현한 Rick Clephas에게 큰 감사를 표합니다.


CocoaPods Gradle 플러그인에서 기본적으로 동적 프레임워크 사용


Kotlin 1.8.0부터는 CocoaPods Gradle 플러그인에 의해 등록된 Kotlin 프레임워크가 기본적으로 동적으로 연결됩니다. 이전의 정적 구현은 Kotlin Gradle 플러그인의 동작과 일관성이 없었습니다.

 

kotlin {
    cocoapods {
        framework {
            baseName = "MyFramework"
            isStatic = false // Now dynamic by default
        }
    }
}


기존 프로젝트에서 정적 링킹 유형을 사용하고 Kotlin 1.8.0으로 업그레이드하거나 링킹 유형을 명시적으로 변경하면 프로젝트 실행 중에 오류가 발생할 수 있습니다. 이를 해결하기 위해 Xcode 프로젝트를 닫고 Podfile 디렉터리에서 `pod install`을 실행하십시오.

자세한 정보는 CocoaPods Gradle 플러그인 DSL 참조를 참조하십시오.

 

Kotlin Multiplatform: 새로운 Android 소스 세트 레이아웃

 

Kotlin 1.8.0에서는 이전의 디렉터리 네이밍 스키마를 대체하는 새로운 Android 소스 세트 레이아웃을 소개합니다. 이전 레이아웃은 여러 가지 방법으로 혼란스러운 디렉터리 이름을 가지고 있습니다.

현재 레이아웃에서 만들어진 두 개의 androidTest 디렉터리를 고려해 보겠습니다. 하나는 KotlinSourceSets에 대한 것이고 다른 하나는 AndroidSourceSets에 대한 것입니다.

  • 이들은 서로 다른 의미를 가지고 있습니다. Kotlin의 androidTest는 unitTest 타입에 속하고, Android의 androidTest는 integrationTest 타입에 속합니다.
  • 이들은 혼란스러운 SourceDirectories 레이아웃을 만듭니다. src/androidTest/kotlin은 UnitTest를 가지고 있고, src/androidTest/java는 InstrumentedTest를 가지고 있습니다.
  • 또한 KotlinSourceSets와 AndroidSourceSets는 Gradle 구성에 대해 유사한 네이밍 스키마를 사용하므로 결과적으로 두 소스 세트의 androidTest에 대한 구성이 동일합니다. androidTestImplementation, androidTestApi, androidTestRuntimeOnly 및 androidTestCompileOnly와 같습니다.


이와 같은 기존 문제와 다른 문제를 해결하기 위해 새로운 Android 소스 세트 레이아웃을 도입했습니다. 이러한 두 레이아웃 간의 주요 차이점 중 일부는 다음과 같습니다:


KotlinSourceSet 네이밍 스키마

 

 

{AndroidSourceSet.name}은 다음과 같이 {KotlinSourceSet.name}에 매핑됩니다.

 


소스 디렉토리

 

 

{AndroidSourceSet.name}은 다음과 같이 {SourceDirectories included}에 매핑됩니다.

 

 

AndroidManifest.xml 파일의 위치

 

 

{AndroidSourceSet.name}은 {AndroidManifest.xml location}에 매핑됩니다.

 

 

Android와 공통 테스트 간의 관계


새 Android 소스 세트 레이아웃은 Android-instrumented 테스트(새 레이아웃에서는 androidInstrumentedTest로 이름이 변경됨)와 공통 테스트 간의 관계를 변경합니다.

이전에는 androidAndroidTest와 commonTest 간에 기본 dependsOn 관계가 있었습니다. 실제로는 다음과 같은 의미를 가졌습니다.

  • commonTest의 코드가 androidAndroidTest에서 사용 가능했습니다.
  • commonTest에서의 expect 선언은 androidAndroidTest에서 해당하는 actual 구현을 가져야 했습니다.
  • commonTest에서 선언된 테스트는 Android instrumented 테스트로 실행되었습니다.


새 Android 소스 세트 레이아웃에서는 기본적으로 dependsOn 관계가 추가되지 않습니다. 이전 동작을 선호하는 경우 build.gradle.kts 파일에서 이 관계를 수동으로 선언하십시오.

kotlin {
    // ...
    sourceSets {
        val commonTest by getting
        val androidInstrumentedTest by getting {
            dependsOn(commonTest)
        }
    }
}


Android 플레이버 지원


이전에 Kotlin Gradle 플러그인은 디버그와 릴리스 빌드 유형 또는 데모 및 풀 같은 사용자 정의 플레버에 해당하는 Android 소스 세트에 해당하는 소스 세트를 즉시 만들었습니다. 이러한 소스 세트는 val androidDebug by getting { ... }와 같은 구문을 통해 액세스할 수 있게 했습니다.

새 Android 소스 세트 레이아웃에서는 이러한 소스 세트가 afterEvaluate 단계에서 생성됩니다. 따라서 이러한 표현식은 유효하지 않아 org.gradle.api.UnknownDomainObjectException: KotlinSourceSet with name 'androidDebug' not found와 같은 오류가 발생합니다. 이를 해결하기 위해 build.gradle.kts 파일에서 새 invokeWhenCreated() API를 사용하십시오.

kotlin {
    // ...
    sourceSets.invokeWhenCreated("androidFreeDebug") {
        // ...
    }
}


설정 및 준비


새 레이아웃은 향후 릴리스에서 기본값이 될 것입니다. 지금이라도 다음 Gradle 옵션을 사용하여 활성화할 수 있습니다.

kotlin.mpp.androidSourceSetLayoutVersion=2


새 레이아웃은 Android Gradle 플러그인 7.0 이상에서 지원되며 Android Studio 2022.3 이상에서 지원됩니다.

이전 Android 스타일 디렉터리의 사용은 더 이상 권장되지 않습니다. Kotlin 1.8.0은 현재 레이아웃에 대한 경고를 도입하며 이러한 경고를 다음 Gradle 속성으로 억제할 수 있습니다.

kotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true

 

Kotlin/JS

 

Kotlin 1.8.0은 JS IR 컴파일러 백엔드를 안정화하고 JavaScript 관련 Gradle 빌드 스크립트에 새로운 기능을 제공합니다.


안정화된 JS IR 컴파일러 백엔드


이 릴리스부터 Kotlin/JS 중간 표현(IR 기반) 컴파일러 백엔드가 안정화되었습니다. 모든 세 개의 백엔드에 대한 인프라를 통합하는 데 시간이 걸렸지만, 이제 Kotlin 코드에 대해 동일한 IR을 사용하여 작동합니다.

안정화된 JS IR 컴파일러 백엔드의 결과로 이제 이전 백엔드는 더 이상 사용되지 않습니다.

안정된 JS IR 컴파일러와 함께 증분 컴파일이 기본으로 활성화되었습니다.

아직 이전 컴파일러를 사용 중인 경우 이전 백엔드에서 새로운 백엔드로 프로젝트를 전환하려면 마이그레이션 가이드를 참조하십시오.


yarn.lock 파일이 업데이트되었음을 보고하는 새로운 설정


yarn 패키지 매니저를 사용하는 경우, CI 빌드 프로세스 중에 yarn.lock 파일이 무음으로 변경되었을 때 알림을 받고 싶다면 세 가지 새로운 특수 Gradle 설정을 사용할 수 있습니다.

이러한 세 가지 새 Gradle 속성은 다음과 같습니다.

  • YarnLockMismatchReport: yarn.lock 파일의 변경 내용을 어떻게 보고할지 지정합니다. 다음 중 하나의 값 중 하나를 사용할 수 있습니다.
    • FAIL: 해당 Gradle 작업 실패. 이것이 기본값입니다.
    • WARNING: 경고 로그에 변경 내용에 대한 정보를 작성합니다.
    • NONE: 보고를 비활성화합니다.
  • reportNewYarnLock: 최근에 생성된 yarn.lock 파일에 대한 보고를 명시적으로 보고합니다. 기본적으로 이 옵션은 비활성화되어 있습니다. 첫 시작에서 새 yarn.lock 파일을 생성하는 것이 일반적인 관행입니다. 이 옵션을 사용하여 파일이 리포지토리에 커밋되었는지 확인할 수 있습니다.
  • yarnLockAutoReplace: Gradle 작업을 실행할 때마다 yarn.lock을 자동으로 대체합니다.


이러한 옵션을 사용하려면 build.gradle.kts 빌드 스크립트 파일을 다음과 같이 업데이트하십시오.

import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension

rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
    rootProject.the<YarnRootExtension>().yarnLockMismatchReport =
        YarnLockMismatchReport.WARNING // NONE | FAIL
    rootProject.the<YarnRootExtension>().reportNewYarnLock = false // true
    rootProject.the<YarnRootExtension>().yarnLockAutoReplace = false // true
}


Gradle 속성 파일에 브라우저용 테스트 대상 추가


Kotlin 1.8.0부터 Gradle 속성 파일에서 다른 브라우저를 위한 테스트 대상을 설정할 수 있습니다. 이렇게 하면 빌드 스크립트 파일에 모든 대상을 작성할 필요가 없으므로 빌드 스크립트 파일 크기를 줄일 수 있습니다.

모든 모듈에 대한 브라우저 목록을 정의하는 데 이 속성을 사용하고, 특정 모듈의 빌드 스크립트에 특정 브라우저를 추가할 수 있습니다.

예를 들어 Gradle 속성 파일에 다음 줄을 추가하면 모든 모듈에서 Firefox와 Safari에서 테스트를 실행합니다.

kotlin.js.browser.karma.browsers=firefox,safari


이 속성에 대한 전체 사용 가능한 값 목록은 GitHub에서 확인하십시오.

이 기능을 구현한 Martynas Petuška에게 Kotlin 팀은 매우 감사드립니다.


프로젝트에 CSS 지원 추가하는 새로운 방법


이 릴리스에서는 프로젝트에 CSS 지원을 추가하는 새로운 방법을 제공합니다. 이 변경 사항이 많은 프로젝트에 영향을 미칠 것으로 예상되므로 아래에 설명된대로 Gradle 빌드 스크립트 파일을 업데이트하는 것을 잊지 마십시오.

Kotlin 1.8.0 이전에는 cssSupport.enabled 속성을 사용하여 CSS 지원을 추가했습니다.

browser {
    commonWebpackConfig {
        cssSupport.enabled = true
    }
}


이제 cssSupport {} 블록에서 enabled.set() 메서드를 사용해야 합니다.

browser {
    commonWebpackConfig {
        cssSupport {
            enabled.set(true)
        }
    }
}

 

Gradle

 

Kotlin 1.8.0은 Gradle 버전 7.2 및 7.3을 완전히 지원합니다. 또한 최신 Gradle 릴리스까지의 Gradle 버전도 사용할 수 있지만, 이 경우 Deprecation 경고가 발생할 수 있거나 일부 새로운 Gradle 기능이 작동하지 않을 수 있습니다.

이 버전에는 다음과 같은 많은 변경 사항이 있습니다:

  • Kotlin 컴파일러 옵션을 Gradle 레이지 속성으로 노출
  • 최소 지원 버전 업그레이드
  • Kotlin 데몬 대체 전략 비활성화 기능
  • 전이 의존성에서 최신 kotlin-stdlib 버전 사용
  • 관련 Kotlin 및 Java 컴파일 작업의 JVM 대상 호환성 동등성을 확인하는 의무적인 체크
  • Kotlin Gradle 플러그인의 전이 의존성 해결
  • 폐기 및 제거


Kotlin 컴파일러 옵션을 Gradle 레이지 속성으로 노출


Kotlin 컴파일러 옵션을 Gradle 레이지 속성으로 노출하고 Kotlin 작업에 더 잘 통합하기 위해 다음과 같은 변경 사항이 있습니다:

  • 컴파일 작업에는 새로운 compilerOptions 입력이 있으며, 기존 kotlinOptions와 유사하지만 Gradle Properties API에서 Property를 반환 유형으로 사용합니다.

tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile::class.java) {
    compilerOptions {
        useK2.set(true)
    }
}

 

  • Kotlin 도구 작업 KotlinJsDce 및 KotlinNativeLink에는 새로운 toolOptions 입력이 있으며, 기존 kotlinOptions 입력과 유사합니다.
  • Kotlin Gradle 플러그인 API 아티팩트에는 두 개의 새로운 인터페이스가 있습니다:
    • org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask: compilerOptions 입력 및 compileOptions() 메서드를 가지고 있습니다. 모든 Kotlin 컴파일 작업은 이 인터페이스를 구현합니다.
    • org.jetbrains.kotlin.gradle.tasks.KotlinToolTask: toolOptions 입력 및 toolOptions() 메서드를 가지고 있으며, KotlinJsDce, KotlinNativeLink 및 KotlinNativeLinkArtifactTask와 같은 모든 Kotlin 도구 작업이 이 인터페이스를 구현합니다.
  • 몇 가지 compilerOptions는 String 유형 대신 새로운 유형을 사용합니다.
    • JvmTarget
    • KotlinVersion (apiVersion 및 languageVersion 입력에 대한)
    • JsMainFunctionExecutionMode
    • JsModuleKind
    • JsSourceMapEmbedMode

 

예를 들어, compilerOptions.jvmTarget.set(JvmTarget.JVM_11)와 같이 사용할 수 있으며 kotlinOptions.jvmTarget = "11" 대신에 이를 사용합니다.

kotlinOptions의 유형은 변경되지 않았으며 내부적으로 compilerOptions 유형으로 변환됩니다.

  • Kotlin Gradle 플러그인 API는 이전 릴리스와 이진 호환됩니다. 그러나 일부 내부 유형에 대한 추가 제네릭 매개변수가 포함된 소스 및 ABI(응용 프로그램 바이너리 인터페이스) 파괴 변경 사항이 있습니다. 중요한 변경 사항 중 하나는 KotlinNativeLink 작업이 더 이상 AbstractKotlinNativeCompile 작업을 상속하지 않는다는 것입니다.
  • KotlinJsCompilerOptions.outputFile 및 관련 KotlinJsOptions.outputFile 옵션은 더 이상 권장되지 않습니다. 대신 Kotlin2JsCompile.outputFileProperty 작업 입력을 사용하십시오.


Kotlin Gradle 플러그인은 Android 확장에 KotlinJvmOptions DSL을 여전히 추가합니다:

 

android {
    kotlinOptions {
        jvmTarget = "11"
    }
}


이것은 이 이슈의 범위 내에서 변경될 것이며 compilerOptions DSL이 모듈 수준에 추가될 때 변경될 것입니다.

 

제한 사항

 

kotlinOptions 작업 입력 및 kotlinOptions{...} 작업 DSL은 지원 모드에 있으며 향후 릴리스에서 폐지될 예정입니다. 개선 사항은 compilerOptions 및 toolOptions에만 적용됩니다.

kotlinOptions에서 setter 또는 getter를 호출하면 compilerOptions와 관련된 속성으로 위임됩니다. 이로 인해 다음과 같은 제한 사항이 발생합니다:

  • compilerOptions 및 kotlinOptions는 작업 실행 단계에서 변경할 수 없습니다 (아래 단락에서 하나의 예외를 참조하십시오).
  • freeCompilerArgs는 변경할 수 없는 List<String>을 반환하므로, 예를 들어 kotlinOptions.freeCompilerArgs.remove("something")와 같은 작업은 실패합니다.


kotlin-dsl 및 Jetpack Compose를 활성화한 Android Gradle 플러그인 (AGP)을 포함한 여러 플러그인은 작업 실행 단계에서 freeCompilerArgs 속성을 수정하려고 시도합니다. Kotlin 1.8.0에서는 이러한 문제에 대한 해결책을 추가했습니다. 이 해결책을 사용하면 빌드 스크립트나 플러그인에서 실행 단계에서 kotlinOptions.freeCompilerArgs를 수정할 수 있지만 빌드 로그에 경고가 표시됩니다. 이 경고를 비활성화하려면 새로운 Gradle 속성 kotlin.options.suppressFreeCompilerArgsModificationWarning=true를 사용하십시오. Gradle은 kotlin-dsl 플러그인 및 Jetpack Compose를 활성화한 AGP에 대한 수정을 추가할 예정입니다.

 

최소 지원 버전 업데이트


Kotlin 1.8.0부터 최소 지원 Gradle 버전은 6.8.3이며 최소 지원 Android Gradle 플러그인 버전은 4.1.3입니다.

사용 가능한 Gradle 버전과의 Kotlin Gradle 플러그인 호환성은 문서에서 확인할 수 있습니다.


Kotlin 데몬 후퇴 전략 비활성화 기능


kotlin.daemon.useFallbackStrategy라는 새로운 Gradle 속성이 도입되었으며, 기본값은 true입니다. 값이 false인 경우, 데몬의 시작 또는 통신 문제로 빌드가 실패합니다. 또한 Kotlin 컴파일 작업에서도 Gradle 속성보다 우선하는 useDaemonFallbackStrategy 속성이 새로 도입되었습니다. 컴파일을 실행하기에 충분한 메모리가 없는 경우, 로그에서 관련 메시지를 볼 수 있습니다.

Kotlin 컴파일러의 후퇴 전략은 데몬이 어떻게 실패하든 데몬 외부에서 컴파일을 실행하는 것입니다. Gradle 데몬이 실행 중인 경우 컴파일러는 "In process" 전략을 사용합니다. Gradle 데몬이 꺼져 있으면 컴파일러는 "Out of process" 전략을 사용합니다. 이 실행 전략에 대해 자세히 알아보려면 문서를 참조하십시오. 또한 무음으로 다른 전략으로의 후퇴는 시스템 리소스를 많이 소비하거나 결정론적이지 않은 빌드로 이어질 수 있으므로 자세한 내용은 YouTrack 이슈를 확인하십시오.


전달 의존성에서 최신 kotlin-stdlib 버전 사용


의존성에 Kotlin 버전 1.8.0 이상을 명시적으로 작성하는 경우, 예를 들어 implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")와 같이 작성하는 경우 Kotlin Gradle 플러그인은 해당 Kotlin 버전을 전달하는 kotlin-stdlib-jdk7 및 kotlin-stdlib-jdk8 의존성에 사용합니다. 이렇게 하면 서로 다른 stdlib 버전에서의 클래스 중복을 피할 수 있습니다. 이 동작을 비활성화하려면 kotlin.stdlib.jdk.variants.version.alignment Gradle 속성을 사용할 수 있습니다:

 

kotlin.stdlib.jdk.variants.version.alignment=false


버전 일치 문제가 발생하는 경우 Kotlin BOM에 대한 플랫폼 종속성을 빌드 스크립트에서 선언하여 모든 버전을 일치시킬 수 있습니다:

 

implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))


문서에서 다른 경우와 제안된 해결책에 대해 자세히 알아보세요.

관련된 Kotlin 및 Java 컴파일 작업의 JVM 대상 필수 확인


이 섹션은 소스 파일이 Kotlin만 포함하고 Java를 사용하지 않는 경우에도 JVM 프로젝트에 적용됩니다.

이 릴리스부터 kotlin.jvm.target.validation.mode 속성의 기본값은 Gradle 8.0+용으로 오류입니다 (이 버전의 Gradle은 아직 릴리스되지 않았습니다) 그리고 JVM 대상의 호환성 문제가 발생하면 플러그인이 빌드를 실패시킵니다.

기본값을 경고에서 오류로 변경하는 것은 Gradle 8.0으로의 원활한 마이그레이션을 위한 준비 단계입니다. 이 속성을 오류로 설정하고 도구 체인을 구성하거나 JVM 버전을 수동으로 일치시키도록 권장합니다.

대상의 호환성을 확인하지 않으면 어떤 문제가 발생할 수 있는지 자세히 알아보세요.


Kotlin Gradle 플러그인의 전달 의존성 해결


Kotlin 1.7.0에서는 Gradle 플러그인 변형을 지원하기 시작했습니다. 이 플러그인 변형으로 빌드 클래스패스에는 일반적으로 kotlin-gradle-plugin-api에 종속되는 Kotlin Gradle 플러그인의 다른 버전이 포함될 수 있습니다. 이로 인해 해결 문제가 발생할 수 있으며, kotlin-dsl 플러그인을 예로 들어 다음 해결책을 제안하고자 합니다.

Gradle 7.6의 kotlin-dsl 플러그인은 org.jetbrains.kotlin.plugin.sam.with.receiver:1.7.10 플러그인에 종속되며, 이 플러그인은 kotlin-gradle-plugin-api:1.7.10에 종속됩니다. org.jetbrains.kotlin.gradle.jvm:1.8.0 플러그인을 추가하는 경우 kotlin-gradle-plugin-api:1.7.10 전달 의존성으로 인해 버전 (1.8.0 및 1.7.10) 및 variant 속성의 org.gradle.plugin.api-version 값 간의 불일치로 인해 종속성 해결 오류가 발생할 수 있습니다. 이 문제를 해결하기 위해 버전을 일치시키기 위한 이 제안대로 종속성을 추가하십시오. 이 해결책은 Kotlin Gradle 플러그인 라이브러리 정렬 플랫폼을 구현할 때까지 필요할 수 있습니다.

dependencies {
    constraints {
        implementation("org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0")
    }
}


이 제약 조건은 전달 의존성의 빌드 클래스패스에서 org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0 버전을 사용하도록 강제합니다. Gradle 이슈 트래커에서 비슷한 경우에 대해 자세히 알아보세요.


폐기 및 제거 사항


Kotlin 1.8.0에서 다음과 같은 속성 및 메서드에 대한 폐기 주기가 계속됩니다:

  • Kotlin 1.7.0의 노트에서 KotlinCompile 작업은 아직 폐기 예정인 Kotlin 속성 classpath를 가지고 있었으며, 이 속성은 향후 릴리스에서 제거될 예정입니다. 이제 KotlinCompile 작업의 classpath 속성에 대한 폐기 수준을 오류로 변경했습니다. 모든 컴파일 작업은 컴파일에 필요한 라이브러리 목록에 libraries 입력을 사용합니다.
  • kapt.use.worker.api 속성을 제거했습니다. 이 속성을 사용하면 kapt를 Gradle Workers API를 통해 실행할 수 있었습니다. 기본적으로 kapt는 Kotlin 1.3.70부터 Gradle 워커를 사용하고 있으면 이 방법을 사용하는 것을 권장합니다.
  • Kotlin 1.7.0에서 kotlin.compiler.execution.strategy 속성의 폐기 주기를 시작했습니다. 이 릴리스에서는 이 속성을 제거했습니다. 다른 방법으로 Kotlin 컴파일러 실행 전략을 정의하는 방법에 대해 알아보세요.

 

표준 라이브러리


Kotlin 1.8.0:

  • JVM 컴파일 대상을 업데이트했습니다.
  • 일련의 기능을 안정화했습니다 - Java 및 Kotlin 간의 TimeUnit 변환, cbrt(), Java Optional 확장 기능.
  • 비교 가능하고 빼기 가능한 TimeMarks에 대한 미리보기를 제공합니다.
  • java.nio.file.path에 대한 실험적인 확장 기능을 포함합니다.
  • 개선된 kotlin-reflect 성능을 제공합니다.

 

JVM 컴파일 대상 업데이트


Kotlin 1.8.0에서 표준 라이브러리 (kotlin-stdlib, kotlin-reflect 및 kotlin-script-*)는 JVM 대상 1.8로 컴파일됩니다. 이전에는 표준 라이브러리가 JVM 대상 1.6으로 컴파일되었습니다.

Kotlin 1.8.0에서는 JVM 대상 1.6 및 1.7을 더 이상 지원하지 않습니다. 결과적으로 빌드 스크립트에서 kotlin-stdlib-jdk7 및 kotlin-stdlib-jdk8를 별도로 선언할 필요가 없으며, 이러한 아티팩트의 내용은 kotlin-stdlib에 병합되었습니다.

빌드 스크립트에서 명시적으로 kotlin-stdlib-jdk7 및 kotlin-stdlib-jdk8를 종속성으로 선언한 경우, kotlin-stdlib로 대체해야 합니다.

다른 버전의 stdlib 아티팩트를 혼합하는 것은 클래스 중복 또는 누락된 클래스로 이어질 수 있으므로 Kotlin Gradle 플러그인이 stdlib 버전을 일치시키는 데 도움을 줄 수 있습니다.


cbrt()


cbrt() 함수는 이제 double 또는 float의 실제 세제곱근을 계산할 수 있게 되어 안정화되었습니다.

 

import kotlin.math.*

fun main() {
    val num = 27
    val negNum = -num

    println("The cube root of ${num.toDouble()} is: " +
            cbrt(num.toDouble()))
    println("The cube root of ${negNum.toDouble()} is: " +
            cbrt(negNum.toDouble()))
}

 

Java 및 Kotlin 간의 TimeUnit 변환


kotlin.time의 toTimeUnit() 및 toDurationUnit() 함수는 이제 안정화되었습니다. Kotlin 1.6.0에서 실험적으로 도입된 이러한 함수는 Kotlin과 Java 간의 상호 운용성을 향상시킵니다. 이제 Java java.util.concurrent.TimeUnit와 Kotlin kotlin.time.DurationUnit 간에 쉽게 변환할 수 있습니다. 이러한 함수는 JVM에서만 지원됩니다.

 

import kotlin.time.*

// Java에서 사용하기 위해
fun wait(timeout: Long, unit: TimeUnit) {
    val duration: Duration = timeout.toDuration(unit.toDurationUnit())
    ...
}


비교 가능하고 빼기 가능한 TimeMarks


TimeMarks의 새로운 기능은 실험적이며 사용하려면 @OptIn(ExperimentalTime::class) 또는 @ExperimentalTime을 사용해야 합니다.

Kotlin 1.8.0 이전에는 여러 TimeMarks 및 현재 시간 간의 시간 차이를 계산하려면 한 번에 하나의 TimeMark에서만 elapsedNow()를 호출할 수 있었습니다. 이로 인해 두 개의 elapsedNow() 함수 호출이 정확히 동시에 실행될 수 없어 결과를 비교하기 어려웠습니다.

Kotlin 1.8.0에서는 이 문제를 해결하기 위해 동일한 시간 소스에서 TimeMarks를 빼고 비교할 수 있습니다. 이제 현재를 나타내는 새 TimeMark 인스턴스를 만들고 다른 TimeMark에서 빼면 이러한 계산에서 얻은 결과가 서로 상대적임이 보장됩니다.

val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
Thread.sleep(500) // 0.5초 동안 슬립
val mark2 = timeSource.markNow()

// 1.8.0 이전
repeat(4) { n ->
    val elapsed1 = mark1.elapsedNow()
    val elapsed2 = mark2.elapsedNow()

    // elapsed1과 elapsed2 사이의 차이는 elapsedNow() 호출 사이에
    // 경과된 시간에 따라 다를 수 있음
    println("Measurement 1.${n + 1}: elapsed1=$elapsed1, " +
            "elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
println()

// 1.8.0부터
repeat(4) { n ->
    val mark3 = timeSource.markNow()
    val elapsed1 = mark3 - mark1
    val elapsed2 = mark3 - mark2

    // 이제 경과된 시

간은 mark3을 기준으로 계산됩니다.
    // 이것은 고정된 값입니다.
    println("Measurement 2.${n + 1}: elapsed1=$elapsed1, " +
            "elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
// 시간 표식을 서로 비교하는 것도 가능합니다.
// mark2가 mark1보다 뒤에 캡처되었기 때문에 이것이 사실입니다.
println(mark2 > mark1)

 

이러한 새로운 기능은 다른 프레임을 나타내는 여러 TimeMark 간의 차이를 계산하거나 비교하려는 애니메이션 계산에서 특히 유용합니다.


디렉터리의 재귀적 복사 또는 삭제


이 java.nio.file.path에 대한 새로운 함수는 실험적입니다. 이를 사용하려면 @OptIn(kotlin.io.path.ExperimentalPathApi::class) 또는 @kotlin.io.path.ExperimentalPathApi을 사용해야 합니다. 또는 컴파일러 옵션 -opt-in=kotlin.io.path.ExperimentalPathApi를 사용할 수도 있습니다.

우리는 java.nio.file.Path에 대한 두 개의 새로운 확장 함수, copyToRecursively() 및 deleteRecursively()를 도입했습니다. 이를 사용하면 다음과 같이 디렉터리 및 그 내용을 재귀적으로 처리할 수 있습니다.

  • 디렉터리 및 내용을 다른 대상으로 복사합니다.
  • 디렉터리 및 내용을 삭제합니다.


이러한 함수는 백업 프로세스의 일부로 매우 유용할 수 있습니다.


오류 처리


copyToRecursively()를 사용하면 복사 중에 예외가 발생할 때 어떻게 처리해야 하는지를 onError 람다 함수를 오버로드하여 정의할 수 있습니다.

 

sourceRoot.copyToRecursively(destinationRoot, followLinks = false,
    onError = { source, target, exception ->
        logger.logError(exception, "Failed to copy $source to $target")
        OnErrorResult.TERMINATE
    })


deleteRecursively()를 사용할 때 파일 또는 폴더를 삭제하는 동안 예외가 발생하면 파일 또는 폴더가 건너뛰어집니다. 삭제가 완료된 후 deleteRecursively()는 발생한 모든 예외를 억제된 예외로 포함한 IOException을 throw합니다.

파일 덮어쓰기


copyToRecursively()가 대상 디렉터리에 이미 파일이 존재하는 것을 발견하면 예외가 발생합니다. 대신 파일을 덮어쓰려면 덮어쓰기를 인수로 사용하는 오버로드를 사용하고 true로 설정하십시오.

 

fun setUpEnvironment(projectDirectory: Path, fixtureName: String) {
    fixturesRoot.resolve(COMMON_FIXTURE_NAME)
        .copyToRecursively(projectDirectory, followLinks = false)
    fixturesRoot.resolve(fixtureName)
        .copyToRecursively(projectDirectory, followLinks = false,
            overwrite = true) // 공통 fixture을 수정합니다.
}


사용자 정의 복사 작업


사용자 정의 복사 로직을 정의하려면 copyAction을 추가 인수로 사용하는 오버로드를 사용하십시오. copyAction을 사용하면 선호하는 작업과 함께 람다 함수를 제공할 수 있습니다.

 

sourceRoot.copyToRecursively(destinationRoot, followLinks = false) { source, target ->
    if (source.name.startsWith(".")) {
        CopyActionResult.SKIP_SUBTREE
    } else {
        source.copyToIgnoringExistingDirectory(target, followLinks = false)
        CopyActionResult.CONTINUE
    }
}


이러한 확장 함수에 대한 자세한 정보는 API 참조를 참조하십시오.


Java Optional 확장 기능


Kotlin 1.7.0에서 도입된 확장 기능은 이제 안정화되었습니다. 이러한 함수는 Java의 Optional 클래스와 함께 사용하기를 단순화합니다. 이러한 함수는 JVM에서 Optional 객체를 언랩하고 변환하는 데 사용할 수 있으며 Java API와 더 간결하게 작업할 수 있습니다. 자세한 내용은 Kotlin 1.7.0에서 무엇이 새로운지를 참조하십시오.


개선된 kotlin-reflect 성능


kotlin-reflect가 JVM 대상 1.8로 컴파일되었다는 이점을 활용하여 내부 캐시 메커니즘을 Java의 ClassValue로 마이그레이션했습니다. 이전에는 KClass만 캐시했지만 이제 KType 및 KDeclarationContainer도 캐시합니다. 이러한 변경 사항은 typeOf()를 호출할 때 성능 개선을 가져왔습니다.

 

문서 업데이트


Kotlin 문서에는 몇 가지 주목할만한 변경 사항이 있습니다.

새롭고 개선된 페이지

 

  • Gradle 개요 - Gradle 빌드 시스템을 사용하여 Kotlin 프로젝트를 구성하고 빌드하는 방법, Kotlin Gradle 플러그인에서 사용 가능한 컴파일러 옵션, 컴파일 및 캐시에 대한 정보를 알아보세요.
  • Java와 Kotlin에서의 널 처리 - Java와 Kotlin의 널 가능성 변수를 처리하는 방식의 차이점을 살펴보세요.
  • Lincheck 가이드 - JVM에서 동시 알고리즘을 테스트하기 위한 Lincheck 프레임워크를 설정하고 사용하는 방법을 배워보세요.


새로운 및 업데이트된 튜토리얼

 

 

Kotlin 1.8.0 설치하기


IntelliJ IDEA 2021.3, 2022.1 및 2022.2에서는 Kotlin 플러그인을 자동으로 버전 1.8.0으로 업데이트하도록 제안합니다. IntelliJ IDEA 2022.3에서는 Kotlin 플러그인의 1.8.0 버전이 곧 업데이트의 마이너 버전에 번들로 제공됩니다.

IntelliJ IDEA 2022.3에서 기존 프로젝트를 Kotlin 1.8.0으로 마이그레이션하려면 Kotlin 버전을 1.8.0으로 변경하고 Gradle 또는 Maven 프로젝트를 다시 가져와야 합니다.

Android Studio Electric Eel (221) 및 Flamingo (222)에서는 Kotlin 플러그인 버전 1.8.0이 예정된 Android Studio 업데이트와 함께 제공됩니다. 새로운 커맨드 라인 컴파일러는 GitHub 릴리스 페이지에서 다운로드할 수 있습니다.


Kotlin 1.8.0 호환성 가이드


Kotlin 1.8.0은 기능 릴리스이므로 이전 버전의 언어로 작성된 코드와 호환되지 않을 수 있는 변경 사항을 가져올 수 있습니다. Kotlin 1.8.0의 호환성 가이드에서 이러한 변경 사항의 자세한 목록을 찾을 수 있습니다.

 

원문

 

https://kotlinlang.org/docs/whatsnew18.html

반응형

댓글