본문 바로가기
Java | spring/Spring

스프링 AOP 기본 개념 잡기!

by 워니 wony 2024. 1. 3.

스프링을 공부하고 서비스를 운영하다 보면 AOP를 적용해야 하는 경우가 생긴다.

핵심 기능은 아니지만, 핵심 기능을 보조하기 위한 부가 기능을 구현해야 하는 경우에 AOP를 사용하게 된다.

기존에 공부하고 사용했던 부분이긴 한데, 오랜만에 강의를 들으면서 공부하니, 정리해 놓으면 좋겠다 싶어서 기본 개념 정리를 해보려 한다.

 

만약 아래와 같은 고민을 하고 있다면 AOP에 대해 공부해 보면 좋다.

  • 공통적으로 처리해야 하는 로직이 있는데, 중요 관심사는 아니다.
  • 추가 기능을 적용해야할 메서드가 많다.
  • 소스 코드에 핵심 로직이 아닌 불필요 로직이 섞여 있는것이 맘에 들지 않는다.

 

나는 아래와 같은 요구 사항이 있어서 AOP를 공부하고 실무에 적용한 적이 있다.

관리자 페이지에서
개인정보가 포함된 정보를
조회하는 경우
조회 데이터 및  조회한 사원의 정보를 저장하는
기능을 추가해주세요!

 

위와 같은 경우는 API에서 핵심로직이 아니고, 로그성 테이블 저장을 해야 하는 케이스이다.

또한, 관리자 페이지에서 호출하는 모든 API에 적용해야 하며, 그 중에서도 개인정보가 포함된 API에만 해당 로직을 추가해야 한다.

그때, 스프링 AOP를 활용해서 어노테이션 기반으로 개발해서 해결했었다.

 

 

AOP

  • Aspect-Oriented Programming 의 약자 AOP, 관점 지향 방식
  • 횡단 관심사를 깔끔하게 처리하기 위해 보조하는 목적으로 사용하는 것
  • 사용 예) 로그 추적, 트랜잭션 기능, 개인정보 조회 데이터 수집 등

 

AOP를 사용하면 공통되게 적용해야 하는 부분을 지정해서 코드를 공통으로 세팅할 수 있다. 만약 관리자에서 사용하는 컨트롤러가 추가된다고 해도 작업한 관련 애노테이션만 추가해 주면 되는 형태로 작업이 가능하다.

 

 

스프링 AOP

  • 스프링도 AOP 지원
    • AspectJ 프레임워크의 문법은 차용하고 있으며, AspectJ 기능 일부를 제공하고 있음
  • 자바 프로그래밍 언어에 대한 완벽한 관점 지향 확장
  • 횡단 관심사 모듈화
  • AOP 적용 방식은 런타임 시점(프록시)로 사용
  • 프록시 방식을 사용하는 스프링 AOP는 메서드 실행 지점에만 AOP 적용 가능
    • 생성자나 static 메서드에는 적용 불가능
  • 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP 적용 가능
참고! 스프링 AOP 말고 AspectJ를 사용하는 경우 더 많은 기능을 사용할 수 있다.(컴파일 시점, 클래스 로딩 시점 등 적용) 하지만, 실무에서는 스프링 AOP를 위주로 사용하는데, 그 이유가 AspectJ는 자바 관련 설정(자바 실행 옵션, 전용 문법 등)이 복잡하고, 사용시 신경써야 하는 부분이 많기 때문이다. 정말 특별한 경우가 아니면 대부분의 문제를 스프링 AOP만으로 해결이 가능하기 때문에 스프링 AOP만 잘 알아놓아도 된다.

 

 

AOP 용어 정리

  • Advice 어드바이스
    • 부가 기능
    • 타켓에 제공할 부가기능을 담고 있는 모듈
    • @Around, @Before, @After 등 다양한 종류의 어드바이스가 있음
  • pointcut 포인트 컷
    • 조인 포인트 중에서 어드마이스가 적용될 위치를 선별하는 기능
    • 프록시를 사용하는 스프링 AOP는 메서드 실행 시점만 포인트 컷으로 선별 가능
    • 주로 AspectJ 표현식을 사용해서 지정
