Spring Framework - AOP

겔로그·2022년 6월 26일
0

Spring Boot

목록 보기
7/21
post-thumbnail

목차

  • AOP 사용 이유
  • AOP란?
  • AOP 주요 개념
    • 용어정의
    • 상세설명
  • Spring AOP
    • Proxy 패턴 정의 및 문제점
    • Spring AOP란?
    • 예시
    • 예시상세
  • Aspect J
  • Spring AOP vs AspectJ
  • 별첨 Filter,Interceptor, AOP의 차이

AOP 사용 이유

기존 OOP(객체지향 프로그래밍)의 한계

  1. 여러 객체에 공통적으로 사용하는 기능 존재
  2. 중복 코드 발생 및 유지 보수의 어려움

=> 기존 객체지향 프로그래밍의 한계를 보완하기 위해 AOP 활용

AOP(관점 지향 프로그래밍)란?

애플리케이션의 핵심적인 비즈니스 로직으로부터 부가적인 기능 을 분리해서 애스펙트(Aspect)로 정의하고 설계하여 개발하는 방식.

  1. 공통적으로 사용하는 로직을 분리 및 추출(부가 기능 중심)
  2. 로직 모듈화
  3. 필요시 사용

AOP 주요 개념 - 용어

  • Aspect : 흩어진 관심사(공통된 로직)를 모듈화 한 것
  • Target : Aspect를 적용하는 곳(클래스, 메소드 등)
  • Advice : 실질적으로 어떤 일을 해야할지에 대한 것, 실질적인 부가기능을 담은 구현체, Aspect가 '무엇'을 '언제'할지를 정의
  • JointPoint : 끼어들 수 있는 지점, 메소드 진입 지점, 생성자 호출 지점 등 Advice가 적용될 위치
  • PointCut : JointPoint의 상세한 스펙을 정의한 것
  • Weaving : 지정된 객체에 Aspect를 적용해 새로운 프록시 객체를 생성하는 과정

AOP 주요 개념 - 상세설명

Advice 동작 시점

  • Before Advice : 조인포인트 전에 실행되는 advice
  • After returning advice : 조인포인트에서 성공적으로 리턴 된 후 실행되는 advice
  • After throwing advice : 예외가 발생하였을 경우 실행되는 advice
  • After advice : 조인포인트에서 메서드의 실행결과에 상관없이 무조건 실행되는 advice, 자바의 finally와 비슷한 역할
  • Around advice : 조인포인트의 전 과정(전, 후)에 수행되는 advice

Weaving 방식

  • RTW(Run-time Weaving)
    • Runtime 시 핵심코드와 Advice를 호출한다. Spring AOP의 기본 설정
  • CTW(Compile-Time Weaving)
    • 핵심코드와 Advice 를 컴파일 시점에 핵심코드와 Advice를 병합한다. AspectJ모듈에서 지원
  • LTW(Load-Time Weaving)
    • 프로세스가 시작될 때 핵심코드와 Advice를 조합한다. AspectJ모듈에서 지원

Spring AOP - Proxy 패턴 정의 및 문제점

proxy란?

  • 클라이언트가 사용하려고 하는 실제 대상인 것처럼 위장해 요청을 받고 대리하여 업무를 처리하는 대리자 역할 담당
  • 프록시는 실제 핵심함수를 호출 하며, 핵심 업무가 아닌 보조 업무를 처리함

장점

  • 핵심 업무의 분리

단점

  • 매번 Proxy 클래스를 직접 만들어야 함
  • 코드중복 발생

Spring AOP - Spring AOP란?

  • Spring IoC를 통한 간단한 AOP 구현을 목적으로 고안
  • Spring 개발자가 마주한 공통적인 문제(코드 중복 등)를 해결하고자 하는데 중점을 둠
  • Weaving 방식중 RTW방식을 사용
  • 기본적으로 Proxy 패턴을 이용하며, 프록시 객체를 자동으로 만들어줌
  • 완전한 AOP를 의도하지 않음

