hayu's 개발 일지

[TIL]240503 Custom Annotation과 AOP로 메서드 실행시간 측정하기 본문

스터디/spring

[TIL]240503 Custom Annotation과 AOP로 메서드 실행시간 측정하기

hayu00 2024. 5. 3. 21:30

Custom Annotation과 AOP로 메서드 실행시간 측정하기

실행 시간을 측정하고 싶은 메서드에 @TimeTrace 라는 에너테이션을 추가하면 동작되도록 하기

 

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-aop'
}

 

커스텀 에너테이션을 만든다.

 

TimeTrace.java

package com.sparta.moit.global.config.aop;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Timer { /*타겟은 메서드, 에너테이션이 런타임이 유지되도록*/
}

 

aop를 이용하여 @TimeTrace 어노테이션이 붙은 메서드의 실행 시간을 로그에 출력하는 코드를 짠다.

 

TimeTraceAspect.java

package com.sparta.moit.global.config.aop;

import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Log4j2
@Component
@Aspect
public class TimerAspect {

    // @Pointcut("execution(* com.example.demo.repository..*(..))")
    @Pointcut("@annotation(com.sparta.moit.global.config.aop.TimeTrace)")
    private void timerePointcut() {
    } /*@TimeTrace를 포인트컷으로 지정하는 메서드*/
    

    @Around("timerPointcut()") /*aop의 포인트컷 지정 */
    public Object traceTime(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch(); /*메서드 실행시간 측정을 위해 객체 생성*/

        try {
            stopWatch.start();
            return joinPoint.proceed(); // 실제 타겟 호출
        } finally {
            stopWatch.stop();
            log.info("{} - Total time = {}s", /*로그에 메서드 실행 시간을 기록*/
                    joinPoint.getSignature().toShortString(),
                    stopWatch.getTotalTimeSeconds());
        }
    }
}

⇒ timeTracePointcut()는 포인트컷을 정의하는 메서드이고 @Around는 메서드를 적용하는 것이다. 즉, 둘은 동반되어야한다.

⇒ joinPoint.proceed()는 메서드를 호출하고 ProceedingJoinPoint는 메서드의 정보를 가져온다.

→ return joinPoint.proceed() : 실제 대상 메서드 즉, 커스텀 에너테이션을 호출해서 실행하는것이다. 실제 메서드가 실행 범위 내에서 발생하는 권한은 유지된다. 시간 측정을 위해 호출한다.

 

사용해보기

    /* 인기 모임 top 5 */
    @Timer
    @GetMapping("/popular")
    public ResponseEntity<?> getPopularMeeting() {
        List<GetPopularResponseDto> responseDtoList = meetingService.getPopularMeeting();
        return ResponseEntity.ok().body(ResponseDto.success("인기 모임 top 5", responseDtoList));
    }

 

결과

[2024-05-02 23:17:30.117] [INFO ] [http-nio-8080-exec-2] c.s.m.g.config.aop.TimerAspect MeetingController.getPopularMeeting() - Total time = 1.0474478s

 

참고 자료

- https://velog.io/@hoho4190/Spring-Boot-AOP%EB%A1%9C-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%8B%A4%ED%96%89-%EC%8B%9C%EA%B0%84-%EC%B8%A1%EC%A0%95