@Pointcut("execution(* com.aop.admin..*(..))")

 

  • Advisor 어드바이저
    • 어드바이스 1개 + 포인트컷 1개로 구성
    •  스프링 AOP에서만 사용되는 용어
  • Aspect 관점, 에스펙트
    • 어드바이스 + 포인트 컷 모듈화 
    • @Aspect
    • 여러 어드바이저와 포인트 컷이 함께 존재
  • joinpoint 조인포인트
    • 어드바이스가 적용될 수 잇는 위치, 실행 지점
    • 조인 포인트는 추상적 개념, AOP 적용 가능한 모든 지점을 뜻함
  • target 타겟
    •  어드바이스를 받는 객체, 포인트 컷으로 결정

 

 

패키지 기반 AOP 적용 소스 코드

@Slf4j
@Component
@Aspect
public class AspectV2 {
    //com.aop.admin 패키지 + 하위 패키지 (
    @Pointcut("execution(* com.aop.admin..*(..))")
    private void allAdmin() {}
    
    @Around("allAdmin()")
    public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("[log] {}", joinPoint.getSignature()); //join point 시그니처
        return joinPoint.proceed();
    }
}

AOP를 적용할 클래스에 @Aspect를 추가하고, 컴포넌트 스캔 시 자동으로 빈으로 등록 될 수 있게 @Component 추가하면 적용이 된다.

 

@Pointcut 에 포인트컷 포현식으로 적용한 패키지를 지정하고(어노테이션 형태로 특정 메서드만 지정하는 것도 가능)하면 해당 패키지에 포함된 클래스에만 적용이 된다.

 

어드바이스 중에 @Around에 포인트컷을 지정해 주고, 로직을 작성하면 해당 로직 안의 내용으로 실행이 되게 된다.

 

 

 

참고! 어드바이스는 기본 순서 보장 하지 않음!!!
어드바이스를 여러개 추가할 수 있는데, 기본적으로는 순서를 보장하지 않는다. 만약 어드바이스의 순서를 지정해야 하는 경우 @Order 어노테이션을 어드바이스에 추가하면 된다. 단! 어드바이스 단위가 아니라 클래스 단위로만 적용가능하기 때문에 어드바이스를 클래스 단위로 작업하고 클래스 상단에 @Order(1), @Order(2) 이런식으로 순서를 지정해야 정상 작동한다.

  

 

Advice 어드바이스 종류

@Around

  • 메서드 호출 전후에 수행
  • 가장 강력한 어드바이스
  • 조인 포인트 실행 여부 선택
  • 전달 값, 반환 값 변환
  • 예외 변환
  • 조인 포인트 실행 재시도 가능

 

@Before

  • 조인 포인트 이전에 실행
  • 작업 흐름 변경 불가하며, 작업 실행 전에 로그를 찍거나 하는 경우에 사용할 수 있음
  • 해당 메서드 종료 시 자동으로 다음 타켓이 호출됨
  • 단, 예외 발생 시 다음 코드 호출되지 않음
    • 단순 로그성 작업의 경우 예외처리가 필요

@After

  • 조인 포인트 정상 또는 예외 발생 시 모두 실행 됨
  • 메서드 실행이 종료되면 실행
  • 일반적으로 리소스 해제 등에 사용됨

 

@AfterReturning

  • 조인포인트가 정상 완료 후 실행
  • 메서드 실행이 정상적으로 반환될 때 실행
  • 반환되는 객체 변경 불가

 

@AfterThrowing

  • 메서드가 예외를 던지는 경우 실행

 

 

 

- 참고) 인프런 강의 - 스프링 고급(김영한)

반응형

댓글