sungwony

[스프링] AOP - Aspect Oriented Programming 본문

development/스프링 프레임워크

[스프링] AOP - Aspect Oriented Programming

일상이상삼상 2018. 7. 10. 22:50

객체지향 프로그래밍에서, 부가적인 기능들을 각각 독립적인 클래스로 작성할 수 있지만 그렇게 구현된 기능들을 호출하고 사용할 때는 결국 비지니스 로직이 담긴 핵심 모듈 안에 이런 부가적인 기능을 호출하는 코드들이 포함될 수 밖에 없다.


예를들어 로그와 관련된 코드가 각 메소드의 시작 부분에 작성되고, 전체적으로 수백개의 메소드에 모두 해당 호출부가 들어있다면 호출방식의 변경이 이뤄졌을 경우 모든 메소드의 호출부분을 수정해야 한다.


이에 따른 문제점들을 정리하면 다음과 같다.


1. 코드가 중복됨

- COPY&PASTE

2. 코드가 지저분해짐

- 핵심기능과 부가적인 기능이 혼재

3. 생산성이 저하됨

- 소스의 양이 늘어나고 개발의 집중도가 분산

4. 재활용성이 저하됨

5. 변화가 어려움

- 서로 다른 모듈간의 결합도가 높아 유지보수가 어렵다


AOP(Aspect Oriented Programming)

- 객체지향 프로그래밍

- 로그 처리, 보안, 트랜잭션 관리 그리고 예외사항 처리 등의 코드를 단일 모듈로 각각 작성하고 필요한 시점에 핵심코드를 삽입하여 동작하게 하는 것

- AOP는 OOP를 조금더 OOP 답도록 보완해준다

- 관심의 분리(Separation of Concerns) : AOP의 필요성을 이해하는데 가장 기초가 되는 개념



AOP의 기술 및 용어


Weaving(Crosscutting)

- 핵심 관심 모듈이 자신이 필요한 횡단 관심 모듈을 찾아 사용하는 대신에, 핵심 관심 모듈의 사이사이에 필요한 횡단 관심 코드가 동작하도록 엮어지게 만드는 것

- 기존의 자바 언어와 컴파일러에서 쉽게 구현할 수 있는 방법은 아니다.


AspectJ

- 자바 언어를 확장하여 AOP를 지원하는 최초의 대표적인 언어

- 1990년대 후반 제록스 PARC 연구소에서 개발

 : 자바 VM과 호환되는 최초의 AOP 툴인 AspectJ를 구현

   특별한 컴파일러를 통해 자바 VM에서 사용될 수 있는 코드로 만들어짐

- 2005년 12월 AspectJ 5.0 발표

 : 자바 진영의 다른 AOP 도구인 AspectWerkz 팀의 흡수와 자바 5에서 새롭게 추가된 독특한 기능(제네릭, Annotation) 등을 적극 활용

   aspect 선언을 @AspectJ와 같이할 수 있도록 Annotation 기반의 Weaving 방식이 추가

   기존의 자체 언어 방식이 아닌 자바 정규 문법을 이용하여 작성 가능 -> 순수 자바 컴파일러를 통해서도 개발이 가능하게 됨


AOP의 주요 구성 요소

Joinpoint. Pointcut, Advice, Weaving, Introduction, Aspect


Joinpoint

- 횡단 관심 모듈의 기능이 삽입되어 동작할 수 있는 실행 가능한 특정위치

- 대표적인 Joinpoint

: 메소드가 호출되는 부분 또는 리턴되는 시점

  필드를 액세스하는 부분

  인스턴스가 만들어지는 시점

  예외가 던져지는 시점

  예외 핸들러가 동작하는 위치

  클래스가 초기화되는 곳 등

- 각각의 Joinpoint들은 그 안에 횡단 관심의 기능이 AOP에 의해 자동으로 추가되어서 동작할 수 있는 후보지가 됨


Pointcut

- 어떤 클래스의 어느 Joinpoint를 사용할 것인지를 결정하는 선택 기능

- 예제는 com.multicampus.biz.user 패키지에 있는 UserServiceImpl 클래스의 모든 메소드 호출시점을 Pointcut으로 지정


