Spring & Kotlin AOP

박미소·2024년 1월 16일
0

코틀린

목록 보기
27/44

위에서 보면 OOP 옆에서 보면 AOP


트랜잭셔널을 이용해서 서비스를 오가며 사용





어플리케이션의 진행 단계


  • Aspect
    • 횡단 관심사(부가기능)를 모듈화한 단위이다. Aspect는 부가기능을 정의하는 Advice와 적용 위치를 결정하는 PointCut으로 구성된다.
  • PointCut
    • Aspect가 적용될 프로그램상 실제 위치이다.
  • JoinPoint
    • PointCut의 후보군이다. Aspect가 적용될 수 있는 위치들을 말한다. method가 호출되는 시점, 특정 class의 생성자가 호출되는 시점, exception이 발생하는 시점 등이 될 수 있다.
  • Advice
    • 실질적으로 부가 기능 로직이 정의되어있는 객체라고 볼 수 있다.
  • Weaving
    • Aspect를 실제 코드에 적용하는 과정을 나타낸다.

point cut 과 adivice를 합쳐서 하나의 Aspect라고 한다.



Weaving : 실제 코드에 적용하는 과정

<대표적인 두 가지 방식>


☑️  Spring AOP vs AspectJ

두 프레임워크의 큰 차이는 weaving 방법에 있다.


1. AspectJ

  • Compile-time Weaving :

AOP가 적용된걸 확인하고 컴파일 시점에 우리가 작성한 클래스가 변경된다.

  • Load-time Weaving :

Java기반 프로그램은 실행되기 전 JVM에서 클래스를 로딩하는 시점이 있다. 자바 컴파일러(java Complier)가 자바 소스파일을 컴파일하고자바 바이트코드로 JVM (자바 가상머신)이 이해가능한 파일로 만든다. 이때, 변경된 바이트 코드를 사용하게 함으로써, 원본 클래스는 변경하지 않고, AOP를 적용하는 방식.

-> 실행 시에 모든 클래스가 로딩되지 않고 필요한 시점에 클래스를 로딩하여 사용할 수 있다



2. Spring AOP 가 사용하는 Run-time Weaving

객체에 직접 접근하는게 아닌 중간에 프록시를 두고 프록시를 통해 객체에 접근해 AOP가 적용된다.

슈퍼클래스 ClassB의 서브클래스 ClassB Proxy

AspectJ는 Compile-time Weaving, Load-time Weaving으로 AOP를 구현하고,

Spring AOP는 Run-time Weaving 을 사용해 AOP를 구현한다.

스프링 AOP가 프록시를 거쳐야하기에 오버헤드가 있고 AspectJ보다 느리다.

AspectJ는 모든 부분에 JoinPoint 적용이 가능하다. 하지만 스프링AOP 는 프록시 패턴을 이용하기 때문에 항상 프록시에 해당하는 sub class를 만들어야 한다. 이때 Aspect(PointCut + Advice)를 적용하려는 class가 final class(상속을 못받는 클래스) 일때는 적용이 되지 않는다. Java의 final or static method에도 적용이 되지 않는다.






규칙 2개 존재


a. Spring AOP는 일반 method만을 JointPoint로 사용할 수 있다.

b. 또 스프링 프레임워크이니까 스프링에서 관리하는 Bean에서만 작동한다.


속도가 빨라 성능면에서는 AspectJ가 좋지만, weacing 방법 두가지 중 하나를 골라야 하고, 별도의 컴파일러나 weaver가 필요하기 때문에 Spring AOP에 비해 매우 복잡하다. Spring AOP는 간단하게 사용이 가능하다.






<적용해보기>


어플리케이션 상단에 적기
@EnableAspectJAutoProxy

Spring AOP인데 AspectJ 이름이 붙은 이유는 AspectJ를 차용해서 만들었기 때문이다.

이 클래스 자체가 AOP가 되는 것이다. 포인트 컷과 어드바이스가 적혀있는 하나의 객체.

여기에 이제 부가기능을 모듈화 한다.

Aspect니까 어노테이션 붙이고, 구성요소 빈 등록 어노테이션 붙인다.

  • @Around 는 Advice의 적용 시점 중 하나이다. JoinPoint를 기준으로, Advice가 언제 동작할지를 정의한다. 아래 5가지가 있다.
    • @Around : 메서드 실행 전후로 동작.
    • @Before : 메서드가 호출되기 전에 Advice가 실행.
    • @After : 메서드 결과와 관계없이, 메서드가 완료되면 Advice가 실행.
    • @AfterReturning : 메서드가 정상적으로 반환 했을시에만 Advice가 실행.
    • @AfterThrowing : 메서드가 예외를 발생시킬때 Advice가 실행.

AOP가 잘 적용됨


먼저 어노테이션 클래스를 만들고,

@Target(AnnotationTarget.FUNCTION)  // Target 은 어노테이션이 적용될 대상을 의미 CLASS : 어떤 클래스에 적용, PROPERTY : 어떤 프로퍼티에 적용, ANNOTATION_CLASS : 다른 어노테이션 클래스에 적용
// 지금은 메서드의 수행시간을 알아보는 것이기에 FUNCTION 지정
@Retention(AnnotationRetention.RUNTIME)
annotation class StopWatch()


AOP를 작성하고,


시간을 측정할 api에 @StopWatch 어노테이션을 달고 swagger를 실행해 아이디를 조회하면,

스탑워치는 특정 api가 너무 오래걸려서 어디가 오버헤드가 있는지 측정할 수 있다.
그래서 모든 api에 스탑워치를 달면 어디가 느리게 실행되는지 알 수 있다.

0개의 댓글