애노테이션

sungs·2025년 8월 23일

자바

목록 보기
74/95

애노테이션

프로그램 코드처럼 사용할 수 있는 주석이라 이해하면 된다. 앞에 @가 붙어서 사용된다.
기존 CamelCase 방식이 아닌 다른 방식으로 메서드나 클래스를 불러야 할 필요가 있을 때 애노테이션을 사용한다.

@interface

애노테이션은 @interface를 만들어 사용한다.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 이 애노테이션이 적용될 대상(클래스, 메소드, 필드)을 지정합니다.
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
// 이 애노테이션 정보가 유지되는 기간(런타임까지)을 지정합니다.
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    // 문자열 타입 변수
    String stringValue() default "default string";

    // 정수 타입 변수
    int intValue();

    // 불리언 타입 변수
    boolean booleanValue() default false;

    // 문자열 배열 타입 변수
    String[] arrayValue();

    // 열거형 타입 변수
    MyEnum enumValue();

    // 다른 애노테이션 타입 변수
    AnotherAnnotation annotationValue();
}

// 애노테이션 안에서 사용할 열거형
enum MyEnum {
    VALUE1, VALUE2, VALUE3
}

// 애노테이션 안에서 사용할 또 다른 애노테이션
@interface AnotherAnnotation {
    String description();
}

이렇게 해서 만들 수 있다. 애노테이션 안에 다양한 변수를 만들어 나중에 클래스 만들 때 @애노테이션(변수...)으로 붙일 수 있다.

@MyAnnotation(
    intValue = 123,
    arrayValue = {"hello", "java"},
    enumValue = MyEnum.VALUE1,
    annotationValue = @AnotherAnnotation(description = "This is another annotation")
)
public class MyClass {

    @MyAnnotation(
        intValue = 456,
        stringValue = "field annotation",
        arrayValue = {"field"},
        enumValue = MyEnum.VALUE2,
        annotationValue = @AnotherAnnotation(description = "Annotation for a field")
    )
    private String myField;

    @MyAnnotation(
        intValue = 789,
        arrayValue = {"method"},
        enumValue = MyEnum.VALUE3,
        annotationValue = @AnotherAnnotation(description = "Annotation for a method")
    )
    public void myMethod() {
        // ...
    }
}

이렇게 해서 애노테이션에서 만들었던 변수에 값을 넣어 사용할 수 있다. 애노테이션에서 변수 뒤에 deafault 기본값으로 기본값 설정을 했으면 그 변수를 비워놔도 기본값으로 설정된다.

참고로 애노테이션에서 변수는 메서드 형태로 항상 빈 괄호가 있어야 하며, value라는 변수 명만 쓰일 경우 value라는 이름을 안 붙이고 값만 넣어 사용할 수 있다. 예를 들어 value 빼고 다 기본값이면 value의 값을 value도 안 쓰고 값을 넣을 수 있는 것이다.

반환 타입도 void가 아닌 구체적이어야 한다.

애노테이션 안에는 다른 애노테이션, 문자열, 열겨형, 배열, 클래스 등 다양한 타입의 변수가 사용될 수 있다.

여기서 @target은 애노테이션이 적용될 수 있는 대상이다. Method만 걸어놓고 필드에 적용하면 예외가 터진다. 주로 타입, 필드, 메서드를 사용한다.

@Retention은 애노테이션이 언제까지 살아있을지 정하는 것이다.

  • RetentionPolicy.SOURCE: 소스 코드에만 남아 있고 컴파일 시점에 제거된다.
  • RetentionPolicy.CLASS: 기본값으로, 클래스 파일에는 남아 있지만 실행할 때는 제거된다.
  • RetentionPolicy.RUNTIME: 자바 실행 중에도 제거되지 않는다. 대부분 이 설정을 사용한다.

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class AnnotationReader {
    public static void main(String[] args) throws Exception { // 예외 처리 간소화

        // MyClass에 적용된 애노테이션 가져오기
        MyAnnotation classAnnotation = MyClass.class.getAnnotation(MyAnnotation.class);

        // 변수명으로 값 출력
        System.out.println("Class intValue: " + classAnnotation.intValue()); // 출력: 123
        System.out.println("Class stringValue: " + classAnnotation.stringValue()); // 출력: default string
        System.out.println("Class enumValue: " + classAnnotation.enumValue()); // 출력: VALUE1
    }
}

// myField 필드 객체 가져오기
Field field = MyClass.class.getDeclaredField("myField");

// 필드에 적용된 애노테이션 가져오기
MyAnnotation fieldAnnotation = field.getAnnotation(MyAnnotation.class);

// 변수명으로 값 출력
System.out.println("\nField intValue: " + fieldAnnotation.intValue()); // 출력: 456
System.out.println("Field stringValue: " + fieldAnnotation.stringValue()); // 출력: field annotation
// main 메소드 안에 이어서 작성

// myMethod 메소드 객체 가져오기
Method method = MyClass.class.getMethod("myMethod");

// 메소드에 적용된 애노테이션 가져오기
MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);

// 변수명으로 값 출력
System.out.println("\nMethod intValue: " + methodAnnotation.intValue()); // 출력: 789
System.out.println("Method annotation description: " + methodAnnotation.annotationValue().description()); // 출력: 

getAnnotaition으로 리플렉션을 이용해서 애노테이션을 사용할 수 있다.

target, Retention 외에도 @Documented, @Inherited가 있다.

@Documented는 자바 api 문서를 만들 때 사용되고, @Inherited는 애노테이션을 상속할 때 사용된다.

상속

모든 애노테이션은 java.lang.annotation.Annotation 인터페이스를 묵시적으로 상속 받는다. 개발자가 직접 구현하거나 확장할 수는 없다.

  • boolean equals(Object obj): 두 애노테이션의 동일성을 비교한다.
  • int hashCode(): 애노테이션의 해시코드를 반환한다.
  • String toString(): 애노테이션의 문자열 표현을 반환한다.
  • Class<? extends Annotation> annotationType(): 애노테이션 타입을 반환한다.

애노테이션에는 기본적으로 이러한 메서드들이 들어있다.

@Inherited를 사용해서 자식 클래스를 상속할 수 있다. 부모 클래스에 애노테이션을 붙이면 자식 클래스가 부모 클래스를 확장하여 애노테이션을 상속받는다. 인터페이스르 구현하는 방식으로는 안 된다. 인터페이스는 상속이 아닌 구현이고, 여러 인터페이스가 올 수 있어 인터페이스는 안 된다.

profile
앱 개발 공부 중

0개의 댓글