Spring_AOP

SG Jang·2021년 3월 2일
0

길잡이를 자바보자

목록 보기
12/12
post-thumbnail

이번 시간에는 "Spring_AOP"에 대해 다뤄보겠습니다.


1. AOP란?

Aspect Oriented Programming의 약자로 관점지향 프로그래밍이라 한다. 그러면 도대체 관점지향 프로그래밍 AOP는 뭘까? 우리가 익히 알고 있는 OOP는 객체지향프로그래밍으로 핵심기능을 여러개로 나누어 둔 것이고, AOP란 각 핵심기능에 들어가는 공통된 기능을 묶어 모듈화 해둔 것이다.


2. AOP를 어떻게 사용해야 할까?

AOP를 사용하는 방법에는 두 가지 방법이 있다. 첫 번째는 Java proxy(InvocationHandler)방식, 두 번째는 CGLIB(MethodInterceptor)방식이 있다. 세 번째는 AspectJ방식이 있다.

프록시방식

  • 런타임시에 타겟 메소드가 호출될 때 Advice를 적용
  • JDK Proxy는 인터페이스에 대한 Proxy만을 지원
  • 리플렉션을 사용하여 구현한 기술이기에 상대적으로 퍼포먼스가 떨어짐.
  • 매번 프록시 클래스를 작성해야하고 여러 클래스 여러 메소드에 적용하게 되어 코드의 중복이 발생할 수 있다는 단점을 갖고 있다.

CGLIB

  • Code Generator Library(코드생성 라이브러리)의 약자이다.
  • java proxy와 동일하게 런타임 시에 Advice 적용
  • 클래스에 대한 Proxy가 가능
  • 메소드가 처음 호출 되었을때 동적으로 bytecode를 생성하여 이후 호출에서는 재사용

AspectJ

  • Runtime이 아닌 Compile 시점에 Aspect를 적용

우리는 이번시간에 클래스에 Advice한 CGLIB방식에 대해서 실습해본다.


- pom.xml에 의존성 추가하기


- aop를 사용할 패키지와 클래스 만들기

aop클래스에서 @Component를 사용할 예정이므로 당연히 컴포넌트 스캔을 해주고 <aop:aspectj-autoproxy/>를 적어줌으로써 @Aspect가 적용된 빈을 Aspect로 사용할 수 있게 해준다.


- aop클래스를 살펴보자

아래 사진을 보면 @Component를 통해 빈으로 등록해주고 @Aspect를 사용함으로써 AOP를 구현할 예정임을 알린다. 그리고 바로아래 TestAop를 보면 AOP 공통 기능을 구현하기 위한 객체를 만들고 있음을 알 수 있다.

우리는 aop가 무엇인지 대강.... 아주 대강 배워보았다. 그렇다면 그 공통된 모듈을 어떻게 적용할건지 의문이 들것이다. "어떤 공통모듈을 언제..", "어디에" 적용할까?에 대해 알아야 한다. "어떤 공통모듈을 언제..."에 대한 내용은 Advice에 있고, "어디에"에 대한 내용은 JoinPoint와 Pointcut에 있다.
조금더 조금 더 디테일하게 알아보자. 단어가 너무너무 생소하다...ㅠㅠ
Advice는 위에서 어떤 부가기능을 언제 사용할지에 대한 정의라고 하던데 언제인지에 따라서 5종류로 나뉘게 된다.

@Before : 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
@After : 타겟 메소드의 결과에 관계없이(성공, 예외 상관없이) 타겟 메소드가 완료되면 어드바이스 기능 수행
@AfterReturning (정상적 반환 이후) : 타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행
@AfterThrowing (예외 발생 이후) : 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
@Around (메소드 실행 전 후) : 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출 전, 후 어드바이스 기능을 수행 -> 스프링 배치의 beforeJob, afterJob과 비슷한 것 같다.

위 5가지 중 Around의 사용빈도가 앞도적으로 많다.

그렇다면 "어디에"에 대한 정보는 JoinPoint와 Pointcut에 있다고 하던데 어디에 이 둘의 차이는 뭘까?
JoinPoint는 위에서 설명한 advice가 적용될 수 있는 위치를 의미한다. advice가 적용될 수 있는 위치란 여러 곳이 있는데 프록시 기반의 aop이기 때문에 "메소드를 호출할 때" 이 advice를 적용할 수 있다. 그렇다면 좋다. 우리는 JoinPoint를 통해 어드바이스가 메소드를 호출할 때 적용가능하다는 사실을 알게되었다.
...
...
...
그렇다면 이 어드바이스를 JoinPoint가 말해주는 모든 메소드에 적용할것인가?
...
...
...
당연히 아니다. 우리는 원하는 곳에서만 쏙쏙 집어넣어 사용하고 싶은게 아닌가? 모든 메소드에 적용하자면 사용의도가 틀어진다.
이때! 모든 메소드에 어드바이스를 적용할 수 있어! 라고 알려주는 JoinPoint에서 내가 필요한 위치에만 "선별적"으로 적용할 수 있도록 JoinPoint를 선별해주는 것이 바로바로 Pointcut이다 이말이다.

아래는 pointcut을 명시해준 부분이다.

그러면 우리는 결과적으로 Around를 사용했으니 이 aop를 구현한 것은 "타겟 메소드 호출 전, 후 Around어드바이스 기능을 수행"하고 "그 타겟메소드는 위에서 pointcut으로 명시해준 TestController가 된다" 이말이다. 아래는 실행 결과이다.


결과화면


참고자료

0개의 댓글