좌충우돌 개발공부

TIL(20240613) [Spring AOP]


📌 Spring

✨ 들어가기전

  • 어플리케이션의 로직은 크게 핵심기능/부가기능으로 나누어짐 1) 핵심기능(종단관심사): 해당 객체가 제공하는 고유의 기능 2) 부가기능(횡단관심사): 핵심기능을 보조하는 기능

💡 AOP 란?

  • AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍으로 관점지향이란 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화 하겠다라는 의미이다.

    ✔모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것
    
  • AOP에서 각 관점을 기준으로 로직을 모듈화 한다는 것은 코드들을 부분적으로 나누어서 묶겠다 라는 것인데, 이때 코드상에서 다른 부분에서 계속 반복해서 쓰이는 코드들을 “흩어진 관심사”라고 부른다고 한다. 이러한 흩어진 관심사를 Aspect로 모듈화(묶어서)하여 핵심적인 비지니스 로직과는 분리하여 공통된 로직은 재사용하겠다는 AOP의 취지이다.

  • 즉, AOP는 부가 기능을 핵심 기능에서 분리해 한 곳으로 관리하도록 하고, 이 부가 기능을 어디에 적용할지 선택하는 기능을 합한 하나의 모듈이다.


AOP 주요 개념

Aspect : joingPoint+Advice 결합한 객체를 의미함, 위에서 설명한 흩어진 관심사를 모듈화  . 주로 부가기능을 모듈화함.
Target : Aspect를 적용하는  (클래스, 메서드 .. )
Advice : 실제 구현체, 실질적으로 어떤 일을 해야할 지에 대한 , 실질적인 부가기능을 담은 구현체
JointPoint : 수행될 시점, Advice가 적용될 위치, 끼어들  있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올   다양한 시점에 적용가능
PointCut : 수행할 대상, JointPoint의 상세한 스펙을 정의한 . 'A란 메서드의 진입 시점에 호출할 ' 같이 더욱 구체적으로 Advice가 실행될 지점을 정할  있음

Spring 스프링 AOP (Spring AOP) 총정리

💡 그래서 AOP의 사용목적은?

  • 코드를 작성하다보면 반복적이면서 길이만 차지하는 코드들이 많이 있다. 이런 것들을 보일러 플레이트 코드라고 하는데, (JDBC에서 흔히 발견된다.) 이러한 부분들을 부가기능 AOP로 처리하여 핵심로직에서 분리시키는 것을 말한다.
// 애너테이션 종류

@Aspect	 Class가 횡단 관심사 로직을 모듈화한 객체(Aspect)라는 것을 알려주는 Annotation
@Pointcut	횡단 관심사가 적용될 JoinPoint들을 표현식으로 정의한 
@Before	Method  호출되기 전에 실행되는 Advice 기능 수행
@Around	Method 실행 중에 호출 전후에 어드바이스 기능을 수행
@After	Method의 결과에 관계 없이(성공, 예외 관련없이. 마치 finally 같은 개념) 타겟 메소드가 완료되면 어드바이스 기능을 수행
@AfterReturning	Method가 성공적으로 결과 값을 반환한  Advice 기능 수행
@AfterThrowing	Method가 수행  예외를 던지게 되면 Advice 기능 수행

[Spring] 스프링 AOP

💡 그래서 Spring AOP의 왜 사용하는 것인가?

1) 코드의 가독성을 높인다. 2) 중복코드를 줄인다. 3) 유지보수가 좋다. -> 만약 AOP를 사용하지 않을 경우 부가기능에 수정이 필요하면 모든 클래스에서 다 수정해줘야한다…

💡 AOP 추가하기

  • 모든 API(Controller)가 호출될 때, Request 정보(Request URL, HTTP Method)를 @Slf4J Logback 라이브러리를 활용하여 Log로 출력해주세요.
  • 컨트롤러 마다 로그를 출력하는 코드를 추가하는것이 아닌, AOP로 구현해야만 합니다.

@Slf4j
@Aspect
@Component
public class ControllerAop {

  @Before("execution(* com.sparta.reviewspotproject.controller.*Controller.*(..))")
  
  public void logBefore(JoinPoint joinPoint) {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();

    log.info("Request URL : {}", request.getRequestURL());
    log.info("HTTP Method : {}", request.getMethod());

  }
}