2014년 11월 12일 수요일

[SPRING] AOP (Aspect Oriented Programming)

[SPRING] AOP (Aspect Oriented Programming) 


1. AOP 목적


AOP 개념을 이해하기 전에 "횡단관심사"라는 단어를 이해할 필요가 있다.

횡단관심사란 보안, 로깅, 트랜젝션등과 같은 기능들처럼 한 애플리케이션의 여러부분에 걸쳐 있는 기능을 의미한다. 
즉, 횡단관심사는 한마디로 한 애플리케이션의 여러부분에 영향을 주는 기능이라고도 할 수 있다.



[참조: 스프링 인 액션]

위 그림을 보면 한 애플리케이션이 여러모듈로 분해된 모습을 보여준다.
각 모듈들은 각자 자기가 맡은 서비스 제공을 위하여 사용되지만 이 모듈들은 모두 보안과 트랜젝션관리 같은 보조 기능을 필요하다.

공통기능을 재사용하는 상속같은 개념도 있지만 상속은 객체의 정적구조에 의존하기 쉽기 때문에 복잡하고 깨지기 쉬운 구조로 되어있다.

물론 AOP도 공통적으로 한 곳에 공통기능을 정의한다는 것은 같다 

하디만 이 기능을 어디에 어떻게 적용할 지 선언할 수 있고 대상 클래스를 전혀 수정할 필요가 없다는 것이 가장 큰 차이점이다. 

정리하자면 AOP는 이러한 횡단관심사의 분리를 위하여 나왔으며 , 횡단관심사를 모듈화를 하기 위하여 AOP라는 개념이 등장하였다.



2. AOP 개념 



AOP 목적에서 우리는 횡단괌심사를 모듈화하기 위하여 AOP를 만들었다고 하였다.
여기서 우린 AOP의 원론적인 의미를 알아야 할 필요가 있다.

Aspect 지향프로그래밍 

횡단 관심사를 모듈화할 때 특별한 클래스로 모듈화 하는데 그 특별한 크래스가 바로 애스팩트라고 부른다.


3. AOP 용어 


애스팩트를 이해하기 위해서는 우리가 이해해야할 용어들이 몇 개 존재한다.

AOP에서 가장 중요한 용어는 어드바이스(Advice), 포인트 컷(Point Cut), 조인 포인트( Join Point) 이 3가지이다.
꼼꼼히 읽어 보길 권고한다.

[참조: 스프링 인 액션]


ㄱ. 어드바이스 

애스팩트(Aspect)는 자신이 무엇을 해야할 지 알고 있어야 한다.
이때 애스팩트가 해야할 작업을 AOP용어로 어드바이스(Advice)라고 한다.

어드바이스는 애스팩트가 해야하는 작업에 대하여 언제 그 작업을 수행해야하는지 정의를 해준다.
어드바이스가 정의하는 언제는 메소드가 호출이전인지 이후인지, 아니면 이전/이후 모두인지 그것도 아니면 예외를 던졌을 때인지를 의미한다.

그 언제를 표현하기위해서는 아래와 같은 선언방식을 사용한다.


* 이전(Before) : 어드바이스 대상 메소드가 호출되기 전에 어드바이스 기능을 수행한다.
* 이후(After) : 결과에 상관없이 어드바이스 대상 메소드가 완료된 후에 어드바이스 기능을 수행한다.
* 반환 이 후 (after-returning) : 어드바이스 대상 메소드가 성공적으로 완료된 후에 어드바이스 기능을 수행한다.
* 예외 발생 이후(after-throwing) : 어드바이스 대상 메소드가 예외를 던진 후에 어드바이스 기능을 수행한다.
* 주위(around) : 어드바이스가 어드바이스 대상메소드를 감싸서 어드바이스 대상 메소드 호출 전과 후에 몇가지 기능을 제공한다??  


ㄴ. 조인 포인트

애플리케이션 하나에도 어드바이스를 적용할 있는 곳이 무수히 많으며 적용할 수 있는 곳을 조인 포인트라고 말한다.
즉 조인포인트는 애플리케이션 실행에 에스팩트를 끼워 넣을 수 있는 지점이며 이러한 조인 포인트 지점은 메소드 호출지점이나 예외발생 , 필드값 수정등이 있다.

ㄷ. 포인트 컷 

한 애스팩트가 전체 애플리케이션의 모든 조인포인트를 다 어드바이스 할 수 없다. 이 때문에 포인트 컷은 에스팩트가 어드바이스할 조인포인트의 영역을 좁혀주는 역할을 한다.

어드바이스가 애스팩트가 무엇을 언제할지 정의한다면 포인트 컷은 어디서를 정의하는 역할은 한다고 보면된다.

포인트 컷을 지정하는 방법은 클래스나 메소드 명을 직접 사용하는 것이지만 정규표현식으로 정의하는 방법도 있다.

ㄹ. 애스팩트

애스팩트는 어드바이스와 포인트 컷을 합친 것이다.
두가지 정보가 합쳐지면 무엇을 언제할지에 대한 모든 정보가 정의된다.

ㅁ. 인트로덕션

인트로덕션을 앞서 설명했던 AOP장점중 기존 클래스에 코드 변경없이 새 메소드나 멤버 변수를 추가하는 기능이다.
예를 들어 어떤 객체의 상태가 언제 마지막으로 변경되었다라는 정보는 추가하는 경우를 생각해보자
각 클래스마다 해당 정보를 저장하는 대신, auditable 어드바이스 클레스를 생성하여 setLastModified(Date) 메소드와 이 상태를 저장하는 멤버변수를 정의한다. 그 다음 인트로덕션을 적용하면 기존 클래스에 소스코드 변경없이 새로운 메소드와 멤버변수를 사용할 수 있다.


