본문 바로가기
프로그래밍/kotlin

[kotlin] 1.3 버전 RELEASE 정리

by 사바라다 2021. 11. 7.

안녕하세요. 최근 회사의 업무를 하던 중 필요에 의해서 kotlin 버전이 올라가면서 추가된 것을 확인해 볼 필요가 있었습니다. 정리한 내용을 이대로 버리기에는 아깝다고 생각했습니다. 오늘은 kotlin 1.3의 RELEASE에 대해서 번역한 내용을 공유드립니다.

Kotlin 1.3.x

kotlin 1.3.x 버전은 최초에 2018년에 출시된 코틀린 버전입니다. pre 버전을 제외한 최초 RELEASE은 1.3.0 버전으며 2018년 10월에 나왔으며 최종버전은 1.3.72로 2020년 4월에 출시되었습니다. 최초버전만 보자면 오래된 버전이긴합니다. 그러면서 최종 버전이 2020년 4월이기 현재.. 1.6.x 버전을 preview 하고 있기때문에 나름 장기간 유지된 메이저 버전이란 것도 알 수 있습니다. 아래에서 1.3.x가 되면서 변경된 점을 차례대로 살펴보도록하겠습니다. kotlin server 기준으며 KMM(kotlin multiplatfrom mobile)과 연관된 내용은 생략했음을 알려드립니다.

주요 내용

코루틴(Coroutine)

1.2.x 버전을 사용하고 있던 팀에서 1.3.x 로 올리고 싶어하는 이유중 가장 큰 이유는 코틀린 1.3.x 부터 코루틴을 지원하기 때문일 것입니다. 코루틴은 코틀린에서 지원하는 비동기(Asynchronous) 또는 논블럭킹(non-blocking) 매커니즘을 쉽게 구현할 수 있도록 언어 레벨에서 해주는 방법입니다. 일반적으로 코딩 방법과 유사하기 때문에 java webflux에서 사용하는 reactor 방식에 비해서 초기에 진입하기가 쉽다는 장점을 가지고 있습니다.

constract

kotlin은 smart cast를 지원합니다. smart cast란 if, 또는 when 절 등에서 null을 한번 체크하면 내부 코드에서는 notNull을 보장하게하는 것입니다. 코드로는 아래와 같습니다.

fun foo(s: String?) {
    if (s != null) s.length // if 에서 null 체크를 했기 때문에 바로 `lenth`를 호출할 수 있음
}

하지만 이러한 smart cast는 만약 야래 코드 처럼 null 체크가 별도의 함수를 통해서 이루어진다면 정상동작 하지 않습니다.

fun String?.isNotNull(): Boolean = this != null

fun foo(s: String?) {
    if (s.isNotNull()) s.length // smart cast 되지 않기 때문에 컴파일 에러
}

이러한 상황에서 contracts 라는 방법이 1.3.x부터 나오게 되었습니다.contacts를 사용하면 불필요한 타입 체크와 컴파일 에러 등을 방지하여 타입 캐스팅 및 호출횟수 등을 줄일 수 있습니다. 아래 코드는 kotlin stdlib에 들어있는 contract를 사용하는 코드입니다. 이 함수를 사용하면 함수를 별도로 호출하여 null을 체크하지만 사용하는 곳에서 정상적으로 smart 캐스트가 이루어집니다.

public inline fun CharSequence?.isNullOrEmpty(): Boolean {
    contract {
        returns(false) implies (this@isNullOrEmpty != null)
    }

    return this == null || this.length == 0
}
fun foo(s: String?) {
    if (!s.isNullOrEmpty()) s.length // 정상적으로 컴파일 됨
}

when의 변수로 값을 바로 할당하여 사용하기

코트린 1.3.x 부터는 when의 변수로 값을 바로 할당하여 사용할 수 있습니다. java의 try-catch-resources, 또는 while 구문과 유사하게 사용할 수 있는 것입니다. 아래의 코드를 보시면 when에 값을 바로 할당하여 사용하는 것을 알 수 있습니다. 기존에는 when의 위 코드에 val response = executeRequest()를 두고 response만 when의 변수로 두고 사용할 수 있는데 코드가 이전에 비해 깔끔해지는것을 기대할 수 있습니다.

fun Request.getBody() =
        when (val response = executeRequest()) {
            is Success -> response.body
            is HttpError -> throw HttpException(response.status)
        }

@JvmStatic 과 @JvmField를 interface의 companions에 사용 가능

