Skip to content

Kotlin 1.5 호환성 가이드

_언어를 현대적으로 유지_하고 _편리한 업데이트_는 Kotlin 언어 설계의 근본 원칙 중 하나입니다. 전자는 언어 발전을 저해하는 구조는 제거되어야 한다고 말하며, 후자는 코드 마이그레이션을 가능한 한 원활하게 만들기 위해 이러한 제거가 미리 잘 전달되어야 한다고 말합니다.

대부분의 언어 변경 사항은 업데이트 변경 로그나 컴파일러 경고와 같은 다른 채널을 통해 이미 발표되었지만, 이 문서는 Kotlin 1.4에서 Kotlin 1.5로 마이그레이션하기 위한 완벽한 참조 자료를 제공하며 모든 내용을 요약합니다.

기본 용어

이 문서에서는 몇 가지 호환성 유형을 소개합니다:

  • 소스(source): 소스 호환성이 없는 변경은 (오류나 경고 없이) 잘 컴파일되던 코드가 더 이상 컴파일되지 않게 만듭니다.
  • 바이너리(binary): 두 바이너리 아티팩트(artifact)는 서로 교환해도 로딩 또는 링크 오류가 발생하지 않을 경우 바이너리 호환성이 있다고 말합니다.
  • 동작(behavioral): 동일한 프로그램이 변경 사항 적용 전후에 다른 동작을 보일 경우 동작 호환성이 없다고 말합니다.

이 정의는 순수한 Kotlin에 대해서만 주어진다는 것을 기억하십시오. 다른 언어의 관점에서 본 Kotlin 코드의 호환성(예: Java)은 이 문서의 범위를 벗어납니다.

언어 및 표준 라이브러리(stdlib)

시그니처 다형성 호출에서 스프레드 연산자 사용 금지

문제: KT-35226

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 시그니처 다형성 호출에 스프레드 연산자(*)를 사용하는 것이 금지됩니다.

사용 중단 주기:

  • < 1.5: 호출 지점에서 문제가 되는 연산자에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ProhibitSpreadOnSignaturePolymorphicCall을 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

해당 클래스에서 보이지 않는(internal/package-private) 추상 멤버를 포함하는 비추상 클래스 금지

문제: KT-27825

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 해당 클래스에서 보이지 않는(internal/package-private) 추상 멤버를 포함하는 비추상 클래스가 금지됩니다.

사용 중단 주기:

  • < 1.5: 문제가 되는 클래스에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ProhibitInvisibleAbstractMethodsInSuperclasses를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

JVM에서 비-reified 타입 파라미터 기반의 배열을 reified 타입 인자로 사용하는 것 금지

문제: KT-31227

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 JVM에서 비-reified 타입 파라미터 기반의 배열을 reified 타입 인자로 사용하는 것이 금지됩니다.

사용 중단 주기:

  • < 1.5: 문제가 되는 호출에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ProhibitNonReifiedArraysAsReifiedTypeArguments를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

주 생성자에게 위임하지 않는 보조 enum 클래스 생성자 금지

문제: KT-35870

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 주 생성자에게 위임하지 않는 보조 enum 클래스 생성자가 금지됩니다.

사용 중단 주기:

  • < 1.5: 문제가 되는 생성자에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-RequiredPrimaryConstructorDelegationCallInEnums를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

비공개 인라인 함수에서 익명 타입 노출 금지

문제: KT-33917

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 비공개 인라인 함수에서 익명 타입 노출이 금지됩니다.

사용 중단 주기:

  • < 1.5: 문제가 되는 생성자에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ApproximateAnonymousReturnTypesInPrivateInlineFunctions를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

SAM 변환을 사용한 인자 뒤에 비-스프레드 배열 전달 금지

문제: KT-35224

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 SAM 변환을 사용한 인자 뒤에 비-스프레드 배열을 전달하는 것이 금지됩니다.

사용 중단 주기:

  • 1.3.70: 문제가 되는 호출에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ProhibitVarargAsArrayAfterSamArgument를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

밑줄(_)로 이름 붙여진 catch 블록 파라미터에 대한 특수 의미 지원

문제: KT-31567

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 catch 블록에서 예외의 파라미터 이름을 생략하는 데 사용되는 밑줄(_) 기호에 대한 참조가 금지됩니다.

사용 중단 주기:

  • 1.4.20: 문제가 되는 참조에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-ForbidReferencingToUnderscoreNamedParameterOfCatchBlock을 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

SAM 변환 구현 전략을 익명 클래스 기반에서 invokedynamic으로 변경

문제: KT-44912

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터 SAM(단일 추상 메서드) 변환의 구현 전략이 익명 클래스 생성에서 invokedynamic JVM 명령어 사용으로 변경됩니다.

사용 중단 주기:

  • 1.5: SAM 변환 구현 전략 변경, -Xsam-conversions=class를 사용하여 구현 방식을 이전으로 되돌릴 수 있습니다.

JVM IR 기반 백엔드(backend)의 성능 문제

