본문 바로가기
Spring

Spring AOP

by yang sing 2023. 6. 13.

지난 포스팅에서 @Async 어노테이션을 사용하여 비동기 멀티 스레드를 구현하는 방식에 대해서 포스팅을 했었다.

해당 기능은 Spring AOP의 기능이라고 작성을 했었는데 이번 포스팅에서는 Spring AOP가 무엇인지, 또 어떻게 사용을 하는지 포스팅을 하고자 한다. 

 

AOP란.

AOP(Aspect-Oriented Programming)는 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법으로 OOP를 보완하는 수단으로 사용.
프로젝트 전반적으로 여러 메소드들에서 반복되는 코드 또는 로직을 모듈화 하여 재사용 할 수 있게 해주는 기능

가장 흔한 예를 들자면 로깅을 하는 기능이 있다고 했을 때 각 메소드 마다 성능 측정 로깅을 넣는다고 하면 메소드 내부에 반복되는 코드들이 계속 늘어날 것이며 유지보수 또한 힘들것이다.

이렇게 반복되는 코드를 따로 끄집어내서 각 메소드에서는 Business logic만 작성 및 동작 시키는게 AOP라고 생각하면 될 것 같다.

 

AOP 적용 방법

1. 컴파일 시점

  • 자바 코드가 컴파일 되는 시점에 적용이 되며 .class 파일에는 이미 코드상으로 해당 AOP 로직이 적용되어있는 상태이다.
  • 로드타임, 런타임에 발생되는 성능 부하가 없다.
  • 별도의 컴파일 과정이 따로 필요하다.

2. 로드 타임 

  •  컴파일 될 시점에는 해당 메서드에는 비즈니스 로직만 존재하며 해당 class 파일이 로딩 되는 시점에 AOP 로직이 적용이 된다.
  • AspectJ를 사용할 수 있어서 다양한 문법을 사용할 수 있다.
  • Load Time Weaving의 java agent 설정을 해줘야 한다.
  • 로드 타임이 진행 될 때 부하가 생성된다.

3. 런타임

  • Spring AOP가 사용하는 방법
  • Spring Application에서 Bean을 만들 때 적용이 된다.
  • 런타임 시 성능 부하가 발생한다. 
  • 별도의 처리 과정이 필요 없다(별도의 컴파일 과정, 별도의 Load Time Weaving 설정)

 

AOP 주요 용어

  1. Aspect
    • Advice와 Pointcut이 포함된 모듈화 된 코드
  2. Target 
    • 적용을 할 대상
  3. Advice 
    • 공통화 시킬 로직을 작성하는 곳
  4. Join point
    • Advice가 합류가 될 위치 또는 지점을 나타내는 용어
    • 메서드 실행 시점, 생성자 호출 시점, 필드 접근 시점 등등 합류점
    • Spring AOP에서는 메서드 실행 시점을 사용한다.
  5. Pointcut 
    • Advice가 실행 될 시점

 

Spring AOP 적용

- 프록시 기반의 AOP 구현체로 Spring Bean에만 적용이 된다.
- Spring AOP는 위에서 설명한 AOP 적용 방법 중 런타임 적용 방법을 사용한다.
- 프록시 패턴의 문제점을 보안하기 위해 스프링 IoC와 Dynamic 프록시를 사용하여 구현한다.

1. 의존성 주입

- Maven
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>2.5.6</version>
</dependency>

- gradle
implementation group: 'org.springframework', name: 'spring-aop', version: '2.5.6'

2. @Aspect 어노테이션을 이용한 Bean 등록

@Component
@Aspect
public class LoggerAspect {

    @Around("@annotation(CustomLogger)")
    public Object CostomLogger(ProceedingJoinPoint joinPoint) throws Throwable{
        // 시작 시간 체크
        long startTime = System.currentTimeMillis();
        // 기존 메소드 호출 (실행)
        Object proceed = joinPoint.proceed();
        // 종료 시간 체크
        long elapsedTime = System.currentTimeMillis() - startTime;

        // 소요 시간 출력
        System.out.println(elapsedTime);

        return proceed;
    }
}

3. Pointcut 정의 하기

- @Around, @Before, @After, @AfterReturing, @AfterThrowing 어노테이션을 통해서 pointcut을 정의한다.

- pointcut 표현식으로 적용 시킬 위치를 표시할 수 있다. ex) execution, within 등등... (추후에 다음 포스팅에서 자세히 다뤄보자)

- @annotation 어노테이션을 사용해서 특정 어노테이션이 붙어있는 method에서 실행 시킬 수 있다.

 

@Around

- method 호출을 감싸는 형식의 어노테이션

- method 전과 후를 감싸서 Advice를 실행

- 아래 4가지의 경우를 하나의 @Around으로 사용이 가능

 

@Before

- method가 실행하기 이전에 무조건 Advice를 실행

 

@After

- method가 실행한 뒤 무조건 Advice를 실행

- method 로직 도중에 Exception이 발생하여 비정상 종료가 되어도 무조건 실행

 

@AfterReturing

- method가 정상 종료 후 Advice를 실행

 

@AfterThrowing

- method가 Exception이 발생해 예외를 던지는 경우에 실행

 

4. AOP 적용

@Service
@RequiredArgsConstructor
public class AspectService {

    @CustomLogger
    public void testSample(String path){
    ...
    비즈니스 로직
    ...
    }
}

- testSample 메소드 위에 내가 미리 정의한 CustomLogger라는 어노테이션을 붙이면 해당 메소드가 실행이 될 때 자동으로 AOP가 실행이 되는것을 확인할 수 있다.

 

 

 

이번 예제에서는 Spring AOP를 어노테이션을 이용한 방법을 포스팅했다. 

그렇다면 어노테이션을 어떻게 만들어야 하는가에 대해서 궁금증이 생길 수 있을것이다. 

다음 포스팅에서는 Spring에서 커스텀 어노테이션을 만드는 방법에 대해서 포스팅을 하도록 하겠다.

 

 

참고 

인프런 강의 - 백기선의 '스프링 프레임워크 핵심 기술'

https://velog.io/@backtony/Spring-AOP-%EC%B4%9D%EC%A0%95%EB%A6%AC

 

Spring - AOP 총정리

Spring의 핵심 개념 중 하나인 DI가 애플리케이션 모듈들 간의 결합도를 낮춘다면, AOP(Aspect-Oriented Programming)는 핵심 로직과 부가 기능을 분리하여 애플리케이션 전체에 걸쳐 사용되는 부가 기능을

velog.io