ㅂ. 위빙

어드바이스를 핵심코드 로직에 적용하는 것을 위빙(weaving)이라고 한다.

어드바이스를 위빙하는 방식은 3가지 방식이 존재한다.

* 컴파일 시에 위빙하기

컴파일 시 코드를 삽입하는 방법은 aspectJ에서 사용하는 방식이다.
컴파일 방식에서는 핵심 오직을 구현한 자바 코드를 컴파일 할 때 알맞은 위치에 공통코드를 삽입한다.
공통코드는 횡단관심사를 모듈화한 코드를 말한다.

이렇게 컴파일된 코드는 AOP가 적용된 클래스 파일이 생성된다.
컴파일 방식을 제공하는 AOP 도구는 공통코드를 알맞으 위치에 삽입할 수 있도록 도와주는 컴파일러나 IDE를 제공한다.

* 클래스 로딩시에 위빙하기 

AOP 라이브러리는 JVM이 클래스를 로딩할 때 클래스 정보를 변경할 수 있는 에이전트를 제공한다.
이 에이전트는 로딩한 클래스의 바이너리 정보를 변경하여 알맞은 위치에 공통 코드를 삽입한 새로운 클래스 바이너리 코드를 사용하도록 한다.

* 런타임 시에 위빙하기 <제일중요: 스프링은 자체적으로 프록시 기반의 AOP를 지원하고 있음>

런타임시 AOP를 적용할 때는 소스코드나 클래스 정보 자체를 변경하지 않는다. 대신 프록시를 이용하여 AOP를 적용한다. 프록시 기반의 AOP는 핵심로직을 구현한 객체에 직접 접근하는 것이 아니라 중간에 프록시를 생성하여 프록시를 통해 핵심로직을 구현한 객체에 접근하게 된다.
이때,  프록시는 핵심 로직을 실행하기 전 또는 후에 공통기능을 적용하는 방식으로 aop를 적용하기 된다.
프록시 기반에서는 메서드가 호출될 때에만 어드바이스를 적용할 수 있기 때문에 필드 값 변경과 같은 조인 포인트에 대해서는 적용할 수 없는 한계가 있다. 


4. Spring에서의 AOP 의 특징



이번엔 Spring에서 지원하는 AOP 특징에 대해서 정리해보자.

1. 스프링은 자체적으로 프록시 기반의 AOP를 지원하고 있다 

그래서 스프링 AOP는 메서드 호출 조인포인트만을 지원한다. 
만약 필드 값 변경 같은 조인포인트를 사용하고 싶다면 AspectJ같은 풍부한 기능을 지원하는 AOP도구를 사용해야 한다.

책에 따르면 스프링 AOP는 JEE 어플리케이션을 구현하는데 필요한 수준의 기느만을 제공한다고 한다.

2. 스프링 AOP는 자바기반이다. 

AspectJ는 에스팩트를 위한 별도의 문법을 제공하고 있는 반명 스프링은 별도의 문법을 익힐 필요 없이 자바언어를 이용하면된다.

스프링은 3가지 방식으로 AOP를 구현할 수 있게 하고 있다.

* XML 스키마 기반의 POJO 클래스를 이용한 AOP 구현
Spring 2 버전부터 aop를 설정하기 위한 aop 네임스페이스 및 네임스페이스와 관련된 xml이 추가되었다.
aop 네임스페이스와 관련된 xml 스키마는 다음과 같이 bean 태그에 명시할 수 있다.

예제)



전체 적용 예시




 <aop:config>AOP 설정정보임을 나타냄
 <aop:aspect>한개의 aspect를 설정한다.
aspect 태그의 ref속성에는 공통기능을 구현하고 있는 빈을 전달한다. 
 <aop:pointcut>pointcut을 설정한다
point태그의 id 속성은 pointcut을 구분하는데 사용되는 식별값을 입력받고
expression속성은 pointcut을 정의하는 aspectJ의 표현식을 입력받는다. 
 <aop:around>around advise를 설정한다.  


point cut에 포함하는 대상 객체의 메서드가 호출될 때 <aop:aspect> 태그의 ref속성으로 지정한 빈 객체에서 어떤 메서드를 실행할지 지정한다.
즉 위 예제를 보면 <asp:before 안에 ref 속성으로  servicePointCut으로 지정한 빈 객체의 beforeServicePointCut메소드를 실행할지 지정했다는 의미이다.

* AspectJ 5.6에서 정의한 @Aspect 어노테이션 기반의 AOP 구현
@Aspect 어노테이션은 AspectJ 5버전에 새롭게 추가된 어노테이션으로서 @Aspect 어노테이션을 사용하면 XML파일에 Advice 및 pointCut 등의 설정을 하지 않고도 자동으로 advice를 할 수 있게 되었다.

스프링 2버전부터 @aspect어노테이션을 지원하고 있다.


* 스프링 API를 이용한 AOP 구현 

어떠한 방식을 이용하더라도 내부적으로는 프록시 서버를 이용하여 AOP가 구현되므로 메서드 호출시에만 AOP를 적용할 수 있는 것에만 유의하면 될 것같다. 

원문 : http://najuung.tistory.com/65

댓글 없음: