[Spring] 도대체 AOP가 뭐고 왜 쓰느냐!

Sun choi·2024년 9월 11일

NEW 지식

목록 보기
22/34

AOP에 대한 (내가 모르는) 모든 것! 나 본인이 알아먹기 쉽도록 정리하겠다.

AOP 란?

관점 지향 프로그래밍! 횡단 관심사 분리!
AOP는 핵심기능과 횡단 관심사(부가기능)을 분리해서 관리하는 것!!

핵심기능이란? 시스템의 주요 목적
부가기능이란? 주요 목적이 아닌 기능
횡단 관심사이란? 여러곳에서 반복적으로 적용되는 부가 기능

객체 지향 프로그래밍(OOP)의 부족한 부분을 보완한다.
OOP의 모듈화의 핵심 단위는 클래스이고, AOP의 모듈화의 핵심 단위는 관점이다.
부가 기능처럼 특정 로직을 애플리케이션 전반에 적용하는 문제는 일반적인 OOP 방식으로는 해결이 어렵기 때문에 핵심 기능과 부가 기능을 분리하는 AOP 방식이 필요하다.

AOP의 활용방법

Service 클래스에서 중복되는 코드들을 한 메서드에 묶어서 가져다 사용하는 것처럼!!
전역적으로 중복되는 코드가 있다면(로그를 찍는 것이나 인증 인가, 사용시간 기록, 메서드 처음이나 끝에 붙여야 하는 보조 기능들) 그걸 AOP로 가져다 사용하면 기존 클래스를 엄청 깔끔하게 정리할 수 있다.
전체 Controller, Service 등 Spring Container에 의해 관리되는 Bean 객체가 등록되어 있는 모든 것에서 모두 사용가능하다! (주로 메소드 실행 전후의 작업을 제어할 때 사용하고, 필드나 생성자 수준의 AOP는 지원하지 않는다.)

만약 그 기능이 필요없어지면 해당 AOP만 삭제하면 되니까 유지보수가 간편하다. (수정도 동일한데 만약 AOP를 사용안한다면 모든 메서드들에서 수정 필요함)

AOP에서 나오는 용어

어드바이스(Advice), 포인트컷(PointCut), 타겟(Target), 조인포인트(JoinPoint), 애스팩트(Aspect) 이렇게 5가지가 있다!
간단히 말하자면 포인트컷은 지정하는 행위고, 타겟은 그 행위로 선택된 객체이다.
그것에 포함되는 메서드들이 조인포인트들!!!

어드바이스(Advice)

실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체

포인트컷(PointCut)

 @Pointcut("execution(* com.standard.sparta.service..*(..))")
private  void serviceLayer() {}

이렇게 지정해줌!(서비스 패키지 기반)
횡단관심사를 적용할 범위 지정
별 이 반환타입 -> 경로지정 -> 이름(모든 메서드)에 범위를 설정할거야 -> (별,별) 매개변수타입들 아무거나 상관없어

모든 메서드에 적용하려면 포인트컷 방법이 좋고 특정 메서드만 적용하려면 애노테이션 방법을 사용함.
범위설정할때는 포인트컷 방법
선택적으로 하려면 어노테이션 방법
(세션 들으면서 메모한건데 정확성 확인 필요)

타겟(Target)

Aspect를 적용하는 곳 (클래스, 메서드 .. )

조인포인트(JoinPoint)

Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능

애스팩트(Aspect)

어드바이스와 포인트컷을 하나로 묶은 모듈
AOP 만들려면 클래스 상단에 @Aspect 걸어줘야 함.

Aspect 실행 시점을 지정할 수 있는 어노테이션

  • @Before (이전) : 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
  • @After (이후) : 타겟 메소드의 결과에 관계없이(즉 성공, 예외 관계없이) 타겟 메소드가 완료 되면 어드바이스 기능을 수행
  • @AfterReturning (정상적 반환 이후) : 타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행
  • @AfterThrowing (예외 발생 이후) : 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
  • @Around (메소드 실행 전후) : 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출 전과 후에 어드바이스 기능을 수행
 @Around("serviceLayer()")
    public Object advicePackageMethoid (ProceedingJoinPoint joinPoint) throws Throwable {
    	// 호출 전
        long startTime = System.currentTimeMillis();
       try {
       		// 해당하는 메서드 실행
           Object result = joinPoint.proceed();
           return result;
       } finally {
            // 호출 후
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            log.info("::: ExecutionTime: {}ms", executionTime);
        }
    }

@Around에서만 ProceedingJoinPoint 사용
@before에서는 JoinPoint 사용


AOP의 한계

1 AOP는 기본적으로 프록시 기반으로 동작하여 실제 객체가 아닌 해당 객체의 프록시가 대신 메소드를 호출한다. 프록시 객체를 사용하지 않으면 AOP가 적용되지 않는다.

2 self invocation 문제 - 같은 클래스 내에서 메소드를 호출하는 경우 프록시를 거치지 않기 때문에 AOP가 적용되지 않는다.(AOP가 적용된 메소드가 동일 클래스 내의 다른 메소드를 호출하는 경우)

profile
풀스택 개발자의 공부기록 📖

0개의 댓글