[스프링 입문] AOP

atdawn·2024년 5월 15일

SPRING BOOT+JPA

목록 보기
13/49

📹 참고 : 인프런 [ 스프링 입문 - 김영한 ]


AOP : Aspect Oriented Programming (관점 지향 프로그래밍)
핵심코드의 변화없이 부가 코드(공통기능)를 원하는 곳에 뺏다 붙였다 할 수 있는 기능.
즉, 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리한다.

AOP가 필요한 상황

  • 모든 메소드의 호출 시간을 측정하고 싶다면?
  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
  • 회원 가입 시간, 회원 조회 시간을 측정하고 싶다면?

만약 각 메소드마다 시간측정 로직을 수동으로 넣게된다면, 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어려워진다. 또한 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.

=> AOP 사용

시간 측정 AOP 등록
java/hello/hellospring/aop/TimeTraceAop.java

@Aspect // 이 클래스가 AOP 기능을 제공하는 Aspect임을 나타내는 애노테이션
@Component //일반적인 빈 선언 . Config파일에 빈을 등록했으니 생략 가능
public class TimeTraceAop {
    // Around 어드바이스: 대상 메서드 실행 전후에 실행되는 어드바이스
    //@Around("execution(* hello.hellospring..*(..))")
     @Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.SpringConfig)")// SpringConfig 클래스를 제외한 모든 메서드에 적용되는 어드바이스
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();// 현재 시간을 기록하여 시작 시간을 저장
        System.out.println("START: " + joinPoint.toString());// 메서드 호출이 시작되었음을 로그로 출력
        try {
            return joinPoint.proceed();// 대상 메서드를 실행하고, 그 결과를 반환
        } finally {
            long finish = System.currentTimeMillis();// 현재 시간을 기록하여 종료 시간을 저장
            long timeMs = finish - start;// 실행 시간을 계산
            System.out.println("END: "+joinPoint.toShortString()+" " +timeMs + "ms");
        }
    }
}

오류
강의 자료의 코드인
@Around("execution(* hello.hellospring..*(..))") 를 사용하고
강의 에서는 AOP를 설정파일에 스프링 빈으로 등록하였지만, 순환참조 오류가 발생하였다.
The dependencies of some of the beans in the application context form a cycle:

  • Spring Boot 2.6.x 버전부터, 순환 참조를 default로 금지함으로서 발생되는 에러메시지

원인 : TimeTraceAop에서 @Around 어노테이션을 보면 hello.hellospring 패키지 내 모든 메서드가 AOP 대상이 되는데, SpringConfig 에서 TimeTraceAop를 빈으로 등록하여 또 다시 TimeTraceAop 메서드도 AOP 대상이 되어 순환 참조 문제가 발생하였다.

해결 방법 2가지
1. Configuration 에서 TimeTraceAop @Bean 제거
2. @Around에서 AOP 적용대상에서 SpringConfig 제외

@Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.SpringConfig)")

참조 : https://dream-and-develop.tistory.com/393

오류 해결 했으니 이제 서버를 띄워 확인해 보자.

회원 목록에 들어가자 각각의 메소드 호출 시간이 측정 되는 것을 확인했다.

AOP 주요 용어

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

Advice의 종류
@Around : 비즈니스 메서드 실행 전후에 실행
@Before : 비즈니스 메서드 실행 전 동작
@After : 비즈니스 메서드 실행 후 동작

ProceedingJoinPoint 클래스
ProceedingJoinPoint: 이 클래스는 실행 중인 메서드에 대한 정보를 제공함. 대상 메서드의 이름, 매개변수, 반환값 등의 정보를 얻을 수 있음. 또한, 대상 메서드를 호출하고 그 결과를 반환 함.

  • AOP 적용 전 의존 관계 : 컨트롤러에서 서비스를 직접 호출
  • AOP 적용 후 의존 관계 : AOP를 적용하면, 지정된 서비스의 가짜 서비스(프록시)가 생성됨. -> 스프링이 실행될 때 프록시로 발생한 가짜 서비스의 스프링빈을 앞세워 둔 후 , joinPoint.proceed()가 실행되면 -> 진짜 서비스를 호출한다.

프록시
스프링에서 프록시는 AOP의 관점의 부가기능들,
즉 Aspect들을 개발자 대신, 대리하여 핵심로직에 추가해주는 역할

기존 코드를 수정하지 않고 코드 중복도 피할 수 있는 방법이 프록시 객체다.

profile
복습 복습 복습

0개의 댓글