Spring 공부

Spring AOP

Rocomi 2024. 10. 12. 23:47

Spring AOP(Aspect-Oriented Programming)는 스프링 프레임워크에서 제공하는 기능으로, 객체 지향 프로그래밍(OOP)의 한계를 보완하고 횡단 관심사(Cross-Cutting Concerns)를 효과적으로 분리하는 프로그래밍 패러다임입니다. AOP는 로깅, 트랜잭션 관리, 보안, 예외 처리 등 여러 클래스에 걸쳐 공통으로 사용되는 코드를 분리하여 코드의 중복을 줄이고, 핵심 비즈니스 로직에 집중할 수 있도록 돕습니다.

AOP의 주요 개념

  1. 횡단 관심사(Cross-Cutting Concern): 여러 모듈에서 공통으로 처리해야 하는 기능(예: 로깅, 보안, 트랜잭션 관리). AOP는 이러한 기능들을 핵심 로직에서 분리합니다.
  2. Aspect(애스펙트): 횡단 관심사를 모듈화한 것. 즉, 여러 클래스에 적용할 수 있는 공통 기능을 정의한 단위입니다. 예를 들어 로깅이나 트랜잭션 관리가 Aspect에 해당합니다.
  3. Join Point(조인 포인트): 애스펙트가 적용될 수 있는 지점. Spring AOP에서는 메서드 호출 시점이 Join Point가 될 수 있습니다. 즉, AOP는 주로 메서드 호출에 대한 동작을 제어합니다.
  4. Advice(어드바이스): 실제로 애스펙트가 수행하는 작업을 의미합니다. 언제, 어떻게 실행될지를 정의하며, 스프링에서 지원하는 어드바이스의 종류는 아래와 같습니다:
    • Before Advice: 메서드 실행 전에 실행.
    • After Returning Advice: 메서드가 성공적으로 실행된 후에 실행.
    • After Throwing Advice: 메서드 실행 중 예외가 발생했을 때 실행.
    • After (Finally) Advice: 메서드 실행 후(예외 발생 여부와 상관없이) 실행.
    • Around Advice: 메서드 호출 전과 후 또는 메서드 실행 자체를 제어할 수 있습니다.
  5. Pointcut(포인트컷): Join Point 중에서 실제로 Advice가 적용될 지점을 선택하는 것. 주로 AspectJ 표현식을 사용해 특정 메서드나 클래스에 애스펙트를 적용할 수 있습니다.
  6. Weaving(위빙): Aspect를 실제 객체에 적용하는 과정입니다. 위빙은 런타임에 적용되며, 스프링에서는 기본적으로 프록시 패턴을 사용하여 런타임에 Aspect를 주입합니다.

Spring AOP의 동작 원리

스프링 AOP는 기본적으로 프록시 기반으로 동작합니다. 스프링 빈으로 등록된 객체에 대해 동적으로 프록시 객체를 생성하고, 실제 객체를 호출하기 전에 프록시 객체가 먼저 인터셉트하여 Advice를 실행합니다.

  • 프록시 패턴: 프록시는 실제 객체 대신 가짜 객체를 만들어 클라이언트와 실제 객체 사이에 위치시킵니다. 이를 통해 클라이언트가 실제 객체에 접근하기 전에 미리 정의된 기능(Advice)을 수행할 수 있습니다.
    • JDK 동적 프록시: 인터페이스를 구현한 클래스에 대해서만 적용할 수 있는 프록시 방식.
    • CGLIB 프록시: 인터페이스가 없는 클래스에도 적용할 수 있는 방식으로, 클래스의 바이트코드를 조작하여 동적으로 프록시를 생성합니다.

AOP의 적용 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Aspect
public class LoggingAspect {
 
    @Before("execution(* com.example.service.*.*(..))")
    public void logBeforeMethod(JoinPoint joinPoint) {
        System.out.println("Method " + joinPoint.getSignature().getName() + " is about to be called.");
    }
 
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("Method " + joinPoint.getSignature().getName() + " returned " + result);
    }
}
 
cs

위 코드는 com.example.service 패키지의 모든 클래스에 있는 메서드가 호출되기 전과 후에 로깅하는 AOP를 정의한 것입니다. @Aspect 애노테이션을 통해 해당 클래스가 Aspect임을 명시하고, @Before, @AfterReturning 등의 어드바이스를 통해 적절한 시점에 원하는 동작을 수행할 수 있습니다.

장점

  1. 관심사의 분리: 핵심 비즈니스 로직과 공통 기능(로깅, 트랜잭션 등)을 분리하여 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
  2. 코드 중복 감소: 여러 클래스에 동일한 코드를 작성하지 않고, 한 곳에서 관리할 수 있습니다.
  3. 유연한 설정: XML 설정이나 어노테이션을 통해 손쉽게 AOP를 설정할 수 있습니다.

단점

  1. 디버깅 어려움: 프록시가 개입하면서 코드의 흐름을 따라가기 어려워질 수 있습니다.
  2. 성능 오버헤드: 프록시 객체를 생성하고 관리해야 하므로 약간의 성능 저하가 발생할 수 있습니다.

결론

Spring AOP는 코드의 관심사를 분리하고, 여러 클래스에 걸쳐 공통된 기능을 쉽게 관리할 수 있게 해주는 강력한 도구입니다. 특히 트랜잭션 관리, 로깅, 예외 처리 등에서 매우 유용하게 사용됩니다.