Kotlin 1.5.0의 새로운 기능
Kotlin 1.5.0은 새로운 언어 기능, 안정적인 IR 기반 JVM 컴파일러 백엔드, 성능 개선, 그리고 실험적 기능 안정화 및 오래된 기능 사용 중단과 같은 발전적인 변화를 도입합니다.
변경 사항에 대한 개요는 릴리스 블로그 게시물에서도 확인할 수 있습니다.
언어 기능
Kotlin 1.5.0은 1.4.30 미리 보기에서 소개되었던 새로운 언어 기능의 안정화 버전을 제공합니다:
이러한 기능에 대한 자세한 설명은 이 블로그 게시물과 Kotlin 문서의 해당 페이지에서 확인할 수 있습니다.
JVM 레코드 지원
자바는 빠르게 발전하고 있으며, 코틀린이 자바와 상호 운용성을 유지하도록 보장하기 위해 최신 기능 중 하나인 레코드 클래스에 대한 지원을 도입했습니다.
코틀린의 JVM 레코드 지원에는 양방향 상호 운용성이 포함됩니다:
- 코틀린 코드에서 자바 레코드 클래스를 속성을 가진 일반 클래스처럼 사용할 수 있습니다.
- 코틀린 클래스를 자바 코드에서 레코드로 사용하려면,
data
클래스로 만들고@JvmRecord
어노테이션을 붙이세요.
@JvmRecord
data class User(val name: String, val age: Int)
코틀린에서 JVM 레코드 사용에 대해 자세히 알아보기.
Sealed 인터페이스
이제 코틀린 인터페이스에 sealed
한정자를 사용할 수 있습니다. 이는 클래스에 작동하는 방식과 동일하게 인터페이스에도 작동합니다: sealed 인터페이스의 모든 구현은 컴파일 시점에 알려집니다.
sealed interface Polygon
예를 들어, 이 사실을 활용하여 모든 경우를 다루는 when
표현식을 작성할 수 있습니다.
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle -> // ...
is Triangle -> // ...
// else는 필요하지 않습니다 - 가능한 모든 구현이 포함됩니다
}
또한 sealed 인터페이스는 클래스가 하나 이상의 sealed 인터페이스를 직접 상속할 수 있으므로, 더 유연한 제한된 클래스 계층 구조를 가능하게 합니다.
class FilledRectangle: Polygon, Fillable
패키지 전체의 sealed 클래스 계층 구조
이제 sealed 클래스는 동일한 컴파일 단위 및 동일한 패키지의 모든 파일에 서브클래스를 가질 수 있습니다. 이전에는 모든 서브클래스가 동일한 파일에 있어야 했습니다.
직접적인 서브클래스는 최상위이거나 다른 이름이 지정된 클래스, 이름이 지정된 인터페이스 또는 이름이 지정된 객체 내부에 중첩될 수 있습니다.
sealed 클래스의 서브클래스는 적절하게 한정된 이름을 가져야 합니다 – 로컬 또는 익명 객체일 수 없습니다.
sealed 클래스 계층 구조에 대해 자세히 알아보기.
Inline 클래스
Inline 클래스는 값만 포함하는 값 기반 클래스의 하위 집합입니다. 메모리 할당으로 인한 추가 오버헤드 없이 특정 타입의 값을 위한 래퍼로 사용할 수 있습니다.
Inline 클래스는 클래스 이름 앞에 value
한정자를 사용하여 선언할 수 있습니다:
value class Password(val s: String)
JVM 백엔드는 특별한 @JvmInline
어노테이션도 필요로 합니다:
@JvmInline
value class Password(val s: String)
inline
한정자는 이제 경고와 함께 사용 중단(deprecated)되었습니다.
Kotlin/JVM
Kotlin/JVM은 내부 및 사용자 관련 측면에서 여러 개선 사항을 받았습니다. 그중 가장 주목할 만한 사항은 다음과 같습니다:
- 안정적인 JVM IR 백엔드
- 새로운 기본 JVM 대상: 1.8
- invokedynamic을 통한 SAM 어댑터
- invokedynamic을 통한 람다
- @JvmDefault 및 이전 Xjvm-default 모드 사용 중단
- Nullability 어노테이션 처리 개선
안정적인 JVM IR 백엔드
Kotlin/JVM 컴파일러용 IR 기반 백엔드가 이제 안정화되었으며 기본적으로 활성화됩니다.
Kotlin 1.4.0부터 IR 기반 백엔드의 초기 버전은 미리 보기로 제공되었으며, 이제 언어 버전 1.5
의 기본값이 되었습니다. 이전 백엔드는 이전 언어 버전에서 여전히 기본적으로 사용됩니다.
IR 백엔드의 이점과 향후 개발에 대한 자세한 내용은 이 블로그 게시물에서 확인할 수 있습니다.
Kotlin 1.5.0에서 이전 백엔드를 사용해야 하는 경우, 프로젝트의 설정 파일에 다음 줄을 추가할 수 있습니다:
- Gradle에서:
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions.useOldBackend = true
}
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useOldBackend = true
}
- Maven에서:
<configuration>
<args>
<arg>-Xuse-old-backend</arg>
</args>
</configuration>
새로운 기본 JVM 대상: 1.8
Kotlin/JVM 컴파일의 기본 대상 버전은 이제 1.8
입니다. 1.6
대상은 사용 중단되었습니다.
JVM 1.6용 빌드가 필요한 경우, 여전히 이 대상으로 전환할 수 있습니다. 방법 알아보기:
invokedynamic을 통한 SAM 어댑터
Kotlin 1.5.0은 이제 SAM(Single Abstract Method) 변환 컴파일을 위해 동적 호출(invokedynamic
)을 사용합니다:
- SAM 타입이 자바 인터페이스인 경우 모든 표현식에서
- SAM 타입이 코틀린 함수형 인터페이스인 경우 람다에서
새로운 구현은 LambdaMetafactory.metafactory()
를 사용하며, 컴파일 중에 보조 래퍼 클래스가 더 이상 생성되지 않습니다. 이는 애플리케이션 JAR의 크기를 줄여 JVM 시작 성능을 향상시킵니다.
익명 클래스 생성에 기반한 이전 구현 방식으로 되돌리려면, 컴파일러 옵션 -Xsam-conversions=class
를 추가하세요.
Gradle, Maven, 및 명령줄 컴파일러에서 컴파일러 옵션을 추가하는 방법을 알아보세요.
invokedynamic을 통한 람다
일반 Kotlin 람다를 invokedynamic으로 컴파일하는 기능은 실험적입니다. 언제든지 중단되거나 변경될 수 있습니다. 옵트인(자세한 내용은 아래 참조)이 필요하며, 평가 목적으로만 사용해야 합니다. YouTrack에 피드백을 주시면 감사하겠습니다.
Kotlin 1.5.0은 일반 코틀린 람다(함수형 인터페이스 인스턴스로 변환되지 않은)를 동적 호출(invokedynamic
)로 컴파일하는 실험적 지원을 도입합니다. 이 구현은 LambdaMetafactory.metafactory()
를 사용하여 더 가벼운 바이너리를 생성하며, 이는 런타임에 필요한 클래스를 효과적으로 생성합니다. 현재, 일반 람다 컴파일과 비교하여 세 가지 제한 사항이 있습니다:
- invokedynamic으로 컴파일된 람다는 직렬화할 수 없습니다.
- 이러한 람다에
toString()
을 호출하면 가독성이 떨어지는 문자열 표현이 생성됩니다. - 실험적인
reflect
API는LambdaMetafactory
로 생성된 람다를 지원하지 않습니다.
이 기능을 사용해 보려면 -Xlambdas=indy
컴파일러 옵션을 추가하세요. 이 YouTrack 티켓을 사용하여 피드백을 공유해 주시면 감사하겠습니다.
Gradle, Maven, 및 명령줄 컴파일러에서 컴파일러 옵션을 추가하는 방법을 알아보세요.
@JvmDefault 및 이전 Xjvm-default 모드 사용 중단
Kotlin 1.4.0 이전에는 @JvmDefault
어노테이션과 -Xjvm-default=enable
및 -Xjvm-default=compatibility
모드가 있었습니다. 이들은 Kotlin 인터페이스의 특정 비추상 멤버에 대한 JVM 기본 메서드를 생성하는 역할을 했습니다.
Kotlin 1.4.0에서 우리는 전체 프로젝트에 대한 기본 메서드 생성을 켜는 새로운 Xjvm-default
모드를 도입했습니다.
Kotlin 1.5.0에서는 @JvmDefault
와 이전 Xjvm-default 모드(-Xjvm-default=enable
및 -Xjvm-default=compatibility
)를 사용 중단합니다.
자바 상호 운용성의 기본 메서드에 대해 자세히 알아보기.
Nullability 어노테이션 처리 개선
코틀린은 nullability 어노테이션을 통해 자바의 타입 nullability 정보를 처리하는 것을 지원합니다. Kotlin 1.5.0은 이 기능에 대한 여러 개선 사항을 도입합니다:
- 의존성으로 사용되는 컴파일된 자바 라이브러리에서 타입 인수에 대한 nullability 어노테이션을 읽습니다.
- 다음 항목에 대해
TYPE_USE
대상을 가진 nullability 어노테이션을 지원합니다:- 배열
- 가변 인자(Varargs)
- 필드
- 타입 파라미터 및 그 경계(bounds)
- 기본 클래스 및 인터페이스의 타입 인수
- nullability 어노테이션이 타입에 적용 가능한 여러 대상을 가지고 있고, 이 대상 중 하나가
TYPE_USE
인 경우,TYPE_USE
가 선호됩니다. 예를 들어,@Nullable
이TYPE_USE
와METHOD
를 모두 대상으로 지원하는 경우, 메서드 시그니처@Nullable String[] f()
는fun f(): Array<String?>!
이 됩니다.
새롭게 지원되는 이러한 경우에 대해, 코틀린에서 자바를 호출할 때 잘못된 타입 nullability를 사용하면 경고가 발생합니다. 이러한 경우에 대한 엄격 모드(오류 보고 포함)를 활성화하려면 -Xtype-enhancement-improvements-strict-mode
컴파일러 옵션을 사용하세요.
null 안전성 및 플랫폼 타입에 대해 자세히 알아보기.
Kotlin/Native
Kotlin/Native가 이제 더 나은 성능과 안정성을 제공합니다. 주목할 만한 변경 사항은 다음과 같습니다:
성능 개선
1.5.0에서 Kotlin/Native는 컴파일과 실행 속도를 모두 향상시키는 일련의 성능 개선 사항을 받았습니다.
컴파일러 캐시는 이제 linuxX64
(Linux 호스트에서만) 및 iosArm64
대상의 디버그 모드에서 지원됩니다. 컴파일러 캐시를 활성화하면 첫 컴파일을 제외하고 대부분의 디버그 컴파일이 훨씬 빠르게 완료됩니다. 측정 결과, 테스트 프로젝트에서 약 200%의 속도 향상이 나타났습니다.
새로운 대상에 컴파일러 캐시를 사용하려면, 프로젝트의 gradle.properties
에 다음 줄을 추가하여 옵트인하세요:
linuxX64
용:kotlin.native.cacheKind.linuxX64=static
iosArm64
용:kotlin.native.cacheKind.iosArm64=static
컴파일러 캐시를 활성화한 후 문제가 발생하는 경우, 이슈 트래커인 YouTrack에 보고해 주세요.
다른 개선 사항은 Kotlin/Native 코드 실행 속도를 높입니다:
- 사소한 속성 접근자는 인라인 처리됩니다.
- 문자열 리터럴에 대한
trimIndent()
는 컴파일 중에 평가됩니다.
메모리 누수 검사기 비활성화
내장된 Kotlin/Native 메모리 누수 검사기가 기본적으로 비활성화되었습니다.
이 검사기는 원래 내부 사용을 위해 설계되었으며, 모든 경우의 누수를 찾는 것이 아니라 제한된 수의 경우에만 누수를 찾을 수 있습니다. 또한 나중에 애플리케이션 충돌을 유발할 수 있는 문제가 있는 것으로 밝혀졌습니다. 따라서 메모리 누수 검사기를 끄기로 결정했습니다.
메모리 누수 검사기는 여전히 특정 경우, 예를 들어 단위 테스트에 유용할 수 있습니다. 이러한 경우를 위해 다음 코드 줄을 추가하여 활성화할 수 있습니다:
Platform.isMemoryLeakCheckerActive = true
애플리케이션 런타임에 검사기를 활성화하는 것은 권장되지 않습니다.
Kotlin/JS
Kotlin/JS는 1.5.0에서 발전적인 변화를 받고 있습니다. 우리는 JS IR 컴파일러 백엔드를 안정화시키고 다른 업데이트를 제공하기 위한 작업을 계속하고 있습니다:
webpack 5로 업그레이드
Kotlin/JS Gradle 플러그인은 이제 webpack 4 대신 브라우저 대상에 webpack 5를 사용합니다. 이는 호환되지 않는 변경 사항을 가져오는 주요 webpack 업그레이드입니다. 사용자 지정 webpack 설정을 사용하는 경우, webpack 5 릴리스 노트를 확인하세요.
webpack을 사용하여 Kotlin/JS 프로젝트 번들링에 대해 자세히 알아보기.
IR 컴파일러를 위한 프레임워크 및 라이브러리
Kotlin/JS IR 컴파일러는 알파 버전입니다. 향후 호환되지 않게 변경될 수 있으며 수동 마이그레이션이 필요할 수 있습니다. YouTrack에 피드백을 주시면 감사하겠습니다.
Kotlin/JS 컴파일러용 IR 기반 백엔드 작업과 더불어, 라이브러리 개발자들이 both
모드로 프로젝트를 빌드하도록 권장하고 돕고 있습니다. 이는 두 가지 Kotlin/JS 컴파일러 모두를 위한 아티팩트를 생성할 수 있어 새로운 컴파일러의 생태계를 성장시키는 데 기여합니다.
많은 잘 알려진 프레임워크와 라이브러리가 이미 IR 백엔드에서 사용할 수 있습니다: KVision, fritz2, doodle 등이 있습니다. 프로젝트에서 이를 사용하고 있다면, 이미 IR 백엔드로 빌드하고 그 이점을 경험할 수 있습니다.
자신만의 라이브러리를 작성하고 있다면, 클라이언트도 새로운 컴파일러와 함께 사용할 수 있도록 ‘both’ 모드로 컴파일하세요.
Kotlin Multiplatform
Kotlin 1.5.0에서는 각 플랫폼에 대한 테스트 의존성을 선택하는 과정이 간소화되었으며, 이제 Gradle 플러그인이 자동으로 처리합니다.
문자 카테고리를 가져오는 새로운 API가 이제 멀티플랫폼 프로젝트에서 사용할 수 있습니다.
표준 라이브러리
표준 라이브러리는 실험적 부분의 안정화부터 새로운 기능 추가에 이르기까지 다양한 변경 및 개선 사항을 받았습니다:
- 안정적인 부호 없는 정수 타입
- 대/소문자 변환을 위한 안정적인 로케일 독립적 API
- 안정적인 문자-정수 변환 API
- 안정적인 Path API
- 내림 나눗셈 및 나머지 연산자
- Duration API 변경 사항
- 문자 카테고리를 가져오는 새로운 API, 이제 멀티플랫폼 코드에서 사용 가능
- 새로운 컬렉션 함수 firstNotNullOf()
- String?.toBoolean()의 엄격 버전
표준 라이브러리 변경 사항에 대한 자세한 내용은 이 블로그 게시물에서 확인할 수 있습니다.
안정적인 부호 없는 정수 타입
UInt
, ULong
, UByte
, UShort
부호 없는 정수 타입이 이제 안정화되었습니다. 이러한 타입에 대한 연산, 범위, 그리고 진행(progression)도 마찬가지입니다. 부호 없는 배열과 그에 대한 연산은 베타 상태로 남아 있습니다.
대/소문자 변환을 위한 안정적인 로케일 독립적 API
이번 릴리스에서는 대/소문자 텍스트 변환을 위한 새로운 로케일 독립적 API를 제공합니다. 이는 로케일 민감성이 있는 toLowerCase()
, toUpperCase()
, capitalize()
, decapitalize()
API 함수에 대한 대안을 제공합니다. 새로운 API는 다른 로케일 설정으로 인한 오류를 방지하는 데 도움이 됩니다.
Kotlin 1.5.0은 다음의 완전히 안정적인 대안을 제공합니다:
String
함수용:이전 버전 1.5.0 대안 String.toUpperCase()
String.uppercase()
String.toLowerCase()
String.lowercase()
String.capitalize()
String.replaceFirstChar { it.uppercase() }
String.decapitalize()
String.replaceFirstChar { it.lowercase() }
Char
함수용:이전 버전 1.5.0 대안 Char.toUpperCase()
Char.uppercaseChar(): Char
Char.uppercase(): String
Char.toLowerCase()
Char.lowercaseChar(): Char
Char.lowercase(): String
Char.toTitleCase()
Char.titlecaseChar(): Char
Char.titlecase(): String
Kotlin/JVM의 경우, 명시적인
Locale
파라미터를 가진 오버로드된uppercase()
,lowercase()
,titlecase()
함수도 있습니다.
이전 API 함수는 사용 중단(deprecated)으로 표시되었으며 향후 릴리스에서 제거될 예정입니다.
텍스트 처리 함수의 전체 변경 목록은 KEEP에서 확인하세요.
안정적인 문자-정수 변환 API
Kotlin 1.5.0부터 새로운 문자-코드 및 문자-숫자 변환 함수가 안정화되었습니다. 이 함수들은 유사한 문자열-Int 변환과 혼동되는 경우가 많았던 현재 API 함수들을 대체합니다.
새로운 API는 이러한 명칭 혼동을 없애고, 코드 동작을 더 투명하고 명확하게 만듭니다.
이번 릴리스에서는 명확하게 명명된 다음 함수 집합으로 나뉜 Char
변환을 도입합니다:
Char
의 정수 코드를 가져오고 주어진 코드에서Char
를 구성하는 함수:
fun Char(code: Int): Char
fun Char(code: UShort): Char
val Char.code: Int
Char
를 나타내는 숫자의 값으로 변환하는 함수:
fun Char.digitToInt(radix: Int): Int
fun Char.digitToIntOrNull(radix: Int): Int?
Int
의 확장 함수로, 나타내는 음이 아닌 한 자리 숫자를 해당Char
표현으로 변환합니다:
fun Int.digitToChar(radix: Int): Char
Number.toChar()
의 구현( Int.toChar()
제외)을 포함한 이전 변환 API와 Char.toInt()
와 같은 숫자 타입으로의 변환을 위한 Char
확장 함수는 이제 사용 중단되었습니다.
KEEP에서 문자-정수 변환 API에 대해 자세히 알아보기.
내림 나눗셈 및 나머지 연산자
표준 라이브러리에 모듈러 산술을 위한 새로운 연산이 추가되었습니다:
floorDiv()
는 내림 나눗셈의 결과를 반환합니다. 이는 정수 타입에서 사용할 수 있습니다.mod()
는 내림 나눗셈의 나머지(모듈러스)를 반환합니다. 이는 모든 숫자 타입에서 사용할 수 있습니다.
이러한 연산은 기존 정수 나눗셈 및 rem() 함수(또는 %
연산자)와 매우 유사하게 보이지만, 음수에서 다르게 작동합니다:
a.floorDiv(b)
는floorDiv
가 결과를 내림(더 작은 정수 방향으로)하는 반면, 일반/
는 결과를 0에 더 가까운 정수로 자른다는 점에서 일반/
와 다릅니다.a.mod(b)
는a
와a.floorDiv(b) * b
의 차이입니다. 결과는 0이거나b
와 같은 부호를 가집니다. 반면a % b
는 다른 부호를 가질 수 있습니다.
fun main() {
println("내림 나눗셈 -5/3: ${(-5).floorDiv(3)}")
println( "나머지: ${(-5).mod(3)}")
println("절삭 나눗셈 -5/3: ${-5 / 3}")
println( "나머지: ${-5 % 3}")
}
Duration API 변경 사항
Duration API는 실험적입니다. 언제든지 중단되거나 변경될 수 있습니다. 평가 목적으로만 사용하세요. YouTrack에 피드백을 주시면 감사하겠습니다.
다양한 시간 단위로 지속 시간을 나타내기 위한 실험적인 Duration 클래스가 있습니다. 1.5.0에서 Duration API는 다음 변경 사항을 받았습니다:
- 내부 값 표현이 이제
Double
대신Long
을 사용하여 더 나은 정밀도를 제공합니다. Long
으로 특정 시간 단위로 변환하기 위한 새로운 API가 있습니다. 이는Double
값을 사용하여 작동하며 이제 사용 중단된 이전 API를 대체합니다. 예를 들어,Duration.inWholeMinutes
는Long
으로 표현된 지속 시간 값을 반환하며Duration.inMinutes
를 대체합니다.- 숫자로부터
Duration
을 구성하기 위한 새로운 동반(companion) 함수가 있습니다. 예를 들어,Duration.seconds(Int)
는 정수 초를 나타내는Duration
객체를 생성합니다.Int.seconds
와 같은 이전 확장 속성은 이제 사용 중단되었습니다.
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ExperimentalTime
fun main() {
val duration = Duration.milliseconds(120000)
println("${duration.inWholeMinutes}분은 ${duration.inWholeSeconds}초입니다")
}
문자 카테고리를 가져오는 새로운 API, 이제 멀티플랫폼 코드에서 사용 가능
Kotlin 1.5.0은 멀티플랫폼 프로젝트에서 유니코드에 따른 문자 카테고리를 가져오는 새로운 API를 도입합니다. 여러 함수가 이제 모든 플랫폼과 공통 코드에서 사용할 수 있습니다.
문자가 글자 또는 숫자인지 확인하는 함수:
fun main() {
val chars = listOf('a', '1', '+')
val (letterOrDigitList, notLetterOrDigitList) = chars.partition { it.isLetterOrDigit() }
println(letterOrDigitList) // [a, 1]
println(notLetterOrDigitList) // [+]
}
문자의 대소문자(case)를 확인하는 함수:
fun main() {
val chars = listOf('Dž', 'Lj', 'Nj', 'Dz', '1', 'A', 'a', '+')
val (titleCases, notTitleCases) = chars.partition { it.isTitleCase() }
println(titleCases) // [Dž, Lj, Nj, Dz]
println(notTitleCases) // [1, A, a, +]
}
다른 함수:
유니코드에 따른 문자의 일반 카테고리를 나타내는 Char.category
속성과 그 반환 타입 열거형 클래스인 CharCategory
도 이제 멀티플랫폼 프로젝트에서 사용할 수 있습니다.
새로운 컬렉션 함수 firstNotNullOf()
새로운 firstNotNullOf()
및 firstNotNullOfOrNull()
함수는 mapNotNull()
과 first()
또는 firstOrNull()
을 결합합니다. 이 함수들은 사용자 정의 셀렉터 함수로 원본 컬렉션을 매핑하고 첫 번째 null이 아닌 값을 반환합니다. 그러한 값이 없으면 firstNotNullOf()
는 예외를 발생시키고, firstNotNullOfOrNull()
은 null을 반환합니다.
fun main() {
val data = listOf("Kotlin", "1.5")
println(data.firstNotNullOf(String::toDoubleOrNull))
println(data.firstNotNullOfOrNull(String::toIntOrNull))
}
String?.toBoolean()의 엄격 버전
두 가지 새로운 함수는 기존 String?.toBoolean()의 대소문자 구분 엄격 버전을 도입합니다:
String.toBooleanStrict()
는 리터럴true
및false
를 제외한 모든 입력에 대해 예외를 발생시킵니다.String.toBooleanStrictOrNull()
은 리터럴true
및false
를 제외한 모든 입력에 대해 null을 반환합니다.
fun main() {
println("true".toBooleanStrict())
println("1".toBooleanStrictOrNull())
// println("1".toBooleanStrict()) // 예외 발생
}
kotlin-test 라이브러리
kotlin-test 라이브러리는 몇 가지 새로운 기능을 도입합니다:
멀티플랫폼 프로젝트에서 테스트 의존성 사용 간소화
이제 kotlin-test
의존성을 사용하여 commonTest
소스 세트에 테스트 의존성을 추가할 수 있으며, Gradle 플러그인이 각 테스트 소스 세트에 대한 해당 플랫폼 의존성을 추론합니다:
- JVM 소스 세트용
kotlin-test-junit
, Kotlin/JVM 소스 세트에 대한 테스트 프레임워크 자동 선택 참조 - Kotlin/JS 소스 세트용
kotlin-test-js
- 공통 소스 세트용
kotlin-test-common
및kotlin-test-annotations-common
- Kotlin/Native 소스 세트에는 추가 아티팩트 없음
또한, 모든 공유 또는 플랫폼별 소스 세트에서 kotlin-test
의존성을 사용할 수 있습니다.
명시적 의존성이 있는 기존 kotlin-test 설정은 Gradle과 Maven 모두에서 계속 작동합니다.
테스트 라이브러리에 의존성 설정에 대해 자세히 알아보세요.
Kotlin/JVM 소스 세트에 대한 테스트 프레임워크 자동 선택
Gradle 플러그인은 이제 테스트 프레임워크에 대한 의존성을 자동으로 선택하고 추가합니다. 공통 소스 세트에 kotlin-test
의존성을 추가하기만 하면 됩니다.
Gradle은 기본적으로 JUnit 4를 사용합니다. 따라서 kotlin("test")
의존성은 JUnit 4용 변형, 즉 kotlin-test-junit
으로 확인됩니다:
kotlin {
sourceSets {
val commonTest by getting {
dependencies {
implementation(kotlin("test")) // 이 의존성은 JUnit 4에 대한
// 전이적 의존성을 가져옵니다
}
}
}
}
kotlin {
sourceSets {
commonTest {
dependencies {
implementation kotlin("test") // 이 의존성은 JUnit 4에 대한
// 전이적 의존성을 가져옵니다
}
}
}
}
테스트 태스크에서 useJUnitPlatform()
또는 useTestNG()
를 호출하여 JUnit 5 또는 TestNG를 선택할 수 있습니다:
tasks {
test {
// TestNG 지원 활성화
useTestNG()
// 또는
// JUnit Platform(일명 JUnit 5) 지원 활성화
useJUnitPlatform()
}
}
프로젝트의 gradle.properties
에 kotlin.test.infer.jvm.variant=false
줄을 추가하여 자동 테스트 프레임워크 선택을 비활성화할 수 있습니다.
테스트 라이브러리에 의존성 설정에 대해 자세히 알아보세요.
단언(Assertion) 함수 업데이트
이번 릴리스에서는 새로운 단언 함수를 도입하고 기존 함수를 개선합니다.
kotlin-test
라이브러리는 이제 다음과 같은 기능을 제공합니다:
값의 타입 확인
새로운
assertIs<T>
와assertIsNot<T>
를 사용하여 값의 타입을 확인할 수 있습니다:kotlin@Test fun testFunction() { val s: Any = "test" assertIs<String>(s) // 단언 실패 시 s의 실제 타입을 언급하는 AssertionError를 던집니다 // assertIs의 계약(contract) 때문에 이제 s.length를 출력할 수 있습니다 println("${s.length}") }
타입 이레이저(type erasure) 때문에, 이 단언 함수는 다음 예시에서
value
가List
타입인지 여부만 확인하며, 특정String
요소 타입의 리스트인지 여부는 확인하지 않습니다:assertIs<List<String>>(value)
.배열, 시퀀스 및 임의의 이터러블에 대한 컨테이너 내용 비교
구조적 동등성을 구현하지 않는 다른 컬렉션의 내용을 비교하기 위한 새로운 오버로드된
assertContentEquals()
함수 집합이 있습니다:kotlin@Test fun test() { val expectedArray = arrayOf(1, 2, 3) val actualArray = Array(3) { it + 1 } assertContentEquals(expectedArray, actualArray) }
Double
및Float
숫자에 대한assertEquals()
및assertNotEquals()
의 새로운 오버로드새로운
assertEquals()
함수 오버로드는 두Double
또는Float
숫자를 절대 정밀도로 비교할 수 있게 합니다. 정밀도 값은 함수의 세 번째 파라미터로 지정됩니다:kotlin@Test fun test() { val x = sin(PI) // 정밀도 파라미터 val tolerance = 0.000001 assertEquals(0.0, x, tolerance) }
컬렉션 및 요소의 내용 확인을 위한 새로운 함수
이제
assertContains()
함수를 사용하여 컬렉션이나 요소가 어떤 것을 포함하는지 확인할 수 있습니다.IntRange
,String
등과 같이contains()
연산자를 가진 Kotlin 컬렉션 및 요소와 함께 사용할 수 있습니다:kotlin@Test fun test() { val sampleList = listOf<String>("sample", "sample2") val sampleString = "sample" assertContains(sampleList, sampleString) // 컬렉션의 요소 assertContains(sampleString, "amp") // 문자열의 부분 문자열 }
assertTrue()
,assertFalse()
,expect()
함수가 이제 인라인입니다이제 이 함수들을 인라인 함수로 사용할 수 있으므로 람다 표현식 내에서 suspend 함수를 호출할 수 있습니다:
kotlin@Test fun test() = runBlocking<Unit> { val deferred = async { "Kotlin is nice" } assertTrue("Kotlin 부분 문자열이 존재해야 합니다") { deferred.await() .contains("Kotlin") } }
kotlinx 라이브러리
Kotlin 1.5.0과 함께 kotlinx 라이브러리의 새로운 버전이 릴리스됩니다:
Coroutines 1.5.0-RC
kotlinx.coroutines
1.5.0-RC에는 다음이 포함됩니다:
- 새로운 channels API
- 안정적인 반응형 통합
- 그리고 더 많은 기능
Kotlin 1.5.0부터 실험적인 코루틴은 비활성화되며 -Xcoroutines=experimental
플래그는 더 이상 지원되지 않습니다.
변경 로그 및 kotlinx.coroutines
1.5.0 릴리스 블로그 게시물에서 자세히 알아보세요.
Serialization 1.2.1
kotlinx.serialization
1.2.1에는 다음이 포함됩니다:
- JSON 직렬화 성능 개선
- JSON 직렬화에서 여러 이름 지원
@Serializable
클래스에서 .proto 스키마 생성 실험적 지원- 그리고 더 많은 기능
변경 로그 및 kotlinx.serialization
1.2.1 릴리스 블로그 게시물에서 자세히 알아보세요.
dateTime 0.2.0
kotlinx-datetime
0.2.0에는 다음이 포함됩니다:
@Serializable
Datetime 객체DateTimePeriod
및DatePeriod
의 정규화된 API- 그리고 더 많은 기능
변경 로그 및 kotlinx-datetime
0.2.0 릴리스 블로그 게시물에서 자세히 알아보세요.
Kotlin 1.5.0으로 마이그레이션
IntelliJ IDEA와 Android Studio는 Kotlin 플러그인 1.5.0이 사용 가능해지면 업데이트를 제안할 것입니다.
기존 프로젝트를 Kotlin 1.5.0으로 마이그레이션하려면, Kotlin 버전을 1.5.0
으로 변경하고 Gradle 또는 Maven 프로젝트를 다시 가져오기(re-import)만 하면 됩니다. Kotlin 1.5.0으로 업데이트하는 방법 알아보기.
Kotlin 1.5.0으로 새 프로젝트를 시작하려면, Kotlin 플러그인을 업데이트하고 File | New | Project에서 프로젝트 마법사를 실행하세요.
새로운 명령줄 컴파일러는 GitHub 릴리스 페이지에서 다운로드할 수 있습니다.
Kotlin 1.5.0은 기능 릴리스이므로 언어에 호환되지 않는 변경 사항을 가져올 수 있습니다. 이러한 변경 사항의 자세한 목록은 Kotlin 1.5 호환성 가이드에서 확인할 수 있습니다.