스프링 AOP

AOP(Aspect-Oriented Programming)는 객체 지향 프로그래밍의 한계를 보완하기 위해 등장한 프로그래밍 패러다임입니다. 스프링 AOP는 스프링 프레임워크에서 AOP를 구현한 것으로, 코드의 횡단 관심사(cross-cutting concerns)를 분리하여 모듈화하고, 공통 로직을 재사용하는 기능을 제공합니다.

AOP에서 횡단 관심사란, 애플리케이션의 여러 부분에서 공통으로 사용되는 로직입니다. 예를 들어, 로깅, 보안, 트랜잭션 관리 등이 있습니다. 이러한 로직은 애플리케이션 전반에 걸쳐 중복되어 사용될 수 있습니다. 이때 AOP를 이용하면 공통 로직을 모듈화하여 각 부분에서 코드의 재사용성과 가독성을 높일 수 있습니다.

스프링 AOP는 프록시 패턴과 런타임 코드 생성을 이용하여, 메서드 호출 시점에 공통 로직을 삽입하는 방식으로 동작합니다. 메서드 호출을 가로채어 공통 로직을 수행하고, 호출한 메서드의 결과를 반환하는 방식입니다. 이를 위해 스프링은 Join Point, Pointcut, Advice, Aspect 등의 개념을 제공합니다.

Join Point는 공통 로직이 삽입될 수 있는 지점으로, 스프링은 메서드 호출을 기준으로 Join Point를 정의합니다. Pointcut은 Join Point 중에서 실제로 공통 로직이 적용될 메서드를 선택하는 기능을 수행합니다. Advice는 실제로 삽입될 공통 로직을 의미합니다. Aspect는 Pointcut과 Advice의 조합으로, 특정한 기능을 담당하는 AOP 모듈을 의미합니다.

스프링 AOP는 프로그램 전반에서 중복되는 로직을 간편하게 모듈화할 수 있는 기능을 제공하여, 코드의 가독성과 재사용성을 높입니다. 또한, 스프링의 다양한 기능과 연동하여, 보안, 로깅, 트랜잭션 처리 등 다양한 영역에서 활용됩니다.

예시

@Aspect
public class LoggingAspect {
    
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Before executing " + methodName + " method");
    }
    
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))",
                    returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("After executing " + methodName + " method");
    }
}

위 코드는 LoggingAspect라는 이름의 클래스를 정의하고, @Aspect 어노테이션을 사용하여 스프링 AOP에서 Aspect로 등록합니다. @Before, @AfterReturning 등의 어노테이션을 이용하여 메서드 실행 전/후에 로그를 출력하는 Advice를 정의합니다.

@Before 어노테이션은 execution 패턴을 이용하여, com.example.service 패키지의 모든 메서드가 실행되기 전에 공통 로직을 수행하도록 설정합니다. JoinPoint 인터페이스를 이용하여 현재 실행되는 메서드의 정보를 추출하고, 메서드 이름을 출력합니다.

@AfterReturning 어노테이션은 실행된 메서드가 정상적으로 반환될 때 공통 로직을 수행하도록 설정합니다. returning 속성을 이용하여 반환된 값을 추출하고, 메서드 이름을 출력합니다.

위와 같이 스프링 AOP를 이용하면 메서드 실행 전/후에 공통 로직을 간단하게 삽입할 수 있습니다.