본문으로 바로가기
반응형

Java Annotation은 메타데이터를 코드에 추가하는 데 사용되며, 이를 통해 다양한 정보를 코드에 부여할 수 있습니다. 하지만 모든 Annotation이 항상 유지되지는 않습니다. Annotation이 어느 시점까지 유지될지는 RetentionPolicy에 따라 결정됩니다.

이 글에서는 RetentionPolicy가 무엇인지, 각 옵션(SOURCE, CLASS, RUNTIME)이 어떤 의미를 가지는지, 그리고 이를 실제로 어떻게 활용할 수 있는지 자세히 살펴보겠습니다.


1. RetentionPolicy란?

Java의 RetentionPolicy는 Annotation이 어느 시점까지 유지될지를 정의합니다. @Retention 어노테이션을 사용하여 RetentionPolicy를 지정할 수 있습니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Logging {
    String value() default "";
}

RetentionPolicy에는 세 가지 옵션이 있습니다:

  1. SOURCE
  2. CLASS
  3. RUNTIME

이 옵션들은 각각 Annotation이 유지되는 기간을 결정합니다.


2. RetentionPolicy의 종류

(1) RetentionPolicy.SOURCE

  • 설명: Annotation이 소스 코드에서만 유지됩니다. 컴파일 이후 .class 파일에는 포함되지 않습니다.
  • 용도: 코드 레벨에서만 필요한 메타데이터로, 런타임이나 컴파일 이후에는 더 이상 필요 없는 경우 사용됩니다.
  • : @Override, @SuppressWarnings

코드 예제

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface DeveloperNote {
    String comment();
}

사용 예제

@DeveloperNote(comment = "This method is critical for performance")
public void process() {
    // 메서드 로직
}

이 @DeveloperNote Annotation은 개발자가 코드를 읽을 때 참고용으로만 사용되며, 컴파일된 .class 파일에는 포함되지 않습니다.


(2) RetentionPolicy.CLASS

  • 설명: Annotation이 컴파일된 .class 파일에 포함되지만, 런타임에는 사용되지 않습니다. JVM이 애플리케이션을 실행할 때는 이 정보를 읽을 수 없습니다.
  • 용도: 런타임에서 필요하지 않지만, 컴파일 이후 다른 도구(예: 바이트코드 분석 도구)에서 활용할 수 있는 메타데이터를 저장할 때 사용됩니다.
  • 기본값: RetentionPolicy.CLASS는 Annotation의 기본 RetentionPolicy입니다.

코드 예제

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface CompileTimeInfo {
    String version();
}

사용 예제

@CompileTimeInfo(version = "1.0.0")
public class MyClass {
    // 클래스 로직
}

이 Annotation은 .class 파일에는 포함되지만, 런타임에 Reflection으로 접근할 수는 없습니다.


(3) RetentionPolicy.RUNTIME

  • 설명: Annotation이 컴파일된 .class 파일에 포함되고, 애플리케이션이 실행되는 동안(JVM 실행 시점)에도 유지됩니다. Reflection API를 사용하여 Annotation 정보를 읽을 수 있습니다.
  • 용도: Spring, Hibernate, JPA 등 다양한 프레임워크와 라이브러리에서 동적으로 Annotation 정보를 처리할 때 사용됩니다.
  • : @Entity, @Transactional, @Component

코드 예제

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Logging {
    String level() default "INFO";
}

사용 예제

@Logging(level = "DEBUG")
public void execute() {
    System.out.println("Executing method");
}

Reflection을 사용하여 Annotation 읽기

import java.lang.reflect.Method;

public class AnnotationTest {
    public static void main(String[] args) throws Exception {
        Method method = AnnotationTest.class.getMethod("execute");
        if (method.isAnnotationPresent(Logging.class)) {
            Logging logging = method.getAnnotation(Logging.class);
            System.out.println("Logging level: " + logging.level());
        }
    }

    @Logging(level = "DEBUG")
    public void execute() {
        System.out.println("Executing method");
    }
}

출력 결과:

Logging level: DEBUG

3. RetentionPolicy 비교

RetentionPolicy소스 코드컴파일된 .class 파일런타임용도

SOURCE 유지 포함 안 됨 사용 불가 개발자 주석, 코드 힌트
CLASS 유지 포함 사용 불가 바이트코드 분석 도구
RUNTIME 유지 포함 사용 가능 Reflection, 프레임워크

4. RetentionPolicy 활용 사례

(1) SOURCE 활용

@Override와 같은 Annotation은 개발자가 코드 작성 시 참고할 수 있도록 도와줍니다. 컴파일 이후에는 의미가 없기 때문에 SOURCE로 설정됩니다.

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface CodeReview {
    String reviewer();
    String date();
}

(2) CLASS 활용

@CompileTimeInfo와 같은 Annotation은 런타임에는 필요 없지만, 컴파일 후 바이트코드를 분석하거나 다른 도구로 처리할 때 유용합니다.

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Generated {
    String value();
}

(3) RUNTIME 활용

@Logging, @Entity, @Component와 같은 Annotation은 런타임에 동적 처리를 위해 사용됩니다. 이는 Spring, Hibernate 등의 프레임워크에서 필수적입니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Transactional {
    String isolation() default "DEFAULT";
}

5. RetentionPolicy 선택 가이드

Annotation을 만들 때, 어떤 RetentionPolicy를 선택할지 다음 기준을 참고하세요:

  1. 개발 단계에서만 필요한 경우: SOURCE를 사용.
    • 개발자가 참고하거나 컴파일러가 경고를 생성하는 용도로 사용.
  2. 런타임에는 필요 없지만, .class 파일에 정보를 포함해야 하는 경우: CLASS를 사용.
    • 바이트코드 분석, 문서 생성 도구에서 사용.
  3. Reflection 또는 프레임워크에서 동적으로 처리해야 하는 경우: RUNTIME을 사용.
    • Spring, Hibernate, JPA 등의 프레임워크에서 Annotation을 활용.

6. 결론

Java의 RetentionPolicy는 Annotation의 유지 기간을 결정하는 중요한 요소입니다. 올바른 RetentionPolicy를 선택하면 코드의 의도를 명확히 하고, 컴파일러와 런타임 환경에서 적절히 동작하도록 제어할 수 있습니다.

  • SOURCE는 코드 힌트와 주석에,
  • CLASS는 바이트코드 분석 및 컴파일 이후 정보 제공에,
  • RUNTIME은 Reflection 및 프레임워크 동작에 사용됩니다.

Annotation을 정의할 때 RetentionPolicy를 적절히 설정하여 효율적이고 명확한 코드를 작성해 보세요!

 

 

 

 

 

반응형