[Spring Framework] AOP

🧩 AOP란 무엇인가?

AOP(Aspect-Oriented Programming)는 객체 지향 프로그래밍의 한계를 보완하는 프로그래밍 패러다임이다. AOP는 애플리케이션 전반에 걸쳐 중복적으로 사용되는 공통 관심사(cross-cutting concerns)를 모듈화하여 코드의 재사용성과 유지보수성을 높이는 데 중점을 둔다. 공통 관심사의 예시에는 로깅, 트랜잭션 관리, 보안, 캐싱, 오류 처리 등이 있다.


🔑 AOP의 주요 개념

🎯 포인트컷 (Pointcut)

포인트컷(Pointcut)어드바이스를 적용할 조인 포인트(Join Point)를 선택하는 표현식이다. 조인 포인트는 메서드 실행, 객체 생성, 필드 접근 등 다양한 애플리케이션 실행 지점을 나타낸다.

예시:

1
2
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}

이 포인트컷은 com.example.service 패키지의 모든 클래스의 모든 메서드를 대상으로 지정한다.

📊 포인트컷 표현식

  • execution(): 메서드 실행 조인 포인트를 매칭
  • within(): 특정 타입 내의 조인 포인트를 매칭
  • this(): 프록시 객체를 대상으로 하는 조인 포인트를 매칭
  • target(): 대상 객체를 대상으로 하는 조인 포인트를 매칭
  • args(): 메서드의 인자를 대상으로 하는 조인 포인트를 매칭

💡 어드바이스 (Advice)

어드바이스(Advice)는 AOP에서 “무엇을” 할 것인지를 정의하는 부분이다. 즉, 횡단 관심사(cross-cutting concern)의 구현체라고 할 수 있다. 어드바이스는 특정 조인 포인트에서 실행될 실제 로직을 포함하고 있다.


📚 어드바이스 유형

⏮️ Before

  • 조인 포인트 실행 전에 실행된다.
  • 예: 메소드 실행 전 로깅, 파라미터 유효성 검사
    1
    2
    3
    4
    
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
      System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
    

⏭️ After

  • 조인 포인트 실행 후 항상 실행된다.(정상 종료, 예외 발생 모두 포함)
  • 예: 리소스 정리, 통계 업데이트
    1
    2
    3
    4
    
    @After("execution(* com.example.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
      System.out.println("After method: " + joinPoint.getSignature().getName());
    }
    

✅ AfterReturning

  • 조인 포인트가 정상적으로 종료된 후 실행된다.
  • 예: 반환값 로깅, 추가 결과 처리
    1
    2
    3
    4
    
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
      System.out.println("Method returned: " + result);
    }
    

❌ AfterThrowing

  • 조인 포인트에서 예외가 발생했을 때 실행된다.
  • 예: 예외 로깅, 추가적인 예외 처리
    1
    2
    3
    4
    
    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
      System.out.println("Exception in " + joinPoint.getSignature().getName() + ": " + error);
    }
    

🔄 Around

  • 가장 강력한 어드바이스로, 조인 포인트 실행 전후에 로직을 실행할 수 있다.
  • 조인 포인트 실행 여부를 직접 제어할 수 있다.
  • 예: 메소드 실행 시간 측정, 트랜잭션 관리
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
      long start = System.currentTimeMillis();
        
      Object result = joinPoint.proceed(); // 실제 메소드 실행
        
      long executionTime = System.currentTimeMillis() - start;
      System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
        
      return result;
    }
    

🔗 어드바이저 (Advisor)

어드바이저(Advisor)포인트컷어드바이스를 결합하여 특정 상황에서 특정 동작을 수행하도록 한다. Spring AOP에서는 @Aspect 어노테이션을 사용해 어드바이저를 정의한다.

예시:

1
2
3
4
5
6
7
8
9
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logMethodEntry(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Entering method: " + methodName);
    }
}

💻 실제 사용 예시

트랜잭션 관리를 AOP로 구현한 예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Aspect
@Component
public class TransactionAspect {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    @Around("@annotation(Transactional)")
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            Object result = joinPoint.proceed();
            transactionManager.commit(status);
            return result;
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

이 예시에서는 @Transactional 어노테이션이 붙은 메서드에 대해 트랜잭션을 자동으로 관리한다.

Leave a comment