IT 정보/Spring

[Spring] 스프링 AOP (Spring AOP)란 무엇인가? 프록시 기반 AOP, @AOP

개발하는 동그리 2025. 4. 15. 13:48
스프링 AOP (Aspect Oriented Programming) : 관점 지향 프로그래밍
  • AOP는 관점 지향 프로그래밍의 약자이다.
  • 객체 지향 프로그래밍 (OOP)이 '클래스 단위'로 관심사를 분리했다면, (AOP)는 '관심사 단위'로 분리하여 횡단 관심사 (Cross-Cutting Concern)를 모듈화할 수 있게 해줍니다.

 

횡단 괌심사(Cross-Cutting Concern)란?  
  • 애플리케이션의 여러 모듈에 공통적으로 적용되어야 하는 기능.
  • 예: 로깅, 보안, 트랜잭션, 성능 모니터링, 예외 처리 등.
  • 이들을 비지니스 로직에서 분리하지 않으면, 코드 중복과 유지보수 어려움이 발생.

 

용어 정리
  • Aspect(관점) : 공통 기능(횡단 관심사)을 모듈화 한 것. 
    • ex) 트랜잭션 처리 모듈
  • Join Point : Aspect가 적용될 수 있는 지점 
    • ex) 메서드 실행, 필드 접근 등이 있고, 스프링 AOP에서는 메서드 실행만 지원
  • Advise : 언제, 무엇을 실행할지를 정의. 즉, 실질적인 부가 기능 코드
  • Pointcut : Advise를 적용할 Join Point를 지정하는 표현식
  • Weaving : Aspect와 대상 객체를 결합하여 하나의 객체로 만드는 과정
  • Target (대상 객체)  : 부가기능이 적용되는 실제 비지니스 로직 객체
  • Proxy (프록시 객체) : Target을 감싸고 Advice가 적용된 객체 (실제 호출 대상은 Proxy가 됨)

 

스프링 AOP의 특징
  • 프록시 기반 AOP를 사용 (런타임 시점에 동적으로 프록시 객체 생성)
    • JDK Dynamic Proxy : 인터페이스 기반
    • CGLIB Proxy : 구체 클래스 기반
  • AspectJ 문법 일부 지원 (단, AspectJ 컴파일러를 사용하지 않고 프록시 방식 사용)
  • 메서드 실행 지점만 Join Point로 지원 (보다 정적인 위빙을 원하면 AspectJ 사용 필요)

 

Advise의 종류
  • @Before : 메서드 실행 전에 수행  -- ex) 보안 검사, 로깅 시작 등
  • @After : 메서드 실행 후 (성공/예외 무관) -- ex) 리소스 정리
  • @AfterReturning : 메서드가 정상적으로 리턴된 후 -- ex) 로그 출력, 후처리
  • @AfterThrowing : 메서드 실행 중 예외 발생시 -- ex) 에러 로그, 트랜잭션 롤백 등
  • @Around : 메서드 실행 전후 모두 관여 -- ex) 트랜잭션 처리, 실행 시간 측정 등

 

스프링 AOP 구현 예시
// 1. 의존성 추가 (spring-boot-starter-aop)
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>



// 2. Aspect 클래스 정의
@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void logBeforeMethod(JoinPoint joinPoint) {
        System.out.println("Before: " + joinPoint.getSignature().getName());
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterMethod(JoinPoint joinPoint, Object result) {
        System.out.println("After: " + joinPoint.getSignature().getName() + " returned " + result);
    }
}


// 3. AOP 적용 대상 서비스 예시
@Service
public class UserService {
    public String getUser() {
        return "User123";
    }
}

 

 

스프링 AOP의 내부 동작 방식
  1. 애플리케이션 구동 시
    • AOP 애너테이션을 탐색하여 Aspect로 등록된 클래스를 스프링이 감지
    • @EnableAspectJAutoProxy가 활성화되면, AOP 프록시 자동 생성
  2. 프록시 객체 생성
    • JDK Dynamic Proxy 또는 CGLIB으로 Target을 감싼 프록시 객체 생성
    • Bean 등록 시 실제 객체가 아닌 프록시가 컨테이너에 등록됨
  3. Advice 실행
    • 클라이언트가 메서드 호출 시 프록시가 중간에 Advice를 실행
    • Pointcut 조건에 따라 Advice가 적용될 지 판단

 

 

스프링 AOP (@Transaction) 작동 방식
// @Transactional = AOP 기반의 트랜잭션 처리

@Service
public class OrderService {
    @Transactional
    public void placeOrder() {
        // 여러 DB 작업 수행
        // 예외 발생 시 전체 롤백
    }
}


// 실제 코드로 보는 @Around 구조 예시
@Aspect
@Component
public class TransactionAspect {

    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    public Object aroundTransactionalMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            System.out.println("🔄 트랜잭션 시작");
            Object result = joinPoint.proceed(); // 실제 placeOrder 실행
            System.out.println("✅ 트랜잭션 커밋");
            return result;
        } catch (Exception e) {
            System.out.println("❌ 트랜잭션 롤백");
            throw e;
        }
    }
}


// 그림으로 봤을 때 
[Client 호출]
     ↓
[프록시 객체] ←——————— AOP 적용 (@Around)
     ↓
[트랜잭션 시작]  ←———— Advice
     ↓
[실제 placeOrder 메서드 실행]
     ↓
[정상/예외 판단 → 커밋 or 롤백]
     ↓
[결과 반환]
  • 위 코드에서 @Transactional 을 붙이면, Spring은 이 클래스 또는 메서드를 대상으로 AOP 프록시 객체를 생성합니다.
  • AOP 흐름 요약
    1. placeOrder()를 호출하면, 실제로는 프록시 객체가 호출됩니다.
    2. 프록시는 내부적으로 트랜잭션을 시작합니다.
    3. placeOrder()의 비지니스 로직이 실행됩니다.
    4. 예외가 발생하지 않으면, 트랙잭션 커밋
    5. 예외가 발생하면 트랜잭션 롤백
  • 이렇게 트랜잭션 처리 전후의 로직이 @Around Advice로 감싸진 행태로 AOP가 적용되어 있습니다.

 

스프링 AOP의 장점과 한계
  • 장점
    • 핵심 로직과 부가 로직 분리로 모듈화 향상
    • 코드 중복 제거
    • 유지보수 및 테스트 용이성 증가
  • 단점
    • 스프링 AOP는 메서드 실행 Join Point만 지원
    • 프라이빗 메서드에는 적용 불가 (프록시 기반 한계)
    • AspectJ처럼 정적 위빙 지원 안함 (복잡한 AOP는 AspectJ 권장)

 

스프링 AOP는 횡단 관심사를 깔끔하게 분리하여 코드의 가독성과 유지보수성을 크게 향상시켜 줍니다. (Logging, Transaction, Security, Monitoring) 등의 공통 기능을 Aspect로 모듈화함으로써 비지니스 로직의 순수성을 유지하는데 매우 유용한 도구입니다.