애노테이션

smj_716·2025년 2월 25일

Java-study / live-study

목록 보기
11/16

1. 애노테이션이란?

사전적 의미로 주석을 의미하며 프로그램에 대한 데이터를 제공하는 메타데이터의 한 형태이다.

📢 애노테이션의 용도

컴파일러에 정보 제공

  • 컴파일러가 코드의 오류를 체크하거나 특정 경고 메시지를 억제하는데 사용한다.
  • ex) @Override (컴파일러가 부모 클래스의 메서드를 올바르게 오버라이딩 했는지 검사), @SuppressWarnings

컴파일 및 배포 시간 처리

  • 애노테이션을 이용해 코드 자동 생성이 가능하고 XML 설정 파일 등을 자동으로 생성하는 데 활용된다.
  • ex) Lombok의 @Getter, @Setter (컴파일 시점에서 자동으로 getter, setter 메서드를 생성)

런타임 처리 (Java Reflection 활용)

  • 런타임에 특정 기능을 수행하는 애노테이션이 존재하는데 이를 Reflection API로 접근하여 처리할 수 있다.
  • ex) @Autowired (런타임에 자동으로 객체를 주입)

📢 자바 리플렉션(Java Reflection)

코드가 런타임에 자기 자신을 분석하고 조작할 수 있도록 하는 기능이다. 즉, 클래스, 메서드, 필드 등을 실행 중에 동적으로 가져와 조작할 수 있다.

  • 클래스 정보 조회 → 클래스 이름, 부모 클래스, 인터페이스 정보 가져오기
  • 필드(변수) 값 조회 및 변경 → private 필드도 접근 가능
  • 메서드 실행 → 이름만 알고 있어도 해당 메서드를 호출 가능
  • 생성자 호출 → 클래스 이름만으로 객체를 동적으로 생성

2. 애노테이션 정의하는 방법

💡정의 방법

애노테이션은 @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 { }
}

3. 메타 애노테이션

메타 데이터가 데이터에 대한 데이터, 즉 데이터를 위한 데이터인것처럼 메타 애노테이션은 '애노테이션을 위한 애노테이션' 즉 애노테이션을 정의하는데 사용하는 애노테이션이다. 메타 애노테이션은 java.lang.annotation 패키지에 포함되어 있다.

애너테이션설명
@Target애노테이션이 적용가능한 대상 지정
@Documented애노테이션 정보가 javadoc으로 작성된 문서에 포함되도록 함
@Inherited애노테이션이 자손 클래스에 상속되도록 함
@Retention애노테이션이 유지되는 범위를 지정하는데 사용
@Repeatable애노테이션을 반복해서 적용할 수 있도록 함

➡️ @retention

@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!
    }
}
  • RetentionPolicy.RUNTIME 이므로 리플렉션으로 애노테이션 값을 가져올 수 있다.

➡️ @target

@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

@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 { }

4. 애노테이션 프로세서

컴파일 시 애노테이션을 분석하고 코드 생성 및 검증을 수행하는 도구이다. 자바 컴파일러(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!");
    }
}

0개의 댓글