본문 바로가기
개발 관련 강의 정리/10분 테코톡

[10분 테코톡] 🌕제이의 Spring AOP 정리

by 코딩개발 2023. 5. 4.
728x90
반응형

서비스에 필요한 내용 : 비즈니스로직이라고 불리는 핵심 기능만 수행할 수 있으면 된다.

인프라 로직(시간 측정, 권한 측정 등) - 부가 기능
- 애플리케이션의 전 영역에서 나타나는 경우가 많아 중복코드를 만들어 낼 가능성 있다.

- 비즈니스로직과 섞여있으면 비즈니스 로직을 이해하기가 어렵게 만든다.
- 로깅, 트랜잭션, 권한검사, 성능 측정 등 하나의 관심사를 가지게 된다.

비즈니스 로직을 수행하는데 있어서 부가기능이 되는 인프라 로직의 중복이 횡단으로 나타나기 때문에

이것을 cross-cutting concern, 횡단 관심사라고 부른다.

 


AOP (Aspect-Oriented Programming) 관점지향 프로그래밍

횡단관심에 따라 프로그래밍 한다고 생각하면 된다.


AOP라는 말에서 OOP와 대치 될 것 같은 느낌을 받을 수 있지만 그렇지 않다.
오히려 더 객체지향적으로 코드를 구성할 수 있도록 보완해준다.

 

Spring documentation에 AOP에 대해서 아래와 같이 "AOP가 OOP를 보완하고 있다"라고 이야기를 한다.

"Aspect-Oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure."

                                                                                                                                - spring documentation -

 

AOP 용어
- Target
    어떤 대상에 부가 기능을 부여할 것인가
- Advice
    어떤 부가 기능?
        Before
        AfterReturning
        AfterThrowing
        After
        Around
메소드가 호출되기 전
메서드가 실행돼서 제대로 된 결과값을 Returning 했을 때
실행 시점에서 무언가 익셉션이 터졌을 때
메소드가 끝났을 때
메서드의 실행 전 후로 무언가를 할 수 있음
- Join point (Spring AOP에서는 메소드가 실행될때만으로 한정)
    어디에 적용할 것인가? 메서드, 필드, 객체, 생성자 등
- Point cut
    실제 advice가 적용될 지점, Spring AOP에서는 advice가 적용될 메서드를 선정
    Spring AOP에서는 Join point가 메서드가 실행될 때이기 때문에 어드바이스가 적용될 메서드를
    선정하는 기능을 한다.

 

AOP의 구현 방법 (Spring AOP가 아니라 전체적인 방향)
- 컴파일
    J.java -> J.class
    컴파일하는 시점에 해당하는 aspect들을 끼워 넣어 주아 AOP 적용시키는 방식
- 클래스 로드시
    J.class
    클래스 로더가 메모리상에 올릴 때 AOP를 적용시키는 방식
- 프록시 패턴
    J라는 어떤 타겟 클래스를 프록시로 감싸서 부가 기능을 제공하는 프록시로 감싸서 실행을
    하는 방식
Spring에서 IoC와 DI를 기반으로 하기 때문에 가능한 방식

 

 

AuthController가 AuthService를 DI 받게 되고 AuthService 클래스의 이름을 출력하는 코드이다.

처음 출력된 것은 AOP가 적용되지 않아 AuthService가 그대로 출력된다.

그 다음에는 AOP를 적용하고 출력하니 AuthService라는 타입 뒤에 EnhancerBySpringCGLIB.... 라고 붙게 된다.

 

디버거를 사용해서 보면 EnhancerBySpringCGLIB 안에 타겟 안에 AuthService가 들어있다.

즉, 프록시로 한 번 감싸주게 된다.

 

- 참고 :  [10분 테코톡] 🔥미르의 JDK Dynamic Proxy vs CGLIB Proxy 정리

 

runtime시에는 위와 같은 구조가 된다.
원래는 AuthController가 AuthService만 의존하고 있었다면 runtime시에는 AuthService 블라블라를 생성해서 프록시를 만들어서 갈아 끼워주게 되는 방식이다.

 


AuthService$$블라블라가 결국에 AuthService의 타입을 갖게 될텐데 AuthService 안에 있는 private 메서드에 AOP를 적용하면 어떻게 될까?

 

AuthService 안에 있는  join은 AOP를 적용하지 않고 private 메서드로 inner라는 메서드를 만들어서 PerformanceCheck 라는 AOP를 적용하였고 join에서 inner를 호출하였다.


이때 당연히 PerformanceCheck이 불리지 않는다.

proxy로 감싼 객체가 실제로 타겟 오브젝트의 join이라는 메서드를 실행을 할 때는 inner라는 메서드가 AOP로 감싼 프록시객체가 아니기 때문에 자기 자신을 호출 할 때는 AOP로 감싸지지 않은 메서드가 호출이 된다.

 

참고로 Service에서 private 메서드에 @Transactional 어노테이션을 붙였을 때 그 Transaction이 작동하지  않는 이유가 이것이다. (@Transactional도 AOP 중 하나이다.)

 

 

Spring AOP vs AspectJ

  Spring AOP AspectJ
목표 간단한 AOP 기능 제공 완벽한 AOP 기능 제공
join point 메서드 레벨만 지원 생성자, 필드, 메서드 등
다양하게 지원
weaving 런타임 시에만 가능 런타임은 제공하지 않음
compile-time, post-compile,
load-time 제공
대상 Spring Container가 관리하는
Bean에만 가능
모든 Java Object에 가능

 


참고

https://www.youtube.com/watch?v=Hm0w_9ngDpM&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC 

728x90
반응형

댓글