AOP

dongeranguk·2021년 9월 16일
0
post-thumbnail

AOP (관점 지향 프로그래밍)

📌 1. AOP란?

문제를 바라보는 관점을 기준으로 프로그래밍을 하는 기법

AOP 구현 방법으로는, 여러 가지가 존재하는데, 일반적으로 공통 관심 사항을 구현한 코드를 핵심 로직을 구현한 코드에 삽입하는 것이다.

비슷한 동작을 하는 인터페이스와 필터가 있는데 이들은 에서 사용한다.

AOP프로그래밍 기법 중 하나이며,
특정 패키지의 특정 클래스 전체, 특정 클래스의 특정 메서드 전체등 적용 범위를 다양하게 설정하여 공통 기능으로 사용할 수 있다.

공통 기능 == 공통 관심 사항
핵심 로직 == 핵심 관심 사항

핵심 비즈니스 기능과 구분하기 위해 공통 기능을 공통 관심 사항(cross-cutting concern)이라고 표현하며, 핵심 로직을 핵심 관심 사항(core concern)이라고 표현한다.

📌 2. AOP 주요 용어

  • Joinpoint : Advice를 적용 가능한 지점을 의미한다. 메서드 호출, 필드 값 변경 등이 Joinpoint에 해당한다.
  • Pointcut : Joinpoint의 부분 집합으로서 실제로 Advice가 적용되는 Joinpoint를 나타낸다.
  • Advice : 언제 공통 기능을 적용할 지를 정의한다.
  • Weaving : Advice를 핵심 로직 코드에 적용하는 것을 weaving이라고 한다.
  • Aspect : 여러 객체에 공통으로 적용하는 기능을 Aspect라고 한다.

📌 3. 프록시 기반의 AOP 적용 과정

공통 기능 호출 == callModule()
핵심 기능 호출 == business()


📌 4. 스프링에서의 AOP

스프링은 자체적으로 프록시 기반의 AOP를 지원하므로,
스프링 AOP는 메서드 호출 Joinpoint만을 지원한다.

스프링은 완전한 AOP 기능을 제공하는 것이 아니라,
엔터프라이즈 어플리케이션을 구현하는 데 필요한 기능만을 지원한다.

스프링은 세 가지 방식으로 AOP를 구현할 수 있도록 한다.

  • XML 스키마 기반의 POJO 클래스를 이용한 AOP 구현
  • AspectJ에서 정의한 @Aspect 어노테이션 기반의 AOP 구현
  • 스프링 API를 이용한 AOP 구현

AspectJ 를 사용하기 위해서는 pom.xml에 dependency 설정이 필요하다.


📌 5. 구현 가능한 Advice 종류

공통 기능을 핵심 로직 '언제'(실행 전/후, 예외 발생 전/후) 적용할 것인가를 정의하고 있다.

  • ✨Around Advice는, 메서드 실행 전/후, 예외 발생 전/후모두 원하는 기능을 삽입할 수 있어 가장 많이 사용되는 Advice 이다.

✍언제 공통 기능을 삽입할 것인가에 대해 구분할 수 있는 기준점이 필요한데, 파라미터로 받는 ProcedingJoinPoint 타입의 proceed() 메서드가 이러한 기준점 역할을 수행한다.
따라서, 반드시 첫번째 파라미터로 ProceedingJoinPoint 타입을 지정해야 한다.

Around Advice 를 제외한 Advice는 좀 더 자세하게 기능을 구현하기 위해서 사용하며, 이들의 구현 방법으로는 조금씩 다르다.

  • Before Advice를 구현한 클래스의 리턴타입은 일반적으로 "void" 이다.
    리턴 값을 갖더라도, 실제 Advice 적용 과정에서 사용되지 않기 때문이다.

  • After Advice를 구현한 메서드에서 대상 객체가 리턴한 값을 사용하고 싶다면, returning 속성을 사용하여 리턴 값을 전달 받을 파라미터의 이름을 명시한다.

  • After Throwing Advice 예외 객체를 사용하고 싶다면,
    throwing속성을 사용해 예외 객체를 전달받을 파라미터 이름을 명시한다.

✍리턴 값을 전달 받을 파라미터 이름을 명시하여 어떤 값이 리턴 되는지, 어떤 예외가 발생하는지에 따라 다른 Aspect를 적용하기 위해 파라미터 이름을 명시한다.

📌 6. XML 기반의 POJO 클래스를 이용한 AOP 구현

aop 네임스페이스의 XML 스키마를 지정했다면, 다음과 같이 <aop:config> 태그를 사용하여 AOP 관련 정보를 설정할 수 있다.

<bean id="profiler" class="com.spring.exercise.aop.Profiler"/>

