안녕하세요~! ㅎㅎ 오늘은 kotlin 에서 Annotation 에 대해 알아보도록 할게요.
개발을 진행하다보면 custom 한 validation annotation 을 만들거나, spring aop 혹은 여러 유틸들을 만들때 유용하게 사용되는데요.
Java 와는 약간 다른 컨셉으로 kotlin 에서는 정의되어 있다보니, 하나씩 차근차근히 봐보도록해요.
Annotation
kotlin 의 어노테이션을 코드와 함께 살펴보도록 해봅시다.
@Target(
AnnotationTarget.FIELD,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.TYPE_PARAMETER,
AnnotationTarget.PROPERTY,
)
@Retention(AnnotationRetention.RUNTIME)
@Repeatable
@MustBeDocumented
annotation class Check(
val description: String = "default value"
)
기본적인 annotation 은 위와 같이 작성할 수 있는데요. 각각의 annotation 의 역할이 무엇인지 정리하면 아래와 같습니다.
종류 | 역할 |
@Target | 해당 Annotation 이 어떤 요소에 붙일 수 있는지 명시합니다. |
@Retention | 해당 Annotation 이 class file 에 저장되어야 하는지 혹은 reflection 을 통해 표시되는지 여부를 명시합니다. |
@Repeatable | 해당 Annotation 이 동일한 요소에 반복해서 명시할 수 있을지 나타냅니다. |
@MustBeDocumented | 해당 Annotation 이 java doc documentation 에 명시되어야 하는지를 나타냅니다. |
하나의 요소들에 대해 천천히 살펴보도록 할게요.
Target
Target 은 Annotation 이 어떤 element 로 지정하게 되는지를 명시한다고 했죠? 종류가 워낙 많아서 정리했습니다.
종류 | 대상 요소 |
CLASS | 클래스 |
ANNOTATION_CLASS | Annotation 클래스 |
FUNCTION | 함수 |
TYPE_PARAMETER | Generic 에서 쓰이는 타입 파라미터 |
FIELD | kotlin property 를 뒷받침하는 backing field |
LOCAL_VARIABLE | 지역 변수 |
VALUE_PARAMETER | 생성자 파라미터 혹은 함수 파라미터 |
CONSTRUCTOR | 생성자 |
PROPERTY | kotlin property |
PROPERTY_GETTER | kotlin property getter |
PROPERTY_SETTER | kotlin property setter |
TYPE | 타입 ( ex)string ) |
TYPE_ALIAS | 타입 alias ( typealias ) |
FILE | 파일 |
EXPRESSION | if else 문과 같은 표현식 |
이렇게 수많은 요소에 annotation 을 붙일 수 있네요. Target 을 지정한 annotation 이라면 명시되지 않은 요소에는 붙일 수가 없습니다.
@Target(
AnnotationTarget.FIELD,
)
@Retention(AnnotationRetention.RUNTIME)
annotation class Check(
val description: String = "default value"
)
위와 같이 field 에만 target 을 지정했다고 하면,
예제처럼 명시한 Target 에만 지정되니 참고해주세요.
만일 @Target Annotation 을 정의하지 않았다면 default 값으로
default | CLASS, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION |
설정되니 참고해주세요 😁
Retention
Retention 은 Annotation 이 실질적으로 어디에 명시될지를 나타냅니다.
- SOURCE: binary 파일로 명시되지 않습니다.
- BINARY: binary 파일에는 명시되지만 reflection 에는 명시되지 않습니다.
- RUNTIME: binary 파일과 reflection 둘다 명시됩니다.
만일 Retention 을 지정하지 않았다면 default 는 RUNTIME 입니다.
그 외
Repeatable 은 단순하게 annotation 을 특정 요소에서 반복해서 나타내는게 가능한지를 확인할 수 있어요.
예를 들면 아래와 같습니다.
@Target(
AnnotationTarget.FIELD,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.TYPE_PARAMETER,
AnnotationTarget.PROPERTY,
)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class Check(
val description: String = "default value"
)
Repeatable 을 없애고, 중복으로 사용하고자 한다면?
위와 같이 compile error 를 맞이합니다.
MustBeDocumented 는 document 생성 시에 영향을 가게 되니,
혹여나 document 를 생성하고자 한다면 그때 붙여주셔도 괜찮습니다
kotlin 에서 Annotation 활용 방법
Annotation 을 생성하는 방법은 알게되었는데, 어떻게 하면 활용할 수 있을까요?
위 예시에 Use-Site Target 을 명시한 예제들을 보셨을텐데요.
Use-Site Target 이 무엇이냐구요? @get:Check 와 같은 문법을 의미합니다.
Annotation 이 어느 위치로 붙어야하는지를 명시하는 것이죠. kotlin 에서는 위 Use-Site Target 을 명시하는게 매우매우 중요합니다.
잘못붙였다가는 당연히 되야하는 기능이 안될 수가 있거든요. ( 예를 들면, spring validation 처럼요 )
종류 | 위치 |
delegate | delegate 된 field 에 위치 |
field | property 에 의해 생성된 field 에 위치 |
file | class 가 선언된 file 에 위치 |
get/set | property getter/setter 에 위치 |
param | constructor 파라미터에 위치 |
property | kotlin property 에 위치 |
receiver | 수신 함수에 위치하게 됩니다. |
이번에도 예제와 같이 살펴볼게요.
@Target(
AnnotationTarget.FIELD,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.TYPE_PARAMETER,
AnnotationTarget.PROPERTY,
AnnotationTarget.PROPERTY_GETTER,
)
@Retention(AnnotationRetention.RUNTIME)
annotation class Check(
val description: String = "default value"
)
data class Student(
@get:Check
val name: String,
val age: Int,
)
property getter 에 위치하도록 정의하고 java 로 변환된 코드를 보면요
getter 에만 명시된 것을 볼 수 있어요. 만일 생성자에도 붙여주고 싶다면?
data class Student(
@get:Check @param:Check
val name: String,
val age: Int,
)
요렇게 쌍으로 붙여주시면 됩니다.
결과는 위와 같이 생성자에도 Check 가 붙고, getter 에도 붙은 것을 볼 수 있죠.
그러면 궁금한게 생깁니다. 만일 Use-Site Target 을 명시안한다면 어떻게 될까요?
data class Student(
@Check
val name: String,
val age: Int,
)
이런이런.. 생성자에만 붙게 되었네요. 왜일까요?
기본적으로 kotlin 에서 use-site target 을 붙이지 않는다면 아래와 같은 우선순위로 강제로 지정하게 됩니다.
- param
- property
- field
즉 아래코드 2개는 같은 코드가 되버리게 되는 것이죠
data class Student(
@Check
val name: String,
val age: Int,
)
data class Student(
@param:Check
val name: String,
val age: Int,
)
이처럼 kotlin 에서는 java 와 다른 성격을 가지고 있기 때문에 꼭 유의해서 사용해야됩니다!
정리하며
kotlin annotation 에 대해 정리해보았는데요! 요약드립니다
- Target 과 Retenetion 의 정책을 꼭 잘 명시하자
- Use-Site Target 에 따라 annotation 이 붙는 위치가 달라지니 default 값을 사용할게 아니라면 꼭 명시하자
Annotations - Kotlin Document
Kotlin Annotations - Baeldung
'Developer > Kotlin & Java' 카테고리의 다른 글
[Kotlin] Coroutine - 6. Suspend 함수에 대해 deep dive 를 해보자 (3) | 2024.03.01 |
---|---|
Java21 Virtual thread vs Kotlin Coroutine - 가상쓰레드와 코루틴에 대해 고찰해보자 (2) | 2024.01.27 |
[Kotlin] Coroutine - 5. 코루틴의 Channel 의 모든 것 (0) | 2023.03.05 |
[Kotlin] Coroutine - 4. 코루틴에서의 예외(exception) 핸들링 (0) | 2023.02.04 |
[Kotlin] Coroutine - 3. 코루틴의 Flow 활용 (2) | 2022.11.27 |