문제: KT-48233

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5는 Kotlin/JVM 컴파일러에 기본적으로 IR 기반 백엔드를 사용합니다. 이전 백엔드는 이전 언어 버전에서 기본적으로 여전히 사용됩니다.

Kotlin 1.5에서 새 컴파일러를 사용할 경우 일부 성능 저하 문제가 발생할 수 있습니다. 이러한 문제는 수정 중입니다.

사용 중단 주기:

  • < 1.5: 기본적으로 이전 JVM 백엔드가 사용됩니다.
  • >= 1.5: 기본적으로 IR 기반 백엔드가 사용됩니다. Kotlin 1.5에서 이전 백엔드를 사용해야 하는 경우, 프로젝트 구성 파일에 다음 줄을 추가하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

그레이들(Gradle)에서:

메이븐(Maven)에서:

xml
<configuration>
    <args>
        <arg>-Xuse-old-backend</arg>
    </args>
</configuration>

이 플래그(flag)에 대한 지원은 향후 릴리스에서 제거될 예정입니다.

JVM IR 기반 백엔드에서 필드 정렬 방식 변경

문제: KT-46378

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: 버전 1.5부터 Kotlin은 IR 기반 백엔드를 사용하여 JVM 바이트코드(bytecode)를 다르게 정렬합니다. 이전 백엔드는 본문에서 선언된 필드를 생성자에서 선언된 필드보다 먼저 생성하는 반면, 새 백엔드는 생성자에서 선언된 필드를 본문에서 선언된 필드보다 먼저 생성합니다. 새 정렬 방식은 Java 직렬화와 같이 필드 순서에 의존하는 직렬화 프레임워크를 사용하는 프로그램의 동작을 변경할 수 있습니다.

사용 중단 주기:

  • < 1.5: 기본적으로 이전 JVM 백엔드가 사용됩니다. 이 백엔드는 본문에서 선언된 필드를 생성자에서 선언된 필드보다 먼저 생성합니다.
  • >= 1.5: 기본적으로 새 IR 기반 백엔드가 사용됩니다. 생성자에서 선언된 필드는 본문에서 선언된 필드보다 먼저 생성됩니다. 해결 방법으로 Kotlin 1.5에서 일시적으로 이전 백엔드로 전환할 수 있습니다. 그렇게 하려면 프로젝트 구성 파일에 다음 줄을 추가하십시오.

그레이들(Gradle)에서:

메이븐(Maven)에서:

xml
<configuration>
    <args>
        <arg>-Xuse-old-backend</arg>
    </args>
</configuration>

이 플래그(flag)에 대한 지원은 향후 릴리스에서 제거될 예정입니다.

위임 표현식에 제네릭(generic) 호출이 있는 위임된 프로퍼티(property)에 대한 널 허용(nullability) 단언문(assertion) 생성

문제: KT-44304

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터 Kotlin 컴파일러는 위임 표현식에 제네릭 호출이 있는 위임된 프로퍼티에 대해 널 허용 단언문을 발행합니다.

사용 중단 주기:

  • 1.5: 위임된 프로퍼티에 대해 널 허용 단언문 발행(자세한 내용은 이슈 참조), -Xuse-old-backend 또는 -language-version 1.4를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

@OnlyInputTypes 어노테이션이 지정된 타입 파라미터를 사용하는 호출에 대한 경고를 오류로 전환

문제: KT-45861

구성 요소: 코어 언어

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터는 타입 안정성(type safety)을 개선하기 위해 contains, indexOf, assertEquals와 같은 무의미한 인자를 사용하는 호출이 금지됩니다.

사용 중단 주기:

  • 1.4.0: 문제가 되는 생성자에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-StrictOnlyInputTypesChecks를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

명명된 vararg가 있는 호출에서 인자 실행의 올바른 순서 사용

문제: KT-17691

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터는 명명된 vararg가 있는 호출에서 인자 실행 순서가 변경됩니다.

사용 중단 주기:

  • < 1.5: 문제가 되는 생성자에 대한 경고 도입
  • >= 1.5: 이 경고를 오류로 격상, -XXLanguage:-UseCorrectExecutionOrderForVarargArguments를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

연산자 함수 호출에서 파라미터의 기본값 사용

문제: KT-42064

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터는 연산자 호출에서 파라미터의 기본값을 사용합니다.

사용 중단 주기:

  • < 1.5: 이전 동작(자세한 내용은 이슈 참조)
  • >= 1.5: 동작 변경, -XXLanguage:-JvmIrEnabledByDefault를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

정규 진행(progression)이 비어 있는 경우 for 루프에서 빈 역진행(reversed progression) 생성

문제: KT-42533

구성 요소: Kotlin/JVM

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터는 정규 진행이 비어 있는 경우 for 루프에서 빈 역진행을 생성합니다.

사용 중단 주기:

  • < 1.5: 이전 동작(자세한 내용은 이슈 참조)
  • >= 1.5: 동작 변경, -XXLanguage:-JvmIrEnabledByDefault를 사용하여 일시적으로 1.5 이전 동작으로 되돌릴 수 있습니다.

