[Spring Boot] Spring AOP

끝으로 ㅣ 2025. 2. 7. 18:39

1. AOP란?

AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 비즈니스 로직과 공통 기능을 분리하여 중복 코드를 줄이고 유지보수성을 높이는 프로그래밍 패러다임이다

 

AOP의 핵심 개념

  • 관점(Aspect): 비즈니스 로직과 관계없이 여러 곳에서 공통적으로 적용되는 기능 (예: 로깅, 트랜잭션 관리 등)
  • 핵심 로직(Core Concern): 애플리케이션의 주요 비즈니스 로직
  • 공통 관심 사항(Cross-Cutting Concern): 여러 클래스에서 반복적으로 나타나는 부가 기능

 

AOP의 역할

AOP는 비즈니스 로직의 특정 시점을 가로채어 전후 처리를 가능하게 해주는 기술

  • 비즈니스 로직과 공통 기능을 분리하여 코드 중복을 줄임
  • 애플리케이션의 가독성과 유지보수성을 향상

 

AOP의 주요 활용 사례

  • 로깅 (Logging): 메서드 실행 전후의 로그 기록
  • 트랜잭션 관리 (Transaction Management): 트랜잭션 자동 처리
  • 예외 처리 (Exception Handling): 공통적인 예외 로깅 및 예외 변환
  • 보안(Security): 접근 권한 제어

 

2. AOP 주요 개념과 용어

Advice 언제 공통 기능을 핵심 기능에 적용할지 정의
JoinPoint Advice를 적용 가능한 지점 (예: 메서드 호출, 필드 값 변경)
Pointcut JoinPoint의 부분집합 (특정 조건을 만족하는 JoinPoint)
Weaving Advice를 핵심 로직 코드에 적용하는 과정
Target Object 하나 이상의 Aspect에 의해 Advice가 적용되는 객체
Aspect 여러 객체에 공통으로 적용되는 공통 관심 사항을 정의하는 모듈

 

 

3. Spring AOP 적용 방식

1) @Aspect 사용 (Spring AOP 기본 제공 방식)

Spring은 @Aspect를 활용하여 AOP를 적용할 수 있음

@Aspect
@Component
public class LoggingAspect {
    
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("메서드 실행 전: " + joinPoint.getSignature().getName());
    }
}
  • @Aspect: 이 클래스가 AOP 기능을 담당하는 Aspect임을 선언
  • @Component: Spring이 관리하는 Bean으로 등록
  • @Before: 메서드 실행 전에 수행될 Advice 설정

 

2) Spring AOP 적용 과정

  1. @EnableAspectJAutoProxy를 설정하면 Spring이 AOP 기능을 활성화
  2. @Aspect를 선언한 클래스에서 Advice와 Pointcut을 정의
  3. Spring이 자동으로 Weaving하여 해당 로직을 메서드 실행 전후에 삽입

 

4. Advice 유형과 사용법

1) @Before - 메서드 실행 전 처리

@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
    System.out.println("메서드 실행 전: " + joinPoint.getSignature().getName());
}
  • Target 객체의 메서드가 실행되기 전에 실행되는 Advice
  • joinPoint를 통해 메서드 이름 및 파라미터 정보 조회 가능

 

2) @After - 메서드 실행 후 처리 (예외 발생 여부 무관)

@After("execution(* com.example.service.*.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
    System.out.println("메서드 실행 후: " + joinPoint.getSignature().getName());
}
  • 메서드가 정상 종료되든, 예외가 발생하든 무조건 실행됨
  • 리턴값이나 예외 정보를 직접 전달받지는 못함

 

3) @Around - 메서드 실행 전후 처리 (가장 강력한 Advice)

@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    
    Object result = joinPoint.proceed();  // 메서드 실행

    long endTime = System.currentTimeMillis();
    System.out.println("메서드 실행 시간: " + (endTime - startTime) + "ms");

    return result;
}
 
  • joinPoint.proceed()를 호출해야 Target 메서드가 실행됨
  • 실행 전후의 로직을 모두 제어할 수 있어 가장 유연한 방식

 

4) @AfterReturning - 정상 실행 후 처리

@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
    System.out.println("메서드 정상 종료: " + joinPoint.getSignature().getName() + " 반환값: " + result);
}
  • 메서드가 정상적으로 실행된 후 실행됨
  • returning 속성에 리턴값을 받을 변수명을 지정하여 리턴값 활용 가능

 

5) @AfterThrowing - 예외 발생 시 처리

@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void afterThrowingAdvice(JoinPoint joinPoint, Throwable ex) {
    System.out.println("메서드 실행 중 예외 발생: " + joinPoint.getSignature().getName() + " 예외: " + ex.getMessage());
}
  • 예외가 발생한 경우 실행됨
  • throwing 속성에 발생한 예외를 받을 변수명을 지정

 

결론

AOP는 비즈니스 로직과 공통 관심 사항을 분리하여 코드 중복을 줄이고 유지보수성을 높일 수 있기 때문에 보다 효율적이고 확장성 있는 서비스를 개발할 수 있다.

'Spring Boot' 카테고리의 다른 글

[Spring Boot] Filter와 Interceptor  (0) 2025.02.02
[Spring Boot] Redisson 분산 락  (0) 2024.06.09
[Spring Boot] OTP 2차 인증  (0) 2024.04.30