<aop:config>
  <aop:aspect id="traceAspect" ref="profiler">
    <aop:pointcut id="publicMethod"
       expression="execution(public * com.spring.exercise..*(..))"/>
    <aop:around pointcut-ref="publicMethod" method="trace"/>
  </aop:aspect>
</aop:config>
 
<bean id="memberService" 
	class="com.spring.exercise.member.MemberServiceImpl" />

<aop:aspect> 태그의 ref 속성은 Aspect의 공통 기능을 제공할 빈을 설정할 때 사용된다. 위 코드는 Aspect 기능을 제공할 빈으로 "profiler" 빈을 지정하였다.

  • 이름이 "traceAspect"인 Aspect는 MemberServiceImpl 클래스의 public 메서드에 대해 Around Advice로 적용된다.
  • "traceAspect"의 구현으로 사용되는 profiler 빈의 "trace"메서드를 통해 공통 기능을 제공한다.

  • <aop:config> : AOP 설정 정보임을 나타낸다.
  • <aop:aspect> : Aspect를 설정한다.
  • <aop:pointcut> : Pointcut을 설정한다.
  • <aop:around> : Around Advice를 설정한다. 이 외에도 다양한 Advice를 설정할 수 있다.

📌 7. @Aspect 어노테이션 기반 AOP

  • @Aspect 어노테이션을 이용해서 Aspect 클래스를 구현한다. 이 때 Aspect 클래스는 Advice를 구현한 메서드와 Pointcut을 포함한다.
  • XML 설정에서 <aop:aspectj-autoproxy/>를 설정한다.

<aop:aspectj-autoproxy/> 태그를 등록해주지 않으면, @Aspect 관련 어노테이션은 사용할 수 없다.

7.1 @Pointcut

메서드에 @Pointcut 을 적용할 수도 있는데, 이렇게 적용된 메서드를 @Around 속성에서 호출하여 간단하게 설정할 수 있고, 여러 Advice에서 사용할 수도 있다.

@Pointcut 어노테이션이 적용된 메서드를 참조하려면, 아래와 같이 입력하면 된다.

  • 같은 클래스에 위치한 @Pointcut 메서드는 '메서드 이름'만 입력
  • 같은 패키지에 위치한 @Pointcut 메서드는 '클래스단순이름.메서드이름'을 입력
  • 다른 패키지에 위치한 @Pointcut 메서드는 '완전한클래스이름.메서드이름'을 입력

7.2 @Joinpoint

Joinpoint 는 Pointcut을 포괄하는 개념
따라서, Pointcut은 세세하게 지정하기 위해서 사용하는것이다.

Around Advice는 핵심 기능 전/후가 지정되지 않았기 때문에, JoinPoint를 기준으로 전/후를 구분하므로, JoinPoint 타입을 반드시 첫번째 매개 변수로 받아 사용해야 한다.
Around Advice 를 제외한 나머지 Advice 타입을 구현한 메서드는 JoinPoint 객체를 선택적으로 사용할 수 있다.

ProceedingJoinPoint의 proceed() 메서드를 호출하면 프록시 대상 객체의 실제 메서드를 호출하게 된다. 실제 메서드를 호출하기 때문에, 실제 메서드 전/후를 구분할 수 있게 되는것이다.

✍스프링 AOP는 인터페이스를 이용해서 프록시 객체를 생성되어, 인터페이스 구현 클래스를 instanceof 연산자로 검사하면 false를 리턴한다. 인터페이스 기준이 아닌 클래스 기준으로 프록시가 생성되게 하려면,
<aop:config proxy-class="true"> 태그를 등록한다. 등록한 뒤 구현 클래스를 instanceof 연산자로 검사하면 올바르게 true를 리턴한다.


📌 8. execution 명시자

execution(수식어? 리턴타입 클래스이름?메서드이름(파라미터)

스프링 AOP는 public 메서드에만 적용 가능하므로 '수식어' 부분은 생략이 가능하다.

각 패턴은 '*'을 이용하여 모든 값을 표현할 수 있고, '..'을 이용하여 0개 이상이라는 의미를 표현할 수 있다.

📌 9. Advice 적용 순서

Advice 적용 순서를 명시적으로 지정하려면, @Order 어노테이션을 적용하거나, Ordered 인터페이스를 구현한다.

@Aspect
public class Exercise implements Ordered {
	@Override
    public int getOrder() {
    	return 2;
}

@Order 어노테이션을 사용할 경우 값으로 적용 순서를 지정한다.

@Order(3)

실행 전(Before)는 순차대로 적용되지만, 실행 후(After)는 역순으로 적용된다.


(출처: 웹 개발자를 위한 Spring 4.0 프로그래밍, 저자 : 최범균)

0개의 댓글