@JvmStatic 과 @JvmField를 interface의 companions에 사용 가능하게 되었습니다.

  • @JvmStatic : java 코드로 컴파일될 때 getter와 setter르 생성
  • @JvmField : java 코드로 컴파일될 때 getter와 setter르 생성하지 않음

annotation classes에 내부 선언 가능

annotation classes에 nested classes, interfaces, objects, 그리고 companions를 내부 선언 가능하게 되었습니다.

파라미터 없는 main

기존의 main 함수는 항상 args: Array<String>를 파라미터로 받았어야했습니다. 하지만 이제 실제로 사용하지 않는다면 fun main()으로 main 함수를 사용할 수 있습니다.

인라인 클래스(Inline classes)

코틀린 1.3 버전에서는 Inline class를 새롭게 소개합니다. inline class는 Java 에서의 Integer 등과 같은 wrapped type 클래스이입니다. 하지만 Java 에서의 wrapped type 클래스는 int와 같은 primitive 타입을 감쌌기 때문에 성능상 단점을 가지게 됩니다. 이러한 단점은 잦은 autoboxing으로 인한 성능 저하 및 memory leak과 같은 현상으로 나오게 됩니다. 코틀린 1.3 버전에서의 Inline Class는 이러한 단점이 나오지 않도록 설계했다고 합니다.

인라인 클래스는 아래과같이 사용할 수 있습니다.

inline class Name(val s: String)
  • 1.3 버전 기준 Alpha 버전입니다. 띠라서 이후 버전에서 변경 및 삭제 될 수 있습니다.
  • 이후 버전에서는 inline이 value로 변경되게 됩니다.

Unsigned integers

양의 정수의 값만을 가지는 unsigned integer type이 새롭게 나왔습니다.

  • kotlin.UByte: an unsigned 8-bit integer, ranges from 0 to 255
  • kotlin.UShort: an unsigned 16-bit integer, ranges from 0 to 65535
  • kotlin.UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1
  • kotlin.ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1
// 아래와 깉이 literal 하게 선언할 수 있습니다.
val uint = 42u 
val ulong = 42uL
val ubyte: UByte = 255u

// un signed에서 아래와 같이 signed로 변경할 수 있습니다.
val int = uint.toInt()
val byte = ubyte.toByte()
val ulong2 = byte.toULong()
  • 1.3 버전 기준 Beta 버전입니다.

@JvmDefault

interface의 default method는 Java 8 버전에서 등장하였습니다. 하지만 코틀린 1.3.x 버전은 java 6 ~ 버전에서 지원합니다. @JvmDefault를 사용하면 java6, java7 버전에서 interface에 default method를 사용할 수 있습니다.

  • 실험(Experimental) 레벨 입니다.
  • 이후 버전에서 Deprecasted 되었으며 -Xjvm-default modes: all or all-compatibility를 사용하라고합니다.

Standard library

아래 내용은 kotlin-stdlib의 업데이트 내용입니다.

  • 멀티플랫폼 random : kotlin 전용 Random이 생겼습니다. kotlin.random.Random 입니다.
  • isNullOrEmpty 과 orEmpty 확장 함수 : collections, maps, 그리고 arrays에 null과 empty를 확인하는 isNullOrEmptyorEmpty 확장함수가 추가됩니다.
  • arrays 사이의 copy : array.copyInto(targetArray, targetOffset, startIndex, endIndex) 함수를 통해 array copy를 지원합니다.
  • associateWith : list에서 본인 값을 key로 map을 만드는 간단한 확장함수가 추가됩니다. 기존에 associate { it to getValue(it) }로 사용하셨다면 associateWith { getValue(it) }로 사용하시면 됩니다.
  • ifEmpty 과 ifBlank 함수 추가 : Collections, maps, object arrays, 그리고 sequences에 값이 존재하지 않으면 특정값을 반환할 수 있도록 하는 함수인 ifEmptyifBlack가 추가됩니다. 아래는 그 예제입니다.
fun printAllUppercase(data: List<String>) {
    val result = data
    .filter { it.all { c -> c.isUpperCase() } }
        .ifEmpty { listOf("<no uppercase>") }
    result.forEach { println(it) }
}

printAllUppercase(listOf("foo", "Bar")) // <no uppercase>
printAllUppercase(listOf("FOO", "BAR")) // FOO, BAR

마무리

오늘의 이 포스팅에서는 kotlin 1.3 버전이 되면서 업데이트 된 내용을 알아보았습니다.

키워드 중심으로 이해해 주시고 조금 더 디테일한 정보는 다른 포스팅을 참고해주시면 좋을것 같습니다.

감사합니다.

참조

kotlinlang_whatsnew13

댓글