Java 애노테이션

유기훈·2025년 3월 3일

메타 애노테이션

애노테이션을 정의하는데 사용하는 애노테이션을 메타 애노테이션이라고 한다.

@Retention

애노테이션의 생존 기간을 정의한다.

  • SOURCE: 컴파일러까지만 유지됨. (바이트코드에 포함되지 않음)
  • CLASS: 바이트코드에 포함되지만 런타임에는 사용 불가 (기본값)
  • RUNTIME: 런타임까지 유지되며 Reflection을 통해 접근 가능

@Target

애노테이션을 어디에 적용할 수 있는지를 지정한다.

적용 가능한 대상 목록:

  • ElementType.TYPE : 클래스, 인터페이스, enum 등에 적용
  • ElementType.METHOD : 메서드에 적용
  • ElementType.FIELD : 필드(멤버 변수)에 적용
  • ElementType.PARAMETER : 매개변수에 적용
  • ElementType.CONSTRUCTOR : 생성자에 적용
  • ElementType.ANNOTATION_TYPE : 다른 애노테이션에 적용 가능
  • ElementType.LOCAL_VARIABLE : 지역 변수에 적용

@Documented

애노테이션을 JavaDoc 문서에 포함할지를 결정한다.
기본적으로 애노테이션은 JavaDoc에서 보이지 않는다. 이 애노테이션을 붙이면 JavaDoc에서 노출된다.

@Inherited

부모 클래스의 애노테이션을 자식 클래스에서 자동으로 상속하도록 한다.
기본적으로 애노테이션은 상속되지 않는다.

@Repeatable

같은 애너테이션을 중복해서 사용 가능하다.
Java8 이상 부터 사용가능하다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(MyAnnotations.class) // 같은 애노테이션을 여러 개 적용할 수 있도록 설정
@interface MyAnnotation {
    String value();
}

// 여러 개의 MyAnnotation을 감싸는 컨테이너 애노테이션 필요
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotations {
    MyAnnotation[] value();
}

// 사용 예시
class Example {
    @MyAnnotation("A")
    @MyAnnotation("B")
    public void myMethod() {}
}

애노테이션 상속

Java에서는 기본적으로 애노테이션은 상속되지 않는다. 하지만 @Inherited 메타 애노테이션을 사용하면, 클래스에서만 애노테이션이 상속될 수 있다.

@Inherited 애노테이션의 동작 방식

@Inherited를 붙이면 부모 클래스에 선언된 애노테이션이 자식 클래스에서도 자동으로 적용된다.


@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {
}

@MyAnnotation
class Parent {}

class Child extends Parent {}

public class Test {
    public static void main(String[] args) {
        System.out.println(Child.class.isAnnotationPresent(MyAnnotation.class)); // true
    }
}

@Inherited가 인터페이스에는 적용되지 않는다.

@Inherited는 클래스 계층 구조에서만 동작하며, 인터페이스에는 적용되지 않는다.

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {}

@MyAnnotation
interface MyInterface {}

class MyClass implements MyInterface {}

public class Test {
    public static void main(String[] args) {
        System.out.println(MyClass.class.isAnnotationPresent(MyAnnotation.class)); // false
    }
}

그 이유는?

  1. 클래스와 인터페이스의 차이점
  • 클래스는 단일 상속, 인터페이스는 다중 구현이 가능.
  • 만약 인터페이스에서 애노테이션이 상속된다면, 하나의 클래스가 여러 인터페이스를 구현할 때 충돌 가능성 발생.
  1. Java의 설계 원칙
  • 애노테이션은 기본적으로 구체적인 구현을 설명하는 것이 많음. (예: @Controller, @Service)
  • 인터페이스는 행동(behavior) 정의 역할이므로, 애노테이션을 상속할 필요가 없음.
profile
개발 블로그

0개의 댓글