Java 환경(Spring AOP 등)에서 관점 지향 프로그래밍(AOP)을 적용하기 위해 커스텀 어노테이션(Custom Annotation)을 만들 때, 반드시 설정해야 하는 두 가지 핵심 메타 어노테이션인 @Target과 @Retention에 대한 정리
@Target은 어노테이션을 "어디에 부착할 수 있는가"를 결정합니다. 즉, 어노테이션의 적용 대상(Scope)을 제한하는 역할을 합니다.
| 타입 (ElementType) | 설명 | AOP 관련 주요 용도 |
|---|---|---|
| METHOD | 메소드 선언부 | 가장 많이 사용됨. 특정 메소드 실행 전후에 로깅, 트랜잭션, 권한 체크 등을 수행할 때 사용. |
| TYPE | 클래스, 인터페이스, 열거형 | 클래스 전체에 공통 로직을 적용하거나, Controller/Service 등을 식별할 때 사용. |
| FIELD | 멤버 변수(필드) | 필드 값 검증이나 특정 필드 암호화/복호화 등의 처리에 사용. |
| PARAMETER | 메소드 파라미터 | 메소드 인자 값의 유효성 검사나 데이터 가공 시 사용. |
| CONSTRUCTOR | 생성자 | 생성자 실행 시점의 로직 제어. |
@Target({ElementType.METHOD, ElementType.TYPE}) // 메소드와 클래스에 붙일 수 있음
public @interface MyCustomAop { ... }
@Retention은 어노테이션이 "언제까지 살아있는가"를 결정합니다. 즉, 어노테이션의 생명 주기(Lifecycle)를 설정합니다.
@Getter), @Override 등 컴파일 타임에만 의미가 있거나 문서화 목적으로 사용할 때.RUNTIME 정책을 사용해야 합니다.@Retention(RetentionPolicy.RUNTIME) // 런타임까지 유지되어야 AOP 동작 가능
public @interface MyCustomAop { ... }
실제 AOP 적용을 위해 어노테이션을 정의할 때는 보통 아래와 같이 구성합니다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 1. 메소드에만 붙일 수 있도록 제한
@Retention(RetentionPolicy.RUNTIME) // 2. 런타임에 리플렉션으로 읽을 수 있도록 유지
public @interface LogExecutionTime {
}
@Aspect
@Component
public class LogAspect {
// @LogExecutionTime 어노테이션이 붙은 메소드를 타겟으로 함
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed(); // 실제 메소드 실행
long executionTime = System.currentTimeMillis() - start;
System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}