스프링

스프링 애스펙트

yoon4360 2025. 4. 4. 21:34

 

스프링 프레임워크는 객체지향 설계 원칙을 충실히 따르면서도,
공통 관심 사항을 코드에서 분리해낼 수 있는 강력한 기능을 제공한다.
그 기능이 바로 AOP (Aspect Oriented Programming), 즉 애스펙트 지향 프로그래밍이다.

 

애스펙트란?

애스펙트는 공통 로직을 핵심 로직과 분리하여 모듈화 하기 위한 개념이다.

 

예: 로그 기록, 보안 검사, 트랜잭션 처리 등은 여러 서비스에서 반복적으로 사용되지만,

이걸 모든 메서드마다 작성하면 중복되고 가독성이 떨어진다.
이런 로직을 하나로 묶고 실행 흐름에 자동으로 삽입하면? → 바로 AOP의 장점이 드러난다.

 


 

스프링 AOP 의 작동 방식

스프링 AOP는 아래 세가지 구성요소를 기반으로 작동한다.

Aspect 실행하고 싶은 공통 기능을 정의하는 클래스이다.
Advice 언제 실행할지를 정의하는 설정이다. (@Before, @After, @Around 등)
Pointcut 어떤 메서드에 적용할지를 정의하는 조건이다.

 

코드 예제

1. 커스텀 애너테이션: @ToLog

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ToLog {}

 

→ 로그를 남기고 싶은 메서드에 이 애너테이션만 붙이면 자동으로 애스펙트가 동작하게 된다.

 

 

2. 비즈니스 로직 CommentService

@Service
public class CommentService {
    private final Logger logger = Logger.getLogger(CommentService.class.getName());
    private Comment comment;

    @ToLog
    public void publishComment(Comment comment) {
        this.comment = comment;
        logger.info("Publishing comment: " + comment.getText());
    }
}

 

→ @ToLog를 붙이면 이 메서드를 호출할 때마다 LoggingAspect와 SecurityAspect가 실행된다.

 

 

3. 실행 전후 로깅 LoggingAspect

@Aspect
@Order(2)
public class LoggingAspect {
    private final Logger logger = Logger.getLogger(LoggingAspect.class.getName());

    @Around("@annotation(ToLog)")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("Logging Aspect 시작");

        Object result = joinPoint.proceed();  // 다음 애스펙트 또는 실제 메서드 호출

        logger.info("Logging Aspect 끝, 결과: " + result);
        return result;
    }
}

 

 

4. 접근 제어 Security Aspect 

@Aspect
@Order(1)
public class SecurityAspect {
    private final Logger logger = Logger.getLogger(SecurityAspect.class.getName());

    @Around("@annotation(ToLog)")
    public Object secure(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("Security Aspect 실행");

        Object result = joinPoint.proceed();

        logger.info("Security Aspect 통과");
        return result;
    }
}

 

@Order 를 통해 애스펙트 실행순서를 조절할 수 있다. 

Main 호출 → SecurityAspect → LoggingAspect → CommentService.publishComment

 

애스펙트에서 할 수 있는 일

  • 메서드 호출 전/후 로직 삽입
  • 매개변수 변경
  • 반환값 변경
  • 예외 감지 및 처리
  • 로깅, 보안 검사, 트랜잭션 처리

 


 

애스펙트 사용시 주의사항

빈 등록 @Aspect만 붙이면 동작하지 않는다. 반드시 @Configuration 클래스에서 직접 Bean으로 등록해야 한다.
프록시 대상 애스펙트를 적용할 클래스는 반드시 스프링 컨텍스트에 등록된 빈이어야 한다.
내부 메서드 호출 같은 클래스 내부에서 메서드 호출 시 프록시를 거치지 않아 애스펙트가 적용되지 않는다.
정상 흐름 유지 가로채서 반환값을 바꾸면 시스템에 부작용이 발생할 수 있으므로 꼭 필요한 경우에만 사용해야 한다.
순서 지정 여러 애스펙트를 사용하는 경우, 실행 순서를 명확히 지정해야 한다 (@Order).

 

 


 

마무리

Spring AOP는 공통된 로직을 분리하고, 비즈니스 로직의 가독성과 유지보수성을 높이는 데 효과적인 도구이다.

  • 반복되는 로깅
  • 보안 검사
  • 트랜잭션 처리
  • 성능 측정
  • 예외 처리

이런 기능들을한 곳에서 선언하고, 자동으로 실행되게 만들면 코드가 훨씬 깔끔해진다.

다만, 적재적소에 신중히 사용하는 것이 핵심이다.