Kotlin 1.3.x 호환성 가이드
_언어의 현대성 유지_와 _편안한 업데이트_는 Kotlin 언어 설계의 핵심 원칙입니다. 전자는 언어의 발전을 저해하는 구조는 제거되어야 함을 의미하며, 후자는 이러한 제거가 코드 마이그레이션을 가능한 한 원활하게 할 수 있도록 사전에 충분히 전달되어야 함을 의미합니다.
대부분의 언어 변경 사항은 업데이트 변경 로그나 컴파일러 경고와 같은 다른 채널을 통해 이미 발표되었지만, 이 문서는 이를 모두 요약하여 Kotlin 1.2에서 Kotlin 1.3으로의 마이그레이션을 위한 완전한 참조를 제공합니다.
기본 용어
이 문서에서는 여러 종류의 호환성을 소개합니다:
- 소스(Source): 소스 호환성이 깨지는 변경이 발생하면 기존에 잘 컴파일되던 코드(에러나 경고 없이)가 더 이상 컴파일되지 않습니다.
- 바이너리(Binary): 두 바이너리 아티팩트를 서로 교체해도 로딩이나 링크 에러가 발생하지 않는 경우 이를 바이너리 호환이 된다고 합니다.
- 동작(Behavioral): 변경 전후에 동일한 프로그램이 서로 다른 동작을 보인다면 해당 변경은 동작 호환성이 깨진 것입니다.
이 정의들은 순수 Kotlin에 대해서만 적용됨을 유의하십시오. Java 등 다른 언어 관점에서의 Kotlin 코드 호환성은 이 문서의 범위를 벗어납니다.
호환되지 않는 변경 사항
<clinit> 호출과 관련한 생성자 인자의 평가 순서
이슈: KT-19532
컴포넌트: Kotlin/JVM
호환되지 않는 변경 유형: 동작
요약: 클래스 초기화와 관련된 평가 순서가 1.3에서 변경되었습니다.
지원 중단 주기:
- 1.3 미만: 이전 동작 (상세 내용은 이슈 참조)
- 1.3 이상: 동작 변경됨.
-Xnormalize-constructor-calls=disable을 사용하여 일시적으로 1.3 이전 동작으로 되돌릴 수 있습니다. 이 플래그에 대한 지원은 다음 메이저 릴리스에서 제거될 예정입니다.
어노테이션 생성자 파라미터에서 누락된 getter 대상 어노테이션
이슈: KT-25287
컴포넌트: Kotlin/JVM
호환되지 않는 변경 유형: 동작
요약: 어노테이션 생성자 파라미터의 getter 대상(getter-target) 어노테이션이 1.3부터 클래스 파일에 올바르게 기록됩니다.
지원 중단 주기:
- 1.3 미만: 어노테이션 생성자 파라미터의 getter 대상 어노테이션이 적용되지 않음
- 1.3 이상: 어노테이션 생성자 파라미터의 getter 대상 어노테이션이 올바르게 적용되어 생성된 코드에 기록됨
클래스 생성자의 @get: 어노테이션에서 누락된 에러
이슈: KT-19628
컴포넌트: 핵심 언어 (Core language)
호환되지 않는 변경 유형: 소스
요약: getter 대상 어노테이션의 에러가 1.3에서 올바르게 보고됩니다.
지원 중단 주기:
- 1.2 미만: getter 대상 어노테이션의 컴파일 에러가 보고되지 않아 잘못된 코드가 정상적으로 컴파일되었음.
- 1.2.x: 툴링에서만 에러가 보고되며, 컴파일러는 여전히 경고 없이 코드를 컴파일함.
- 1.3 이상: 컴파일러에서도 에러가 보고되어 잘못된 코드는 거부됨.
@NotNull이 붙은 Java 타입 접근 시 null 가능성 검사(Nullability assertions)
이슈: KT-20830
컴포넌트: Kotlin/JVM
호환되지 않는 변경 유형: 동작
요약: not-null 어노테이션이 붙은 Java 타입에 대한 null 가능성 검사가 더 공격적으로 생성되므로, 여기서
null을 전달하는 코드는 더 일찍 실패하게 됩니다.지원 중단 주기:
- 1.3 미만: 타입 추론이 관여할 때 컴파일러가 이러한 검사를 놓칠 수 있어, 바이너리에 대해 컴파일하는 동안 잠재적인
null전파를 허용했습니다 (상세 내용은 이슈 참조).- 1.3 이상: 컴파일러가 누락된 검사를 생성합니다. 이로 인해 (잘못되게)
null을 전달하던 코드가 더 일찍 실패할 수 있습니다.-XXLanguage:-StrictJavaNullabilityAssertions를 사용하여 일시적으로 1.3 이전 동작으로 되돌릴 수 있습니다. 이 플래그에 대한 지원은 다음 메이저 릴리스에서 제거됩니다.
enum 멤버에 대한 잘못된(Unsound) 스마트 캐스트
이슈: KT-20772
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: 한 enum 엔트리의 멤버에 대한 스마트 캐스트가 해당 enum 엔트리에만 올바르게 적용됩니다.
지원 중단 주기:
- 1.3 미만: 한 enum 엔트리의 멤버에 대한 스마트 캐스트가 다른 enum 엔트리의 동일한 멤버에 대해 잘못된 스마트 캐스트로 이어질 수 있었습니다.
- 1.3 이상: 스마트 캐스트가 해당 enum 엔트리의 멤버에만 올바르게 적용됩니다.
-XXLanguage:-SoundSmartcastForEnumEntries는 일시적으로 이전 동작을 되돌립니다. 이 플래그에 대한 지원은 다음 메이저 릴리스에서 제거됩니다.
getter 내에서의 val 뒷받침 필드(backing field) 재할당
이슈: KT-16681
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약:
val프로퍼티의 getter 내에서 해당 뒷받침 필드를 재할당하는 것이 이제 금지됩니다.지원 중단 주기:
- 1.2 미만: Kotlin 컴파일러가 getter 내에서
val의 뒷받침 필드 수정을 허용했습니다. 이는 Kotlin 시맨틱을 위반할 뿐만 아니라,final필드를 재할당하는 잘못된 JVM 바이트코드를 생성합니다.- 1.2.X:
val의 뒷받침 필드를 재할당하는 코드에 지원 중단 경고가 보고됩니다.- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
순회하는 for 루프 이전의 배열 캡처
이슈: KT-21354
컴포넌트: Kotlin/JVM
호환되지 않는 변경 유형: 소스
요약: for 루프 범위의 표현식이 루프 바디에서 업데이트되는 로컬 변수인 경우, 이 변경이 루프 실행에 영향을 줍니다. 이는 범위(range), 문자 시퀀스(character sequence) 및 컬렉션과 같은 다른 컨테이너를 순회하는 방식과 일치하지 않았습니다.
지원 중단 주기:
- 1.2 미만: 설명된 코드 패턴이 정상적으로 컴파일되지만, 로컬 변수에 대한 업데이트가 루프 실행에 영향을 미칩니다.
- 1.2.X: for 루프의 범위 표현식이 루프 바디에서 할당되는 배열 타입 로컬 변수인 경우 지원 중단 경고가 보고됩니다.
- 1.3: 이러한 경우의 동작을 다른 컨테이너와 일치하도록 변경합니다.
enum 엔트리 내의 중첩 분류기(Nested classifiers)
이슈: KT-16310
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 enum 엔트리 내의 중첩 분류기(클래스, 객체, 인터페이스, 어노테이션 클래스, enum 클래스)가 금지됩니다.
지원 중단 주기:
- 1.2 미만: enum 엔트리 내의 중첩 분류기가 정상적으로 컴파일되지만, 런타임에 예외가 발생할 수 있습니다.
- 1.2.X: 중첩 분류기에 대해 지원 중단 경고가 보고됩니다.
- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
data 클래스의 copy 오버라이딩
이슈: KT-19618
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 data 클래스가
copy()를 오버라이딩하는 것이 금지됩니다.지원 중단 주기:
- 1.2 미만:
copy()를 오버라이딩하는 data 클래스가 정상적으로 컴파일되지만, 런타임에 실패하거나 이상한 동작을 보일 수 있습니다.- 1.2.X:
copy()를 오버라이딩하는 data 클래스에 대해 지원 중단 경고가 보고됩니다.- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
외부 클래스의 제네릭 파라미터를 캡처하는 Throwable 상속 내부 클래스
이슈: KT-17981
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 내부 클래스(inner class)가
Throwable을 상속하는 것이 허용되지 않습니다.지원 중단 주기:
- 1.2 미만:
Throwable을 상속하는 내부 클래스가 정상적으로 컴파일됩니다. 이러한 내부 클래스가 제네릭 파라미터를 캡처하게 되면 런타임에 실패하는 이상한 코드 패턴으로 이어질 수 있습니다.- 1.2.X:
Throwable을 상속하는 내부 클래스에 대해 지원 중단 경고가 보고됩니다.- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
컴패니언 객체가 포함된 복잡한 클래스 계층 구조의 가시성 규칙
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 컴패니언 객체(companion objects) 및 중첩 분류기가 포함된 복잡한 클래스 계층 구조에서 짧은 이름(short name)에 의한 가시성 규칙이 더 엄격해집니다.
지원 중단 주기:
- 1.2 미만: 이전 가시성 규칙 (상세 내용은 이슈 참조)
- 1.2.X: 더 이상 접근할 수 없게 될 짧은 이름에 대해 지원 중단 경고가 보고됩니다. 툴링에서 전체 이름(full name)을 추가하는 자동 마이그레이션을 제안합니다.
- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다. 문제가 되는 코드는 전체 수식어(full qualifiers)를 추가하거나 명시적인 임포트(import)를 추가해야 합니다.
상수가 아닌 vararg 어노테이션 파라미터
이슈: KT-23153
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 상수가 아닌 값을 vararg 어노테이션 파라미터로 설정하는 것이 금지됩니다.
지원 중단 주기:
- 1.2 미만: 컴파일러가 vararg 어노테이션 파라미터에 상수가 아닌 값을 전달하는 것을 허용하지만, 실제로는 바이트코드 생성 중에 해당 값을 누락시켜 명확하지 않은 동작을 유발합니다.
- 1.2.X: 이러한 코드 패턴에 대해 지원 중단 경고가 보고됩니다.
- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
로컬 어노테이션 클래스
이슈: KT-23277
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 로컬 어노테이션 클래스가 지원되지 않습니다.
지원 중단 주기:
- 1.2 미만: 컴파일러가 로컬 어노테이션 클래스를 정상적으로 컴파일했습니다.
- 1.2.X: 로컬 어노테이션 클래스에 대해 지원 중단 경고가 보고됩니다.
- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
로컬 위임 프로퍼티에 대한 스마트 캐스트
이슈: KT-22517
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터 로컬 위임 프로퍼티(local delegated properties)에 대한 스마트 캐스트가 허용되지 않습니다.
지원 중단 주기:
- 1.2 미만: 컴파일러가 로컬 위임 프로퍼티의 스마트 캐스트를 허용했으나, 잘못 동작하는 위임자의 경우 안전하지 않은 스마트 캐스트로 이어질 수 있었습니다.
- 1.2.X: 로컬 위임 프로퍼티에 대한 스마트 캐스트가 지원 중단된 것으로 보고됩니다(컴파일러 경고 발생).
- 1.3 이상: 지원 중단 경고가 에러로 격상됩니다.
mod 연산자 관례
이슈: KT-24197
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터
mod연산자 선언 및 해당 선언으로 분석되는 호출이 금지됩니다.지원 중단 주기:
- 1.1.X, 1.2.X:
operator mod선언 및 해당 선언으로 분석되는 호출에 대해 경고를 보고합니다.- 1.3.X: 경고를 에러로 격상하지만, 여전히
operator mod선언으로 분석되는 것은 허용합니다.- 1.4.X: 더 이상 호출이
operator mod선언으로 분석되지 않도록 합니다.
이름을 지정한 형태(named form)로 vararg에 단일 요소 전달
이슈: KT-20588, KT-20589. KT-20171도 참조하십시오.
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3에서 vararg에 단일 요소를 할당하는 방식이 지원 중단되었으며, 스프레드(spread) 연산자와 배열 생성의 조합으로 대체되어야 합니다.
지원 중단 주기:
- 1.2 미만: 이름을 지정한 형태로 vararg에 단일 값 요소를 할당하는 것이 정상적으로 컴파일되며 배열에 단일 요소를 할당하는 것으로 처리되어, 배열을 vararg에 할당할 때 명확하지 않은 동작을 유발했습니다.
- 1.2.X: 이러한 할당에 대해 지원 중단 경고가 보고되며, 사용자는 스프레드 연산자와 배열 생성을 연속해서 사용하는 방식으로 전환할 것을 권장받습니다.
- 1.3.X: 경고가 에러로 격상됩니다.
- 1.4 이상: vararg에 단일 요소를 할당하는 시맨틱을 변경하여, 배열의 할당을 배열의 스프레드를 할당하는 것과 동일하게 만듭니다.
EXPRESSION 타겟을 가진 어노테이션의 유지(Retention)
이슈: KT-13762
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터
EXPRESSION타겟을 가진 어노테이션은SOURCE유지 정책(retention)만 허용됩니다.지원 중단 주기:
- 1.2 미만:
EXPRESSION타겟과SOURCE이외의 유지 정책을 가진 어노테이션이 허용되었으나, 사용 시점(use-sites)에서 무시되었습니다.- 1.2.X: 이러한 어노테이션 선언에 대해 지원 중단 경고가 보고됩니다.
- 1.3 이상: 경고가 에러로 격상됩니다.
PARAMETER 타겟을 가진 어노테이션은 파라미터 타입에 적용될 수 없어야 함
이슈: KT-9580
컴포넌트: 핵심 언어
호환되지 않는 변경 유형: 소스
요약: Kotlin 1.3부터
PARAMETER타겟을 가진 어노테이션이 파라미터 타입에 적용될 때 잘못된 어노테이션 타겟 에러가 올바르게 보고됩니다.지원 중단 주기:
- 1.2 미만: 앞서 언급한 코드 패턴이 정상적으로 컴파일되었으며, 어노테이션은 무시되고 바이트코드에 나타나지 않았습니다.
- 1.2.X: 이러한 사용법에 대해 지원 중단 경고가 보고됩니다.
- 1.3 이상: 경고가 에러로 격상됩니다.
Array.copyOfRange가 반환 배열을 확장하는 대신 인덱스가 범위를 벗어날 때 예외를 던짐
이슈: KT-19489
컴포넌트: kotlin-stdlib (JVM)
호환되지 않는 변경 유형: 동작
요약: Kotlin 1.3부터 복사할 범위의 끝(exclusive)을 나타내는
Array.copyOfRange의toIndex인자가 배열 크기보다 크지 않은지 확인하고, 클 경우IllegalArgumentException을 던집니다.지원 중단 주기:
- 1.3 미만:
Array.copyOfRange호출 시toIndex가 배열 크기보다 큰 경우, 범위 내의 누락된 요소가null로 채워져 Kotlin 타입 시스템의 건전성(soundness)을 위반했습니다.- 1.3 이상:
toIndex가 배열 범위 내에 있는지 확인하고, 그렇지 않으면 예외를 던집니다.
Int.MIN_VALUE 및 Long.MIN_VALUE를 step으로 하는 Int 및 Long 수열(Progression)은 금지되며 인스턴스화가 허용되지 않음
이슈: KT-17176
컴포넌트: kotlin-stdlib (JVM)
호환되지 않는 변경 유형: 동작
요약: Kotlin 1.3부터 정수 수열의 step 값이 해당 정수 타입(
Long또는Int)의 최소 음수 값인 것을 금지하여,IntProgression.fromClosedRange(0, 1, step = Int.MIN_VALUE)호출 시IllegalArgumentException을 던집니다.지원 중단 주기:
- 1.3 미만:
Int.MIN_VALUEstep으로IntProgression을 생성하는 것이 가능했으며, 이는 두 값[0, -2147483648]을 생성하는 명확하지 않은 동작을 보였습니다.- 1.3 이상: step이 해당 정수 타입의 최소 음수 값인 경우
IllegalArgumentException을 던집니다.
매우 긴 시퀀스(Sequence) 작업 시 인덱스 오버플로 검사
이슈: KT-16097
컴포넌트: kotlin-stdlib (JVM)
호환되지 않는 변경 유형: 동작
요약: Kotlin 1.3부터 매우 긴 시퀀스에 대해
index,count및 유사한 메서드에서 오버플로가 발생하지 않도록 합니다. 영향을 받는 전체 메서드 목록은 이슈를 참조하십시오.지원 중단 주기:
- 1.3 미만: 매우 긴 시퀀스에서 이러한 메서드를 호출하면 정수 오버플로로 인해 음수 결과가 생성될 수 있었습니다.
- 1.3 이상: 이러한 메서드에서 오버플로를 감지하고 즉시 예외를 던집니다.
플랫폼 간 빈 일치 정규식에 의한 split 결과 통합
이슈: KT-21049
컴포넌트: kotlin-stdlib (JVM)
호환되지 않는 변경 유형: 동작
요약: Kotlin 1.3부터 모든 플랫폼에서 빈 일치(empty match) 정규식에 의한
split메서드의 동작을 통일합니다.지원 중단 주기:
- 1.3 미만: 설명된 호출의 동작이 JS, JRE 6, JRE 7과 JRE 8+를 비교할 때 서로 달랐습니다.
- 1.3 이상: 모든 플랫폼에서 동작을 통일합니다.
컴파일러 배포판에서 지원 중단된 아티팩트 배포 중단
이슈: KT-23799
컴포넌트: 기타
호환되지 않는 변경 유형: 바이너리
요약: Kotlin 1.3은 다음과 같은 지원 중단된(deprecated) 바이너리 아티팩트의 배포를 중단합니다:
kotlin-runtime: 대신kotlin-stdlib를 사용하십시오.kotlin-stdlib-jre7/8: 대신kotlin-stdlib-jdk7/8을 사용하십시오.- 컴파일러 배포판의
kotlin-jslib: 대신kotlin-stdlib-js를 사용하십시오.지원 중단 주기:
- 1.2.X: 아티팩트들이 지원 중단된 것으로 표시되었으며, 컴파일러가 해당 아티팩트 사용 시 경고를 보고했습니다.
- 1.3 이상: 아티팩트 배포가 중단됩니다.
stdlib의 어노테이션
이슈: KT-21784
컴포넌트: kotlin-stdlib (JVM)
호환되지 않는 변경 유형: 바이너리
요약: Kotlin 1.3은 stdlib에서
org.jetbrains.annotations패키지의 어노테이션을 제거하고, 컴파일러와 함께 제공되는 별도의 아티팩트인annotations-13.0.jar및mutability-annotations-compat.jar로 이동합니다.지원 중단 주기:
- 1.3 미만: 어노테이션이 stdlib 아티팩트와 함께 제공되었습니다.
- 1.3 이상: 어노테이션이 별도의 아티팩트로 제공됩니다.
