본문 바로가기

Kotlin/Spring

(Spring) 관점 지향 코딩의 핵심!! AOP 의 설정 법을 알아보자

  implementation("org.springframework.boot:spring-boot-starter-aop")

AOP 란??

  • 부가 기능과 핵심 기능을 구분하여 부가 기능을 모듈화 하여 Application 전체에서 사용 할 수 있도록 하는 방법
  • Annotation 을 사용하여 모듈화 할 수 있고 이를 전체적으로 사용할 수 있다

사용하기 전에 build.gradle에 설정을 해주고 가자!!

 

AOP를 사용하기 위해서는 실행 위치나 메서드의 상태 변화 따라서 다음과 같은 Annotation 을 적용할 수 있다

@Aspect AOP를 사용하기 위해서 정의한 클래스 위에 지정해 준다
@Pointcut AOP기능을 메서드, Annotation 등 어디에 적용시킬지 지점을 설정 지점을 설정하기 위한 Annotation
@Before 특정 메서드 실행하기 이전에 
@After 메서드가 성공적으로 실행 후 AOP를 실행 시켜준다(예외 발생 되더라도 실행 됨)
@AfterReturning 메서드가 정상적으로 종료될때 AOP를 실행 시켜준다
@AfterThrowing 메서드에서 예외가 발생할때
@Around 메서드 전과 후로 모두 제어가 가능할 수 있게끔 사용이 가능하다(예외 발생 되더라도 실행 됨)
  • 위와 같은 방법들이 있다 본인이 필요한 상황에 적절하게 맞게끔 Annotation을 잘 골라주면 된다

여기서 Annotation 설정 하는 방법은 ?? <- 다음에 포스팅 예정이다

 

예시로 나는 인가를 해주는 코드를 모듈화 하는 것을 해보려고 한다

 

우선 인가라고 하면 메소드 실행 전에 들어가서 검사를 해줘야 하기 때문에 @Before Annotation을 사용하여 Aop를 설정해줄 예정이다

 

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class CheckAuthentication(
    val authenticationType: AuthenticationType,
)

위와 같이 인가의 종류를 받는 Annotation을 만들어주고

@Aspect
@Component
class AspectAdvice(
    private val validAuthentication: ValidAuthentication, 
    private val memberService: ExternalMemberService,// 사용할 서비스 객체 및 클래스 등을 생성자로 주입 받았다
) {
	// 다른 Annotation으로 상태에 따라서 움직일 수 있도록 변경이 가능하다
    @Before("@annotation(com.yoong.myissue.common.annotationGather.CheckAuthentication)")
    fun checkAuthentication(joinPoint: JoinPoint) {
        val methodSignature = joinPoint.signature as MethodSignature
        val method = methodSignature.method
        val annotation = method.getAnnotation(CheckAuthentication::class.java)

        val authenticationType = annotation.authenticationType

        val member = memberService.searchEmail(joinPoint.args[1].toString())

        validAuthentication.role(member.getRole(), authenticationType)
    }

이런식으로 작성을 해줬는데

 

여기서 JoinPoint란 ??

  • 관점(Aspect)적으로 봤을 때 PointCut이 적용될 수 있는 시점을 말하는데 PointCut이란 Aspect가 적용될 프로그램상 실제 위치를 말합니다 즉 코드로 보면 PointCut은 해당 Annotation이 부착된 자리를 의미한다고 할 수 있습니다
  • 따라서 JoinPoint는 Annotation이 부착이 된 시점에서 Annotation 내부에서 값을 가져오거나 함수 내부에서 매개변수를 받았을 경우에는 매개 변수까지도 가져 올 수 있는 역할을 한다

위에 코드에서 보면 JoinPoint를 통해서 Annotation 에 있는 값을 가져온 것을 확인 할 수 있다

joinPoint.args[0]

아니면 위와 같이 args 에서 메서드 내에 정의된 매개변수의 값을 꺼내 올 수 있다 단 매개변수의 값을 가져 올 경우 매개변수의 값에 맞춰서 타입 캐스팅을 해줘야 정상적으로 작동하는 것을 확인할 수 있다

 

추가적인 사항으로 @Around 를 제외하고 나머지는 JoinPoint 를 사용하지만 @Around는 proceedingJoinPoint 를 사용하는 것만 참고하면 될 것 같다