Spring AOP

송윤재·2025년 3월 31일

1. AOP란?

관점 지향 프로그래밍(Aspect-Oriented Programming)
객체 지향 프로그래밍(OOP)으로 해결하기 어려운 공통 관심 사항(Cross-Cutting Concerns)을 분리하여 관리하는 기법
중복 코드를 줄이고, 핵심 비즈니스 로직과 분리하여 유지보수성을 향상

  • 여기서 3개의 A, B, C의 클래스가 있다고 가정합니다.
  • 클래스 A에서는 주황, 파랑, 빨간색 블록으로 구성이 되어 있고 클래스 B에서는 빨강, 주황 블록으로 구성되어 있으며 클래스 C에서는 주황, 파랑 블록으로 구성되어 있습니다. 해당 색은 클래스 A, B, C에서 동일하게 사용되는 코드를 의미합니다.

  • 예를 들어서 클래스 A에서 주황색 블록을 수정을 하게 되면 클래스 B, C에서도 수정을 해야 합니다. 이렇게 되면 유지보수 차원에서 모든 코드를 수정해야 하니 불편한 점이 있습니다. 그래서 Aspect X에서는 공통 관심사인 주황색 블록을 묶어서 모듈화를 시켜서 코드의 재 사용성과 유지 보수성을 강화하였습니다.

이렇듯, 관점 지향 프로그래밍에서는 소스코드에서 반복적으로 사용하는 코드를 하나로 묶어서 모듈화하여 재사용성과 유지 보수성을 높일 수 있는 강점을 가지고 있습니다.

1.1 AOP 적용 사례

  • 로깅(Logging): 메서드 실행 시간 측정, 요청/응답 로깅

  • 트랜잭션 관리(Transaction Management)

  • 보안(Security): 권한 체크

  • 예외 처리(Exception Handling)

1.2 AOP 주요 개념

1.3 AOP 적용 방법

위빙은 대상 객체의 생애 중 수행되는 시점에 따라 아래 3가지로 나뉠 수 있다.

  • 컴파일 타임 위빙(Compile time weaving = CTW)
    타겟 클래스가 컴파일될 때 aspect가 위빙되며 별도의 컴파일러가 필요하다. AspectJ의 위빙 컴파일러는 이러한 목적으로 사용된다.
  • 로드 타임 위빙(Load time weaving = LTW)
    클래스가 JVM에 적재될 때 aspect가 위빙된다. 이를 위해서는 애플리케이션에서 사용되기 전에 타켓 클래스의 바이트코드를 enhance하는 특별한 ClassLoader가 필요하다. AspectJ의 로드시간 위빙 기능을 사용하면 클래스로드시간에 위빙된다.
  • 실행 시간 위빙(Runtime Weaving = RTW)
    애플리케이션 실행 중에 aspect가 위빙된다. 보통 타겟 객체에 호출을 위임하는 구조의 프록시 객체를, 위빙 중에 AOP 컨테이너가 동적으로 만들어낸다. 스프링 자체 AOP의 aspect는 실시간 위빙을 사용한다.

2. Spring AOP

2.1 Spring AOP 개념

  • Spring에서 AOP는 프록시(Proxy) 패턴을 기반으로 동작

  • 프록시 객체가 실제 객체를 감싸서 부가 기능을 제공

  • 실행 시점(Runtime)에 동적으로 적용 가능

2.2 @Aspect 설정 방법

Spring에서는 @Aspect와 @Component를 활용하여 AOP를 구현

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        System.out.println("[LOG] Method 실행 전: " + joinPoint.getSignature().getName());
    }
}

2.3 주요 어노테이션 설명

2.4 @Around 예제 (메서드 실행 시간 측정)

@Around("execution(* com.example.service.*.*(..))")
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    Object result = joinPoint.proceed(); // 실제 메서드 실행
    long end = System.currentTimeMillis();
    System.out.println("[LOG] " + joinPoint.getSignature().getName() + " 실행 시간: " + (end - start) + "ms");
    return result;
}

3. Pointcut 표현식 예제

3.1 execution 패턴 예제

@Before("execution(* com.example.service.*.*(..))")
  • *: 반환 타입 무관

  • com.example.service.*.*(..): service 패키지 내 모든 클래스의 모든 메서드에 적용

3.2 특정 메서드에 적용

@Before("execution(* com.example.service.UserService.getUser(..))")
  • getUser 메서드 실행 전에 AOP 적용

3.3 특정 어노테이션이 있는 메서드에 적용

@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
  • @Transactional이 적용된 메서드에 AOP 적용

4. 결론

  • Spring AOP는 메서드 실행에 대해서만 적용 가능

  • 필드 접근, 생성자 호출 등은 지원하지 않음

  • AOP를 사용하면 공통 기능을 효율적으로 관리할 수 있음

  • @Aspect와 다양한 Advice를 활용하여 필요에 맞게 적용 가능

  • Spring AOP는 프록시 기반이므로 런타임에 동적으로 적용됨

출처

https://adjh54.tistory.com/133
https://velog.io/@youjung/Spring-AOP

profile
CS 공부를 해봅시다

0개의 댓글