Char를 코드 및 숫자로 변환하는 방식 정리

문제: KT-23451

구성 요소: kotlin-stdlib

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터 Char를 숫자 타입으로 변환하는 것이 사용 중단됩니다.

사용 중단 주기:

  • 1.5: Char.toInt()/toShort()/toLong()/toByte()/toDouble()/toFloat()Long.toChar()와 같은 역 함수 사용 중단, 대체 방안 제안

kotlin.text 함수에서 일관성 없는 대소문자 구분 없는 문자 비교

문제: KT-45496

구성 요소: kotlin-stdlib

호환되지 않는 변경 유형: 동작

요약: Kotlin 1.5부터 Char.equals는 대소문자를 구분하지 않는 비교 시 먼저 문자의 대문자 변형이 같은지 비교한 다음, 해당 대문자 변형의 소문자 변형(문자 자체와는 반대로)이 같은지 비교하여 개선됩니다.

사용 중단 주기:

  • < 1.5: 이전 동작(자세한 내용은 이슈 참조)
  • 1.5: Char.equals 함수의 동작 변경

기본 로케일(locale)에 민감한 대소문자 변환 API 제거

문제: KT-43023

구성 요소: kotlin-stdlib

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.5부터 String.toUpperCase()와 같은 기본 로케일 민감 대소문자 변환 함수가 사용 중단됩니다.

사용 중단 주기:

  • 1.5: 기본 로케일의 대소문자 변환 함수 사용 중단(자세한 내용은 이슈 참조), 대체 방안 제안

컬렉션 minmax 함수의 반환 타입을 점진적으로 널 불가능(non-nullable)으로 변경

문제: KT-38854

구성 요소: kotlin-stdlib (JVM)

호환되지 않는 변경 유형: 소스

요약: 컬렉션 minmax 함수의 반환 타입이 1.6에서 널 불가능으로 변경될 예정입니다.

사용 중단 주기:

  • 1.4: ...OrNull 함수를 동의어(synonym)로 도입하고 영향을 받는 API 사용 중단(자세한 내용은 이슈 참조)
  • 1.5.0: 영향을 받는 API의 사용 중단 수준을 오류로 격상
  • >= 1.6: 영향을 받는 API를 널 불가능 반환 타입으로 다시 도입

부동 소수점(floating-point) 타입을 ShortByte로 변환하는 것의 사용 중단 수준 격상

문제: KT-30360

구성 요소: kotlin-stdlib (JVM)

호환되지 않는 변경 유형: 소스

요약: Kotlin 1.4에서 WARNING 수준으로 사용 중단되었던 부동 소수점 타입을 ShortByte로 변환하는 것은 Kotlin 1.5.0부터 오류를 발생시킵니다.

사용 중단 주기:

  • 1.4: Double.toShort()/toByte()Float.toShort()/toByte() 사용 중단 및 대체 방안 제안
  • 1.5.0: 사용 중단 수준을 오류로 격상

도구

단일 프로젝트에서 여러 JVM kotlin-test 변형을 혼합하지 마십시오.

문제: KT-40225

구성 요소: 그레이들(Gradle)

호환되지 않는 변경 유형: 동작

요약: 여러 상호 배타적인 kotlin-test 변형은 하나가 전이적 의존성으로 인해 포함될 경우 단일 프로젝트에 존재할 수 있었습니다. 1.5.0부터 그레이들은 다른 테스트 프레임워크에 대한 상호 배타적인 kotlin-test 변형을 허용하지 않습니다.

사용 중단 주기:

  • < 1.5: 다른 테스트 프레임워크에 대한 여러 상호 배타적인 kotlin-test 변형을 허용
  • >= 1.5: 동작 변경, 그레이들은 "Cannot select module with conflict on capability..."와 같은 예외를 발생시킵니다. 가능한 해결책:
    • 전이적 의존성이 가져오는 것과 동일한 kotlin-test 변형 및 해당 테스트 프레임워크를 사용하십시오.
    • kotlin-test 변형을 전이적으로 가져오지 않는 다른 의존성 변형을 찾아, 사용하고 싶은 테스트 프레임워크를 사용할 수 있도록 하십시오.
    • 원하는 테스트 프레임워크와 동일한 kotlin-test 변형을 전이적으로 가져오는 다른 의존성 변형을 찾으십시오.
    • 전이적으로 가져와지는 테스트 프레임워크를 제외하십시오. 다음 예시는 JUnit 4를 제외하는 방법입니다:
    groovy
    configurations {
        testImplementation.get().exclude("org.jetbrains.kotlin", "kotlin-test-junit")
    }
    테스트 프레임워크를 제외한 후 애플리케이션을 테스트하십시오. 만약 작동이 중단되면, 제외 변경 사항을 롤백(rollback)하고 라이브러리가 사용하는 것과 동일한 테스트 프레임워크를 사용하며, 사용자(자신)의 테스트 프레임워크를 제외하십시오.