Proxy 생성 방식

  • JDK 동적 Proxy : 대상 객체가 한 개의 인터페이스를 구현 하면 JDK 동적 프록시를 사용할 수 있음
  • CGLIB Proxy : 대상 객체가 인터페이스를 구현하지 않은 경우 CGLIB 프록시 사용
  • 인터페이스 구현 여부를 통해 RTW간 프록시 생성이 구분되어짐

Proxy 생성 방식 특징

  • JDK는 자바 리플렉션을 통해 프록시 객체 생성
  • CGLIB은 Enhancer 클래스를 상속받으며 바이트코드를 조작해 프록시 객체 생성
  • CGLIB 사용시 일부 이슈(생성자 두번 호출 등)가 발생했으나, 해결되어 CGLIB 사용이 성능면에서 뛰어남

Spring AOP - 예시

maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

gradle

implementation 'org.springframework.boot:spring-boot-starter-aop'

Aspect

@Component
@Aspect
public class PerfAspect {

    @Around("execution(* com.example..*.EventService.*(..))")//com.example 패키지 밑에 있는 모든 클래스에 적용을 하고, EventService 밑에 있는 모든 메소드에 적용해라
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.currentTimeMillis();
        Object reVal = pjp.proceed();//실제 대상 객체 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return reVal;
    }
}

또는

@Component
@Aspect
public class PerfAspect {

    @Around("@annotation(CheckProcessTime)")
    //CheckProcessTime 어노테이션 사용시 해당 Advice 실행
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.currentTimeMillis();
        Object reVal = pjp.proceed(pjp.getArgs());//실제 대상 객체 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return reVal;
    }
}

Spring AOP - 예시 상세

Aspect

@Aspect
public class PerfAspect {

Advice

@Around("execution(* com.example..*.EventService.*(..))") // -> pointcut 
//또는
@Around("@annotation(CheckProcessTime)")

Target

@Target
public class SendMailController{
// 또는
@CheckProcessTime
public class SendMailController{

JointPoint

public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.currentTimeMillis();
        Object reVal = pjp.proceed(pjp.getArgs());//실제 대상 객체 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return reVal;
    }

AspectJ

  • 완전한 AOP를 제공하는 것이 목적
  • 모든 객체에 AOP 적용 가능함
  • LTW,CTW,RTW 방식 사용 가능
  • 디자인 패턴 필요 X
  • AspectJ 컴파일러를 통해 AOP 구현

Spring AOP vs AspectJ

Spring AOPAspectJ
순수 java로 구현 가능추가 도구를 통해 구현
복잡한 과정 필요 XAspectJ compiler가 필요
RTW 지원RTW,CTW,LTW 지원
Spring Container에 의해 관리되는 beans에만 적용 가능모든 객체 대상으로 적용 가능
프록시 패턴을 필요로함디자인 패턴 필요 x
비교적 성능이 안좋음비교적 성능 좋음
배우고 적용하기 쉽다Spring AOP에 비해 복잡

Spring AOP를 보편적으로 사용하되, 필요에 따라 AspectJ 사용(성능이슈, 위빙 방식 변경 등)

#별첨

실행 순서 : Filter -> Interceptor -> AOP -> Interceptor -> Filter

Filter

  • 요청과 응답을 거른뒤 정제하는 역할
  • DispatcherServlet 이전에 실행이 되며, Spring 영역 밖에서 실행됨
  • web.xml에 등록하며, 인코딩 변환 및 xss방어 처리에 사용
  • ex) init,doFilter,destroy

Interceptor

  • 요청에 대한 작업 전/후로 진행
  • 스프링 영역 내부에서 Controller에 관한 요청과 응답에 대해 처리함
  • ex) preHandler,postHandler,afterCompletion

AOP

  • OOP를 보완하기 위해 사용
  • Interceptor와 Filter와 달리 다양한 지점에서 처리가 되도록 설정이 가능하다
  • Interceptor와 Filter는 주소를 대상으로 구분하지만, AOP는 주소, 파라미터, 어노테이션 등 다양한 방법으로 대상을 지정할 수 있다.
profile
Gelog 나쁜 것만 드려요~

0개의 댓글