Annotation
어노테이션은 사전적인 정의로 주석이라는 의미를 가집니다. 흔히 개발할 때 접할 수 있는 대표적인 어노테이션들로 @Override, @Deprecated 부터 시작해서 Spring에서는 @Service, @Controller등이 있습니다.
JDK 1.5 버전 이상에서 사용 가능하며, 자바 소스 코드에 사이에 @ 기호를 앞에 붙여서 사용할 수 있습니다.
클래스, 필드, 메서드 및 기타 프로그램 요소의 선언부에 사용할 수 있으며, Java 8에 들어와서는 타입 매개변수에도 사용할 수 있게 되었습니다. (관련글 링크)
그렇다면, 왜 어노테이션을 사용할까?
1) 코드가 간결해진다.
개발을 하다보면 저같은 초보 개발자는 보일러 플레이트 코드를 마주하기 쉽습니다. 비슷한 동작을 필요로 하는 곳들마다 보일러 플레이트 코드를 두기 보다는 해당 기능을 어노테이션으로 만들어 제공한다면 불필요한 코드는 줄이고, 개발자는 코드를 유지보수 및 개선할 때마다 모든 곳에 있는 보일러 플레이트 코드를 모두 수정할 필요가 없어집니다.
- 보일러 플레이트 코드(Boilerplate code)란?
- 보일러플레이트 코드는 최소한의 변경으로 여러 곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 의미합니다.
2) 로직을 방해하지 않는다.
3) 정보를 제공할 수 있다.
4) 빠르다. 💨
컴파일할 때 모든 처리를 수행합니다. 때문에 런타임 비용이 들지 않고, 이는 런타임시의 속도 향상을 가져옵니다.
용도
컴파일러를 위한 정보 제공
오류를 감지하거나 경고를 억제하기 위해 주석을 사용할 수 있습니다.
코드 자동 생성
소프트웨어 도구는 주석 정보를 처리하여 코드, XML 파일 등을 생성할 수 있습니다. 대표적으로 @Lombok이 가장 쉽게 접할 수 있는 예가 될 듯 합니다.
런타임에 특정 기능을 수행하도록 정의 가능
특정 기능을 런타임에 수행할 수 있습니다.
처리되는 과정(어노테이션 프로세서의 작동 원리)
별도의 글로 작성될 예정입니다.
종류
내장(Built-in) 어노테이션: Java 코드에 사용
여기에는 @Override, @Deprecated, @SuppressWarnings, @SafeVarargs, @FunctionalInterface 가 존재한다. 이 어노테이션들은 java.lang에 정의되어 있습니다.
@Override
자식 클래스에서 해당 메소드가 부모 클래스에 있는 메서드를 Override 했다는 의미를 가집니다.
@Deprecated
메서드, 클래스 또는 필드를 사용할 때마다 경고를 생성합니다.
@SuppressWarnings
발생할 수 있는 경고에 대해 무시하도록 합니다. 경고를 발생시키지 않습니다.
@SafeVarargs
Java7 전에는 제네릭 가변 인수 메서드(인수 개수를 특정하지 않는 메서드)에서 에러가 발생했을 때 클라이언트 측에서 발생되는 경고를 숨기기 위해서는 가변 인수 메서드마다 @SuppressWarnings 어노테이션을 추가해주어 경고를 숨겨야 했습니다. Java 7에서 @SafeVarargs 어노테이션이 추가되어 코드 작성자(개발자)는 해당 메서드가 Type-Safe함을 보장함으로써 클라이언트 측에서 발생하는 경고를 숨길 수 있게 되었습니다.
Cf. 가변 인수란?
메서드에 전달하는 인수의 개수를 클라이언트가 원하는 대로 전달할 수 있도록 하는 메서드를 의미합니다. 매개변수는 Type... var 형태로 정의합니다.
public class App { public static void print(String... strs) { ... } }
@FunctionalInterface
해당 인터페이스가 Functional Interface임을 나타냅니다.
메타 어노테이션: 어노테이션에 사용
여기에는 @Retention, @Documented, @Target, @Inherited, @Repeatable이 존재합니다. 이 어노테이션들은 java.lang.annotation에 정의되어 있습니다.
@Retention
어노테이션이 얼마나 오래 지속되는지(어떤 특정 시점까지 영향을 미치는지)를 정의합니다.
RetentionPolicy.SOURCE
소스 수준에서만 유지되며, 컴파일러에게는 무시됩니다.
RetentionPolicy.CLASS
컴파일 타임에 컴파일러에서 유지되지만 JVM(Java Virtual Machine)에서는 무시됩니다. - 컴파일러가 클래스를 참조할 때까지 유효
RetentionPolicy.RUNTIME
런타임 환경에서 사용할 수 있도록 JVM에서 유지됩니다. - 컴파일 이후에도 JVM에 의해 계속 참조가 가능 (리플렉션 사용)
@Documented
해당 어노테이션을 Javadoc에 포함시킵니다.
@Target
어노테이션이 적용될 수 있는 Java 요소를 제한합니다.
- ElementType.PACKAGE : 패키지 선언
- ElementType.TYPE : 타입 선언
- ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
- ElementType.CONSTRUCTOR : 생성자 선언
- ElementType.FIELD : 멤버 변수 선언
- ElementType.LOCAL_VARIABLE : 지역 변수 선언
- ElementType.METHOD : 메서드 선언
- ElementType.PARAMETER : 매개변수 선언
- ElementType.TYPE_PARAMETER : 타입 매개변수 선언(Java 8에 추가)
- ElementType.TYPE_USE : 타입 선언(Java 8에 추가)
@Inherited
어노테이션의 상속을 가능하게 합니다. (기본값은 false)
@Repeatable
동일한 곳에 여러 번 사용될 수 있음을 의미합니다. 매개변수로 해당 어노테이션을 담는 어노테이션 컨테이너 클래스를 전달해야 합니다. (Java8 부터 지원)
커스텀 어노테이션
사용자가 개발의 편의를 위해 정의한 사용자 정의 어노테이션을 의미합니다. 어노테이션은 특별한 종류의 인터페이스이므로, 일반 인터페이스와 타입 구분을 위해 @를 앞에 붙여 선언합니다.
public @interface AnnotaionName { ... }
어노테이션을 선언할 때에는 @Retention을 통해 어노테이션의 지속 시간을 정의해주고, @Target을 통해 어떤 곳에 사용할 수 있는 어노테이션인지를 정의해야 합니다.
참고
Oracle Java Documentation; - Lesson: Annotations
Stackoverflow - How do annotations like @Override work internally in Java?
우아한 형제들 기술블로그(어노테이션 사용 예시) - https://techblog.woowahan.com/2684/
'Backend > Java' 카테고리의 다른 글
(메모) Map -> Set -> Iterator 변환하기 (0) | 2024.07.24 |
---|---|
Java 소스 코드의 동작 원리(JVM은 어떻게 동작할까? 메모리와 GC) (0) | 2024.04.08 |
Java8) Annotation 변경 사항(타입 선언부에 사용, @Repeatable) (0) | 2022.12.26 |
Java8) Java 비동기 프로그래밍과 CompletableFuture (0) | 2022.10.31 |
Java8) Java에서 날짜 및 시간을 나타내는 방식 - Date, Time (0) | 2022.10.31 |