본문 바로가기
[개발] 프레임워크/Spring

Spring AOP

by Devsong26 2024. 6. 26.

AOP(Aspect Oriented Programming), 관점 지향 프로그래밍이란?

애플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스펙트라는 독특한 모듈로 만들어 설계하고 개발하는 방법, OOP를 돕는 보조적인 기술

 

 

Spring AOP의 중요 개념은 아래와 같다.

 

■ 타깃(Target)

타깃은 부가기능을 부여할 대상이다. 핵심기능을 담은 클래스일 수도 있지만 경우에 따라서는 다른 부가기능을 제공하는 프록시 오브젝트일 수도 있다.

 

■ 어드바이스(Advice)

어드바이스는 타깃에게 제공할 부가기능을 담은 모듈이다. 어드바이스는 오브젝트로 정의하기도 하지만 메소드 레벨에서 정의할 수도 있다. 

어드바이스는 여러 가지 종류가 있다. MethodInterceptor처럼 메소드 호출 과정에 전반적으로 참여하는 것도 있지만, 예외가 발생했을 때만 동작하는 어드바이스처럼 메소드 호출 과정의 일부에서만 동작하는 어드바이스도 있다.

 

■ 조인 포인트(Join point)

어드바이스가 적용될 수 있는 위치를 말한다. 스프링의 프록시 AOP에서 조인 포인트는 메소드의 실행 단계뿐이다.

타깃 오브젝트가 구현한 인터페이스의 모든 메소드는 조인 포인트가 된다.

 

■ 포인트컷(Pointcut)

어드바이스를 적용할 조인 포인트를 선별하는 작업 또는 그 기능을 정의한 모듈을 말한다. 스프링 AOP의 조인 포인트는 메소드의 실행이므로 스프링의 포인트컷은 메소드를 선정하는 기능을 갖고 있다. 그래서 포인트 컷 표현식은 메소드의 실행이라는 의미인 execution으로 시작하고, 메소드의 시그니처를 비교하는 방법을 주로 이용한다. 메소드는 클래스 안에 존재하는 것이기 때문에 메소드 선정이란 결국 클래스를 선정하고 그 안의 메소드를 선정하는 과정을 거치게 된다.

 

■ 프록시(Proxy)

클라이언트와 타깃 사이에 투명하게 존재하면서 부가기능을 제공하는 오브젝트다. DI를 통해 타깃 대신 클라이언트에게 주입되며, 클라이언트의 메소드 호출을 대신 받아서 타깃에 위임해주면서, 그 과정에서 부가기능을 부여한다. 스프링은 프록시를 이용해 AOP를 지원한다.

 

■ 어드바이저(Advisor)

포인트컷과 어드바이스를 하나씩 갖고 있는 오브젝트이다. 어드바이저는 어떤 부가기능(어드바이스)을 어디에(포인트컷) 전달할 것인가를 알고 있는 AOP의 가장 기본이 되는 모듈이다. 스프링은 자동 프록시 생성기가 어드바이저를 AOP 작업의 정보로 활용한다. 어드바이저는 스프링 AOP에서만 사용되는 특별한 용어이고, 일반적인 AOP에서는 사용되지 않는다.

 

■ 애스펙트(Aspect)

OOP의 클래스와 마찬가지로 애스펙트는 AOP의 기본 모듈이다. 한 개 또는 그 이상의 포인트컷과 어드바이스의 조합으로 만들어지며 보통 싱글톤 형태의 오브젝트로 존재한다. 따라서 클래스와 같은 모듈 정의와 오브젝트와 같은 실체(인스턴스)의 구분이 특별히 없다. 두 가지 모두 애스펙트라고 불린다. 스프링의 어드바이저는 아주 단순한 애스펙트라고 볼 수도 있다.

 

 

Spring의 Proxy 방식 AOP를 적용하려면 최소한 네 가지 빈을 등록해야 한다.

 

■ 자동 프록시 생성기

스프링의 DefaultAdvisorAutoProxyCreator 클래스를 빈으로 등록한다. 다른 빈을 DI 하지도 않고 자신도 DI 되지 않으며 독립적으로 존재한다. 따라서 id도 굳이 필요하지 않다. 애플리케이션 컨텍스트가 빈 오브젝트를 생성하는 과정에 빈 후처리기로 참여한다. 빈으로 등록된 어드바이저를 이용해서 프록시를 자동으로 생성하는 기능을 담당한다. 

 

■ 어드바이스

부가기능을 구현한 클래스를 빈으로 등록한다. TransactionAdvice는 AOP 관련 빈 중에서 유일하게 직접 구현한 클래스를 사용한다.

 

■ 포인트컷

스프링의 AspectJExpressionPointcut을 빈으로 등록하고 expression 프로퍼티에 포인트컷 표현식을 넣어주면 된다.

코드를 작성할 필요는 없다.

 

■ 어드바이저

스프링의 DefaultPointcutAdvisor 클래스를 빈으로 등록해서 사용한다. 어드바이스와 포인트컷을 프로퍼티로 참조하는 것 외에는 기능은 없다. 자동 프록시 생성기에 의해 자동 검색되어 사용된다. 

 

이 중에서 부가기능을 담은 코드로 만든 어드바이스를 제외한 나머지 세 가지는 모두 스프링이 직접 제공하는 클래스를 빈으로 등록하고 프로퍼티 설정만 해준 것이다.

 

 

애노테이션 트랜잭션 속성과 포인트컷

 

 

위의 글은 "토비의 스프링 3.1 Vol.1 6장 AOP"에 나오는 설명의 일부분이다.

 

간단하게 설명하자면 아래 그림과 같다.

 

Spring AOP Flow

 

 

코드를 예시로 들면 아래와 같다.

package com.example.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TestAspect {

	@Before("execution(* com.example.demo.aop.TargetClazz.run())")
	public void advice(JoinPoint joinpoint) {
		
		System.out.println("■ The advice ran before TargetClazz.run");
	}
	
}
package com.example.demo.aop;

import org.springframework.stereotype.Component;

@Component
public class TargetClazz {

	public void run() {
		System.out.println("■ Target");
	}
	
}

@Aspect를 지정하면 Aspect 모듈이 된다.

단, spring-boot-starter-aop를 사용할 경우 @Component를 반드시 붙여야 한다.

 

어드바이스의 종류는 아래와 같다.

@Before: Pointcut으로 지정된 메소드가 실행되기 전에 수행

@After: Pointcut으로 지정된 메소드가 실행된 후에 수행

@Around: Pointcut으로 지정된 메소드가 실행 전, 후로 수행

@AfterReturning: Pointcut으로 지정된 메소드가 정상적으로 수행이 완료된 경우에만 수행

@AfterThrowing: Pointcut으로 지정된 메소드에서 에러가 발생된 경우에만 수행

 

execution(* com.example.demo.aop.)("execution(* com.example.demo.aop.TargetClazz.run())")은 포인트컷이다.

 

JoinPoint는 Pointcut으로 지정된 메소드(Target)의 정보를 지님

 

 

Reference URL

Spring AOP Flow Diagram

https://howtodoinjava.com/spring-aop-tutorial/

advice types

https://www.tutorialspoint.com/springaop/springaop_advice_types