[applicationContext.xml]

<beans xmlns="http://www.springframework.org/schema/beans" ...>

      <bean id="aroundAdvice" class="com.multicampus.biz.common.FilterAdvice">


      <aop:config>

            <aop:pointcut id="testPointcut" 

              expression="execution(* com.multicampus.biz.user.UserServiceImpl.*(..))"/>

            <aop:aspect id="logAspect" ref="aroundAdvice">

                  <aop:around pointcut-ref="testPointcut" method="filter" />

            </aop:aspect>

      </aop:config>

</beans>


Advice

- 각 Joinpoint에 삽입되어 동작할 수 있는 코드

- 주로 메소드 단위로 구성된 Advice는 Pointcut에 의해 결정된 모듈의 Joinpoint에서 호출되어 사용됨


[applicationContext.xml]

<beans xmlns="http://www.springframework.org/schema/beans" ...>

       <bean id="aroundAdvice" class="com.multicampus.biz.common.FilterAdvice">


       <aop:config>

            <aop:pointcut id="testPointcut" 

              expression="execution(* com.multicampus.biz.user.UserServiceImpl.*(..))"/>

            <aop:aspect id="logAspect" ref="aroundAdvice">

                  <aop:around pointcut-ref="testPointcut" method="filter" />

            </aop:aspect>

        </aop:config>

</beans>


Weaving

- Pointcut에 의해서 결정된 조인포인트에 지정된 Advice를 삽입하는 과정

- AOP가 기존의 핵심 관심 모듈의 코드에 전혀 영향을 주지 않으면서 필요한 횡단 관심 기능을 추가할 수 있게 해주는 핵심과정

- AOP 기술이 핵심 관점의 코드와 전혀 상관없는 부가 관점의 코드가 동시에 실행되게 하는 기술

- 둘 간의 결합이 없는 경우이므로 누군가에 의해 두 코드가 동시에 실행되는 것을 제어해야 함

 -> 이를 제공해주는 것이 Weaving

- Weaving은 별도의 전용 컴파일러를 통한 Compiletime Weaving, 별도의 Agent를 이용해 JVM이 클래스를 로딩할 때 클래스의 바이너리 정보를 변경하는 Loadingtime Weaving, 소스코드나 바이너리 파일의 변경 없이 Proxy를 이용하여 AOP를 지원하는 Runtime Weaving 3가지 방식이 있다. SpringAOP는 이중 Runtime Weaving 방식으로 AOP를 지원한다.


Introduction

- 기존의 클래스와 인터페이스에 필요한 메소드나 필드를 추가해서 사용할 수 있게 해주는 방법

- 정적인 방식의 AOP 기술

- OOP에서 말하는 오브젝트의 상속이나 확장과는 다른 방식으로 Advice 또는 Aspect를 이용해서 기존 클래스에 없는 인터페이스 등을 다이나믹하게 구현해줄 수 있음


Aspect

- Pointcut(어디에서)과 Advice(무엇을 할 것인지)를 합쳐놓은 것

- 필요에 따라 Introduction도 포함할 수 있음

- AspectJ와 같은 자바 언어를 확장한 AOP에서는 마치 자바의 클래스처럼 Aspect를 코드로 작성

- AOP 툴의 종류에 따라서 Advice와 Pointcut을 각각 일반 자바 클래스로 작성하고 이를 결합한 어드바이저 클래스를 만들어 사용


[applicationContext.xml]

<beans xmlns="http://www.springframework.org/schema/beans" ...>

       <bean id="aroundAdvice" class="com.multicampus.biz.common.FilterAdvice">


       <aop:config>

            <aop:pointcut id="testPointcut" 

              expression="execution(* com.multicampus.biz.user.UserServiceImpl.*(..))"/>

            <aop:aspect id="logAspect" ref="aroundAdvice">

                 <aop:around pointcut-ref="testPointcut" method="filter" />

            </aop:aspect>

       </aop:config>

</beans>


'development > 스프링 프레임워크' 카테고리의 다른 글

IoC 컨테이너  (0) 2018.07.03
[Spring Framework] IoC 메모  (0) 2018.07.01
[Spring]스프링 프레임워크 개론  (0) 2017.04.06