Spring AOP

김현찬·2025년 6월 17일

Spring AOP 정리 – 개념부터 로깅 적용까지

1. AOP란?

AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)은 공통된 기능(=횡단 관심사)을 분리하여 핵심 비즈니스 로직과 독립적으로 관리하기 위한 프로그래밍 패러다임입니다.

  • 예: 로깅, 트랜잭션, 보안, 성능 측정 등

핵심 로직을 건드리지 않고도 공통 기능을 모듈화할 수 있습니다.


2. 핵심 개념 정리

용어설명
횡단 관심사(Cross-cutting Concern)모든 서비스에 걸쳐 중복되는 기능 (ex. 로깅, 인증)
어드바이스(Advice)횡단 관심사를 구현한 실제 실행 코드
포인트컷(Pointcut)어드바이스가 적용될 지점(메서드 범위)을 지정하는 표현식
조인포인트(JoinPoint)어드바이스가 실행될 수 있는 구체적인 실행 지점 (메서드 실행 시점 등)
타겟(Target)어드바이스가 적용되는 실제 객체 (ex. 서비스 클래스)
에스팩트(Aspect)어드바이스 + 포인트컷을 합친 모듈 단위
@Transactional내부적으로 AOP로 구현된 대표적인 어노테이션
@Aspect클래스를 AOP 컴포넌트로 정의하는 어노테이션

3. 어드바이스 종류

어노테이션실행 시점설명
@Before메서드 실행 전사전 작업 수행
@After메서드 실행 후 (성공/실패 모두)무조건 실행
@AfterReturning메서드 정상 종료 후반환값 처리 가능
@AfterThrowing예외 발생 시예외 로깅 등에 사용
@Around전/후/예외 모두 제어실행 시간 측정, 전체 흐름 제어 가능

4. 실전 예제 – 메서드 실행 시간 로깅

@Aspect
public class AopPractice {

    private static final Logger log = LoggerFactory.getLogger(AopPractice.class);

    // [1] 포인트컷: service 패키지 하위 전체 메서드
    @Pointcut("execution(* com.spring.basic.service..*(..))")
    public void serviceLayerPointCut() {}

    // [2] 포인트컷: @TrackTime 어노테이션이 붙은 메서드
    @Pointcut("@annotation(com.spring.basic.aop.TrackTime)")
    public void trackTimePointCut() {}

    // [3] 어드바이스 - 실행 전
    @Before("serviceLayerPointCut()")
    public void beforeMethod() {
        log.info("@Before");
    }

    // [4] 어드바이스 - 정상 실행 후
    @AfterReturning(pointcut = "serviceLayerPointCut()", returning = "result")
    public void afterReturningMethod(Object result) {
        log.info("@AfterReturning");
        log.info("::: result : {}", result.getClass());
    }

    // [5] 어드바이스 - 예외 발생 시
    @AfterThrowing(pointcut = "serviceLayerPointCut()", throwing = "exception")
    public void afterThrowingMethod(Throwable exception) {
        log.info("@AfterThrowing");
        log.info("::: exception: {}", exception.getClass());
    }

    // [6] 어드바이스 - 무조건 실행
    @After("serviceLayerPointCut()")
    public void AfterMethod() {
        log.info("@After");
    }

    // [7] 어드바이스 - Around 위 모든 경우에 사용 가능 ( ex)시간 측정 )
    @Around("trackTimePointCut()")
    public Object AroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            Object proceed = joinPoint.proceed();
            log.info("@AfterReturning");
            return proceed;
        } catch (Throwable e) {
            log.info("@AfterThrowing");
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            log.info("::: executionTime: {}ms", executionTime);
        }
    }
}

0개의 댓글