Custom Annotation 만들기
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
String level() default "INFO";
boolean trace() default false;
}
| 옵션 |
설명 |
@Target({ElementType.TYPE, ElementType.METHOD}) |
클래스와 메서드에 모두 사용 가능 |
@Retention(RetentionPolicy.RUNTIME) |
런타임에서도 유지 (AOP 활용을 위해 필수) |
String level() |
Annotation 속성값 (기본값 제공 가능) |
boolean trace() |
옵션 처리용 boolean 속성 |
AOP 구현
@Aspect
@Component
public class LogExecutionTimeAspect {
private static final Logger log = LoggerFactory.getLogger(LogExecutionTimeAspect.class);
@Around("@annotation(logExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint,
LogExecutionTime logExecutionTime) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
// Annotation의 속성값을 가져와 활용
String level = logExecutionTime.level();
boolean trace = logExecutionTime.trace();
String message = "[%s] executed in %d ms".formatted(
joinPoint.getSignature().toShortString(), (end - start)
);
if (trace) {
message += " / args=" + Arrays.toString(joinPoint.getArgs());
}
switch (level.toUpperCase()) {
case "DEBUG" -> log.debug(message);
case "WARN" -> log.warn(message);
default -> log.info(message);
}
return result;
}
}
| 코드 |
의미 |
@Around("@annotation(logExecutionTime)") |
Annotation이 붙은 메서드만 감지 |
logExecutionTime.level() |
Annotation 속성 사용 |
joinPoint.getArgs() |
trace 옵션일 때만 파라미터 출력 |
Annotation 사용 예시
@Service
@LogExecutionTime(level = "INFO") // 클래스 전체 메서드에 공통 적용
public class UserService {
@LogExecutionTime(level = "DEBUG", trace = true) // 메서드별 오버라이딩
public void createUser() throws InterruptedException {
Thread.sleep(200);
}
public void deleteUser() throws InterruptedException {
Thread.sleep(100);
}
}
실행 결과
UserService.createUser() executed in 202 ms / args=[] (DEBUG)
UserService.deleteUser() executed in 101 ms (INFO)
실무 사용 예시
| Custom Annotation |
실무 확장 예시 |
@CheckAuth(role = "ADMIN") |
권한 체크 AOP |
@DistributedLock(key = "#userId") |
Redis 분산 락 |
@ApiTrace(masking = true) |
개인정보 마스킹 로그 |