1. AOP (Aspect Oriented Programming) 란?
2. Spring AOP의 처리 방법과 과정
3. Spring AOP를 이해하기 위한 핵심 용어
4. Application 개발에서 Spring AOP 적용 예제
5. 마무리
AOP는 '관점지향 프로그래밍'으로서 애플리케이션의 핵심 비즈니스 로직과 부가적인 비즈니스 로직, 다시말해 핵심 관점과 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 다양한 기능을 분리하여 보는 프로그래밍 이다.
처음 Spring Framework의 AOP라는 개념을 접했을때 기존에 알고 있던 OOP(Object oriented Programming)와 다른 개념인 줄 알았으나 실제로는 OOP의 연장선에 있는 프로그래밍 방법이었다.
핵심 관점(기능) 과 부가적인 관점(기능)으로 분리하게 되면 기존 코딩방법과 다르게 부가적인 관점, 그 중 여러 핵심 관점에서 반복하여 사용했던 부가적인 관점(공통 관심 사항, 횡단 관심사)을 분리할 수 있고 그로 인해 아래와 같은 효과를 얻을 수 있다.
예를들어 은행 업무와 관련된 프로그램을 개발하던 도중 '계좌 이체' 라는 핵심 기능을 구현했는데 그 핵심 기능을 실행하기 전 '유저의 정보를 다시 확인해야하는 보조기능'을 넣어야한다면 기존 프로그래밍의 경우 핵심 기능에 직접 보조 기능을 넣었어야했다. 그렇게 된다면 해당 보조기능은 핵심 기능에 종속적인 관계가 되고 일부의 수정이 번거롭게 되며 재사용이 어려워진다.
그러나 '유저의 정보를 다시 확인해야하는 보조기능'를 분리하여 AOP나 Interceptor를 사용해서 핵심 기능이 실행 하기 전에 해당 보조기능이 실행되게 설정한다면 기존 작성한 프로그래밍과 기능적 큰 차이는 없지만 해당 보조기능을 '유저 정보 수정' 이라는 또 다른 핵심 기능에서 쉽게 재사용 할 수 있으며, 보조기능이 따로 관리되기에 유지보수에도 용이하다.
(출처 : https://shlee0882.tistory.com/206)
핵심 기능을 종단으로 나열했을 때 핵심 기능안에서 공통적으로 사용되는 부가기능이 마치 횡으로 가로지른 것과 같이 보이기 때문
(출처 : https://cafe.daum.net/flowlife/HrhB/39)
위의 흐름도는 HTTP 프로토콜로 들어오는 요청을 처리하는 과정을 보여준다. 그 중 우리가 Spring AOP를 이해하기 위해 주목해야 할 3부분이 있다. 바로 Filter와 Interceptor와 AOP이다. 앞서 언급한 3가지 컴포넌트들은 Request가 들어왔을때 해당 요청을 가로채어 추가적인 처리를 수행하는 역할을 한다. Spring AOP역시 Joinpoint를 통해 메인 메소드가 실행되는 과정 중에 인터셉트하여 필요한 기능을 실행할 수 있도록 해준다.<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- target / AOP기준 target, 실제 프로젝트 기준 핵심 -->
<bean id="targetClass" class="pack.MessageImpl">
<property name="name" value="한국인" />
</bean>
<!-- Advice(Aspect)를 Target에 위빙 -->
<bean id="loggingAdvice" class="advice.LoggingAdvice" />
<!-- Proxy를 통한 간접 접근 -->
<bean id="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="targetClass" />
</property>
<property name="interceptorNames"> <!-- Collection List -->
<list>
<value>hiAdvisor</value> <!-- 인터셉터는 여러개 걸 수 있다. 그렇기 때문에 List Collection으로 이루어져 있다. -->
</list>
</property>
</bean>
<!-- Advisor(Advise+Pointcut) 설정 -->
<bean id="hiAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<ref bean="loggingAdvice" />
</property>
<property name="pointcut">
<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern">
<!-- 현재 패키지 안에 모든 파일, sayHi가 포함되어있는 모든 메소드가 pointcut 대상이된다. -->
<value>.*sayHi*.</value>
</property>
</bean>
</property>
</bean>
</beans>