애노테이션(Annotation) 적용하기

코틀린은 자바와 같은 방법으로 애노테이션을 사용할 수 있다. 애노테이션은 @과 이름으로 이뤄지며 함수나 클래스 등 여러 다른 코드 구성 요소에 붙일 수 있다.

@Test
fun testTrue() {
  Assert.assertTrue(true)
}

@Deprecated 애노테이션은 자바와 같은 의미이지만 코틀린에서는 replaceWith 파라미터를 사용해 대체할 수 있는 패턴을 제시할 수 있다.

@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"))
fun remove(index: Int)

Intellij IDEA에서는 Kotlin의 @Deprecated 경고에 대해 자동으로 경고 메시지 및 Quick Fix 기능을 제공한다.

애노테이션의 인자로는 원시 타입 값, 문자열, enum, 클래스 참조, 다른 애노테이션, 앞서 말한 요소의 배열을 넣을 수 있다. 애노테이션 인자를 지정하는 문법은 자바와 약간 다르다.

  • 클래스를 애노테이션 인자로 지정할 때는 클래스 이름 뒤에 ::class를 넣어야 한다.
  • 다른 애노테이션을 인자로 지정할 때는 인자로 들어가는 애노테이션 앞에 @를 붙이지 않는다(@Deprecated 참조).
  • 배열을 인자로 지정하려면 arrayOf('a', 'b', 'c')와 같이 사용한다. 다만 자바에서 선언한 애노테이션 클래스를 사용할 때는 가변 길이 인자 형식을 취한다.

애노테이션 인자는 컴파일 시점에 알 수 있어야 한다. 프로퍼티를 애노테이션 인자로 지정하려면 const변경자를 사용해 상수로 취급해야 한다.

애노테이션 대상

코틀린은 소스코드에서 한 선언을 컴파일한 결과가 여러 자바 선언과 대응되는 경우가 있다. 여러 자바 선언에 각각 다른 애노테이션을 붙여야 할 때가 있을 것이다. 코틀린은 애노테이션을 붙일 때 어느 요소에 붙일 지 정할 수 있다. 사용 지점 대상(Use-site target)을 사용해서 애노테이션을 붙일 요소를 정할 수 있다.

@get:Rule
//@(사용 지점 대상):(애노테이션 이름)

다음은 사용 지점 대상을 지정할 때 사용하는 대상 목록이다.

  • property: 프로퍼티 전체. 자바에서 선언된 애노테이션에는 사용할 수 없다.
  • field: 프로퍼티에 의해 생성되는 필드(뒷받침하는 필드)
  • get: 프로퍼티 게터
  • set: 프로퍼티 세터
  • receiver: 확장 함수나 프로퍼티의 수신 객체 파라미터
  • param: 생성자 파라미터
  • setparam: 세터 파라미터
  • delegate: 위임 프로퍼티의 위임 인스턴스를 담아둔 필드
  • file: 파일 안에 선언된 최상위 함수와 프로퍼티를 담아둔 필드

file을 사용하는 애노테이션은 package선언 앞에서 파일의 최상위 수준에만 적용할 수 있다.

@file:JvmName("StringFunctions")
package string

애노테이션 선언

애노테이션을 선언하려면 클래스 앞에 annotation 키워드를 붙인다.

annotation class JsonExclude

애노테이션 클래스는 오직 선언이나 식과 관련 있는 메타데이터의 구조를 정의하기 때문에 내부에 코드가 들어있을 수 없다.

파라미터가 있는 애노테이션을 정의하려면 애노테이션 클래스의 주 생성자에 파라미터를 선언한다.

annotation class JsonName(val name: String)

일반 클래스와 다른점은 모든 파라미터 앞에 val을 붙여야 한다.

같은 코드를 자바 애노테이션으로 작성하면 다음과 같다.

public @interface JsonName {
  String value();
}

자바는 어떤 애노테이션을 적용할 때 value를 제외한 모든 속성에는 이름을 명시해야 한다. 코틀린은 애노테이션 적용에 일반적인 생성자 호출을 사용한다. 따라서 이름을 붙일 수도 있고 생략할 수도 있다.

메타애노테이션

애노테이션 클래스에 적용할 수 있는 애노테이션을 메타애노테이션(Meta-annotation)이라고 한다. 표준 라이브러리에는 몇 가지 메타애노테이션이 있으며 그런 메타애노테이션들은 컴파일러가 애노테이션을 처리하는 방법을 제어한다(애노테이션을 적용할 수 있는 요소의 유형을 지정할 수 있는 @Target 등).

애노테이션 파라미터로 클래스 사용하기

클래스 참조를 파라미터로 하는 애노테이션 클래스를 선언하려면 다음과 같이 한다.

annotation class DeserializeInterface(val targetClass: KClass<out Any>)

Kclassjava.lang.Class 타입과 같은 역할을 하는 코틀린 타입이다. KClass의 타입 파라미터는 KClass 인스턴스가 가리키는 코틀린 타입을 지정한다. 예를 들어 CompanyImpl::class의 타입은 KClass<CompanyImpl>이며 KClass<out Any>의 하위 타입이다(공변성).

애노테이션 파라미터로 제네릭 클래스 받기

애노테이션 파라미터로 제네릭 클래스를 받으려면 스타 프로젝션을 사용하면 된다.

annotion class CustomSerializer(val serializerClass: KClass<out ValueSerializer<*>>)

위 예제에서는 CustomSerializerValueSerializer를 구현하는 클래스만 인자로 받도록 제한하고 있다.


© 2021. All rights reserved.

Powered by Hydejack v9.1.6