[Java] 사용자 정의 어노테이션 (Custom Annotation)

해니·2025년 7월 4일
0

Java

목록 보기
32/34
post-thumbnail

커스텀 어노테테이션 생성 방법

  • @interface 키워드를 사용
  • 메소드에 적용 및 런타임에 사용하기 위해 RetentionTarget을 선언한다.

✏️ 어노테이션은 주로 프로그래밍 언어에서 특정 기능이나 동작을 정의하거나 설명하는데 사용되는 메타데이터를 의미한다.



메타 어노테이션 (meta-annotaiton)

  • 다른 annation 에서도 사용되는 annotation 의 경우를 말하며 custom-annotation 을 생성할 때 주로 사용된다.

@Target

@Target(ElementType.FIELD)
  • Java compilerannotation어디에 적용될지 결정하기 위해 사용한다.
  • ElementType의 값들을 사용하여 지정할 수 있다.
ElementType.PACKAGE : 패키지 선언
ElementType.TYPE : 타입 선언
ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
ElementType.CONSTRUCTOR : 생성자 선언
ElementType.FIELD : 멤버 변수 선언
ElementType.LOCAL_VARIABLE : 지역 변수 선언
ElementType.METHOD : 메서드 선언
ElementType.PARAMETER : 전달인자 선언
ElementType.TYPE_PARAMETER : 전달인자 타입 선언
ElementType.TYPE_USE : 타입 선언



@Retention

@Retention(RetentionPolicy.RUNTIME)
  • Annotation 이 실제로 적용되고 유지되는 범위를 의미한다.
RetentionPolicy.RUNTIME  :  컴파일 이후에도 JVM 에 의해서 계속 참조가 가능하다. (주로 리플렉션이나 로깅에 많이 사용됨)
RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때가지 유효하다.
RetentionPolicy.SOURCE : 컴파일 전까지만 유효하다. (컴파일 이후에는 사라짐)



🧩 예시 코드

필드 검증용 어노테이션

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface NotEmpty {
    String message() default "Field cannot be empty";
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Range {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "Value must be within range";
}

어노테이션을 사용 클래스

class User {


	@NotEmpty(message = "사용자명은 필수입니다")
	private String username;
    
	@Range(min = 0, max = 150, message = "나이는 0-150 사이여야 합니다")
    private int age;
    
}



어노테이션 처리 (리플렉션 사용)

class AnnotationProcessor {
    
    public static void validateFields(Object obj) {
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            field.setAccessible(true);
            
            // @NotEmpty 검증
            if (field.isAnnotationPresent(NotEmpty.class)) {
                try {
                    Object value = field.get(obj);
                    if (value == null || value.toString().trim().isEmpty()) {
                        NotEmpty annotation = field.getAnnotation(NotEmpty.class);
                        throw new IllegalArgumentException(annotation.message());
                    }
                } catch (IllegalAccessException e) {
                    // 예외처리
                }
            }
            
            // @Range 검증
            if (field.isAnnotationPresent(Range.class)) {
                try {
                    Object value = field.get(obj);
                    if (value instanceof Integer) {
                        int intValue = (Integer) value;
                        Range annotation = field.getAnnotation(Range.class);
                        if (intValue < annotation.min() || intValue > annotation.max()) {
                            throw new IllegalArgumentException(annotation.message());
                        }
                    }
                } catch (IllegalAccessException e) {
                    // 예외처리
                }
            }
        }
    }
    






출처
Spring Boot 기초: 어노테이션 활용하기 (1편)
Spring Boot 심화: 커스텀 어노테이션 만들기 (2편)
[Spring] Meta Annotation 이란?(@Target, @Retention)
Java annotation(2) - Custom Annotation

profile
💻 ⚾️ 🐻

0개의 댓글