BACK/SPRING

[Spring] AOP란? 용어 정리, 사용 방법

연듀 2021. 10. 18. 21:59

 

AOP란?

 

 

AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불린다.

OOP를 보완하는 수단으로,여러 곳에서 쓰이는 공통 기능을 모듈화하고, 쓰이는 곳에 필요할 때 연결함으로써, 유지 보수 혹은 재사용에 용이하도록 프로그래밍 하는 것이다.

 

중복되는 코드 제거, 효율적인 유지보수, 높은 생산성, 재활용성 극대화, 변화 수용이 용이하다는 장점들이 있다.

 

 

 

 

여러 concerns들과 여러 모듈들이 뒤섞여 있는데, 모듈끼리, concerns끼리 분리한다.

이렇게 분리해 독립된 클래스로 만든 부가기능을 aspect라고 한다. 

프로그램에서 비즈니스 로직을 분리하고, spring framework에서 런타임시 필요한 기능을 주입시킨다.

 

 

이전에는 Callerapp function 을 호출하고 결과를 리턴하는 방식이였다.

AOP에서는 런타임시 Caller에서 Proxy가 가로채 Aspect를 호출한다. Proxy란 대리하여 보조 업무를 처리해주는 역할을 하는 것이다.

프록시는 타겟 객체에 대한 호출을 가로챈 다음 어드바이스의 부가기능 로직을 수행하고 난 후에 타겟의

핵심기능 로직을 호출한다.(전처리 어드바이스)

또는 타겟의 핵심기능 로직 메서드를 호출한 후에 부가기능(어드바이스)을 수행하는 경우도 있다.(후처리 어드바이스)

 

이러한 일을 AOP Weaving(짜집기)이라 한다.

 

Aspect(부가기능)와 target(핵심 기능)은 완전히 분리되어 있고 런타임시 aspect -> target -> aspect 이렇게 호출한다.

 

 

aspect를 사용하려면 pom.xml에서 라이브러리를 다운 받아야 한다.

<dependency>
   <groupId> org.springframework </groupId>
   <artifactId> spring-aspects </artifactId>
   <version> ${org.springframework-version} </version>
</dependency>

 

 

AOP용어

 

aspect

Advice(부가기능) + PointCut(advice를 어디에 적용시킬 것인지 결정)

AOP의 기본 모듈이다.

핵심기능 코드 사이에 침투된 부가기능을 독립적인 aspect로 구분해 낼수 있다.

구분된 부가기능 aspect를 런타임 시에 필요한 위치에 동적으로 참여하게 할 수 있다.

싱글톤 형태의 객체로 존재한다.

 

 

Target

핵심 기능을 담고 있는 모듈로 타겟은 부가기능을 부여할 대상이 된다.

 

Advice

타겟에 제공할 부가기능을 담고 있는 모듈

 

Join Point

어드바이스가 적용될 수 있는 위치

 

Pointcut

어드바이스를 적용할 타겟의 메서드를 선별하는 정규표현식이다.

포인트컷 표현식은 execution으로 시작하고 메서드의 Signature를 비교하는 방법을 주로 이용한다.

 

Weaving

포인트컷에 의해서 결정된 타겟의 조인 포인트에 부가기능(advice)를 삽입하는 과정을 뜻한다.

AOP가 핵심기능(타겟)의 코드에 영향을 주지 않으면서 필요한 부가기능(advice)를 추가할 수 있도록

해주는 핵심적인 처리과정이다.

 

 

 

Aspect안에 실제 부가 기능이 담긴 모듈인 Advice와 그 Advice가 적용될 메서드를 정의하는 Pointcut이 있다.

@Pointcut annotation에 expression을 넣어서 Joinpoint가 무엇인지 지정해준다.

여기선 리턴 타입이 void이고 패키지는 kr.ac.spring~, 모든 클래스(*)안의 sound() 메서드이다.

pointcut의 이름은 메서드 형태로 selectSound()라 해준다. 메서드 이름을 pointcut signiture라고 한다.

 

Advice에는 @Before(pointcut이름), @After(pointcut이름) annotation을 달아주는데

여기선 Before이므로 JoinPoint인 sound()가 호출되기 전에 aboutToSound()가 먼저 호출이 된다. 

 

 

 

 

 

xml로 하는 방법

 

public class Logger {

    public void aboutToSound() {
	System.out.println("before: about to sound");
    }
    …
}

Aspect를 구현한다.

 

<aop:config>
    <aop:aspect id="myAspect" ref="logger">

        <aop:pointcut id="selectSound"  expression 
	    ="execution(void kr.ac.spring.aop.*.sound())"/>

        <aop:before method="aboutToSound"
 		pointcut-ref="selectSound" />

    </aop:aspect>
</aop:config>


<bean id="logger" class="kr.ac.spring.aop.Logger">
</bean>

 

logger라는 클래스를 빈으로 등록한다. 

<aop:config>로 aspect를 정의해준다.

<aop:aspect~>에서 aop ref는 logger로 빈의 id와 같아야 한다.

<aop:pointcut~>에서 joinpoint를 지정해준다.

<aop:before~>로 aboutToSound메서드를 before advice로 지정한다. 

 

 

 

 

 

 

 

=>

AOP를 사용함으로써 여러 개의 클래스에 걸쳐있는 function들을 독립된 클래스로 빼내서 추후에 재사용한 모듈로 만들 수 있다.

Concern분리, 코드를 재사용, 모듈화 가능