사전적 의미로 주석을 의미하며 프로그램에 대한 데이터를 제공하는 메타데이터의 한 형태이다.
✅ 컴파일러에 정보 제공
@Override (컴파일러가 부모 클래스의 메서드를 올바르게 오버라이딩 했는지 검사), @SuppressWarnings✅ 컴파일 및 배포 시간 처리
@Getter, @Setter (컴파일 시점에서 자동으로 getter, setter 메서드를 생성)✅ 런타임 처리 (Java Reflection 활용)
@Autowired (런타임에 자동으로 객체를 주입) 코드가 런타임에 자기 자신을 분석하고 조작할 수 있도록 하는 기능이다. 즉, 클래스, 메서드, 필드 등을 실행 중에 동적으로 가져와 조작할 수 있다.
애노테이션은 @interface 키워드를 사용해 정의하며 내부에 요소를 선언할 수 있다. 이 요소들은 추상 메서드처럼 보이지만 실제 구현할 필요는 없고 애노테이션을 적용할 때 값을 지정한다.
(🔺인터페이스의 추상메서드는 반드시 구현 / 애노테이션은 적용할 때 값만 지정)
@interface 애노테이션이름 {
타입 요소이름(); // 필수 요소
타입 요소이름() default 기본값; // 기본값 지정 가능
}
애노테이션을 사용할 때 요소에 값을 지정하고 순서는 상관없다.
@interface Example {
String name();
int age() default 25; // 기본값 설정 가능
}
@Example(name = "Kim") // age 요소는 기본값(25) 사용
public class MyClass { }
👉 요소의 타입: 기본 타입(int, boolean), String, enum, 다른 애노테이션, 배열만 사용 가능
enum TestType { FIRST, SECOND, THIRD }
@interface DateTime {
String yyyymmdd();
String hhmmss();
}
@interface TestInfo {
int count();
String[] tools();
TestType type();
DateTime testDate();
}
@TestInfo(
count = 3,
tools = {"JUnit", "Mockito"},
type = TestType.FIRST,
testDate = @DateTime(yyyymmdd = "20220204", hhmmss = "102000")
)
public class MyClass { }
👉 기본값 지정 가능: default 키워드를 사용하여 기본값을 설정할 수 있음
👉 NULL 사용 불가: 기본값으로 null을 사용할 수 없음
👉 요소가 하나이고 이름이 value라면 요소명 생략 가능
@interface SimpleAnnotation {
String value();
}
@SimpleAnnotation("Hello") // @SimpleAnnotation(value = "Hello") 와 동일
public class MyClass { }
}
메타 데이터가 데이터에 대한 데이터, 즉 데이터를 위한 데이터인것처럼 메타 애노테이션은 '애노테이션을 위한 애노테이션' 즉 애노테이션을 정의하는데 사용하는 애노테이션이다. 메타 애노테이션은 java.lang.annotation 패키지에 포함되어 있다.
| 애너테이션 | 설명 |
|---|---|
@Target | 애노테이션이 적용가능한 대상 지정 |
@Documented | 애노테이션 정보가 javadoc으로 작성된 문서에 포함되도록 함 |
@Inherited | 애노테이션이 자손 클래스에 상속되도록 함 |
@Retention | 애노테이션이 유지되는 범위를 지정하는데 사용 |
@Repeatable | 애노테이션을 반복해서 적용할 수 있도록 함 |
@Retention 애노테이션은 애노테이션이 유지되는 범위(수명) 를 지정하는 데 사용된다.
| RetentionPolicy 값 | 설명 |
|---|---|
SOURCE | 컴파일 시 제거됨 (소스 코드에서만 유효) |
CLASS | 클래스 파일(.class)에 포함되지만 런타임에는 사용 불가 |
RUNTIME | 런타임에도 유지됨 (리플렉션으로 접근 가능) |
RetentionPolicy 값에 따라 애노테이션이 어디까지 유지되는지 결정
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// 런타임에도 유지되는 애노테이션
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
@MyAnnotation("Hello Retention!")
public class TestClass {
public static void main(String[] args) {
// 리플렉션을 이용해 애노테이션 값 가져오기
MyAnnotation annotation = TestClass.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value()); // Hello Retention!
}
}
@Target 애노테이션은 애노테이션이 적용될 수 있는 위치(대상)를 지정하는 데 사용된다.
| ElementType 값 | 설명 |
|---|---|
TYPE | 클래스, 인터페이스, enum 등에 적용 가능 |
METHOD | 메서드에 적용 가능 |
FIELD | 필드(멤버 변수)에 적용 가능 |
PARAMETER | 메서드 매개변수에 적용 가능 |
CONSTRUCTOR | 생성자에 적용 가능 |
LOCAL_VARIABLE | 지역 변수에 적용 가능 |
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
// 메서드에만 적용할 수 있는 애노테이션
@Target(ElementType.METHOD)
@interface MyMethodAnnotation {
String info();
}
public class TestClass {
@MyMethodAnnotation(info = "This is a test method")
public void myMethod() {
System.out.println("Method executed!");
}
}
@Target(ElementType.METHOD) 로 설정했기 때문에 클래스나 필드에는 적용 불가능하다. @Documented애노테이션은 Javadoc(문서 생성기)에서 애노테이션을 포함할지 여부 를 지정한다. 즉 애노테이션이 Javadoc 문서에 포함되도록 설정할 때 사용한다.
import java.lang.annotation.Documented;
// Javadoc에 포함되는 애노테이션
@Documented
@interface MyAnnotation {
String description();
}
/**
* Example class using MyAnnotation
*/
@MyAnnotation(description = "This is an example class")
public class TestClass { }
컴파일 시 애노테이션을 분석하고 코드 생성 및 검증을 수행하는 도구이다. 자바 컴파일러(javac)가 애노테이션을 감지하면 프로세서를 실행하여 추가 작업을 수행한다.
| 기능 | 설명 |
|---|---|
| 소스 코드 검증 | 애노테이션이 올바르게 사용되었는지 검사 |
| 코드 자동 생성 | 애노테이션을 기반으로 새로운 코드 생성 |
| 메타데이터 처리 | 애노테이션 정보를 분석하여 활용 |
➕ ex) Lombok(@Getter, @Setter) → 컴파일 시 getter/setter 자동 생성
➕ ex) Spring(@ComponentScan) → 특정 애노테이션이 있는 클래스를 찾아 자동 등록
👉 컴파일 시점에 조작하기 때문에 런타임 비용이 제로
1️⃣ 애노테이션 정의
import java.lang.annotation.*;
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface MyAnnotation { }
2️⃣ 애노테이션 프로세서 구현
import javax.annotation.processing.*;
import javax.lang.model.element.*;
@SupportedAnnotationTypes("MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class MyAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
System.out.println("Processing: " + element.getSimpleName());
}
return true;
}
}
3️⃣ 애노테이션 적용
컴파일 시 MyAnnotationProcessor가 실행되어 TestClass 를 처리
@SimpleAnnotation
public class TestClass {
public static void main(String[] args) {
System.out.println("Hello, Annotation Processor!");
}
}