<TIL> 60. Spring AOP

YUJIN LEE·2023년 3월 16일
0

개발log

목록 보기
55/149

AOP(Aspect Oriented Programming)?

AOP는 관점지향 프로그래밍.
관점지향 -> 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어 보고 그 관점을 기준으로 모듈화 하겠다는 것.

  • 모듈화: 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것.

핵심적인 관점은 비즈니스 로직이 될 수 있고,
부가적인 관점은 핵심 로직을 실행하기 위해 행해지는 데이터베이스 연결, 로깅, 파일 입출력 등이 될 수 있다.

AOP는 흩어진 관심사(Crosscutting Concerns)를 모듈화 할 수 있는 프로그래밍 기법.

흩어진 관심사를 모듈화 하겠다는 의미.
이때 모듈화 시켜놓은 블럭 -> Aspect라고 한다.

  • Aspect: 흩어진 관심사를 모듈화 한 것.
  • Target: Aspect를 적용하는 곳. (클래스, 메서드 등..)
  • Advice: 실질적으로 어떤 일을 해야 할 지에 대한 것, 실질적인 부가기능을 담은 구현체.
  • Join Point: Advice가 적용될 위치 혹은 끼어들 수 있는 시점. 메서드 진입 시점, 생성자 호출 시점, 필드에서 꺼내올 시점 등 끼어들 시점들 의미.
    -> 스프링에서 Join Point는 언제나 메서드 실행 시점 의미.
  • Point Cut: Join Point의 상세한 스펙을 정의.
    - "A란 메서드의 진입 시점에 호출할 것"처럼 구체적으로 Advice가 실행될 시점 정함.

Spring AOP

  • 스프링에서 제공하는 스프링 AOP는 proxy 기반 AOP 구현체.
  • Proxy 객체를 사용하는 것은 접근 제어 및 부가 기능을 추가하기 위해.
  • Spring AOP는 Spring Bean에서만 적용 가능.
  • 모든 AOP 기능을 제공하는 것이 목적이 아닌, 중복코드, Proxy 클래스 작성의 번거로움 등 흔한 문제를 해결하기 위한 솔루션을 제공하는 것이 목적.
  • Spring AOP는 순수 자바로 구현, 특별한 컴파일 과정 필요 x
  • Proxy 패턴
    - interface존재. Client는 이 interface 타입으로 Proxy 객체를 사용.
    • Proxy 객체는 기존 타겟 객체(Real Subject)를 참조, Proxy 객체와 기존 타겟 객체의 타입은 같고, Proxy는 원래 할 일을 가지고 있는 Real Subject를 감싸 Client의 요청 처리.

부가기능 모듈화의 필요성

핵심기능: 각 API 별 수행해야 할 비즈니스 로직

ex) 상품 키워드 검색, 관심상품 등록, 회원 가입, 관심상품에 폴더 추가...

부가기능: 핵심기능을 보조하는 기능

ex) 회원 패턴 분석을 위한 로그 기록, API 수행시간 저장

문제점

  • 모든 핵심기능의 Controller에 부가기능 코드 추가 시,
    - 핵심기능이 100개? -> 100개의 핵심기능에 동일한 내용의 코드 추가 필요..
  • 핵심기능 수정 시
    - 같은 함수 내에 핵심기능과 부가기능이 섞임.
    • 핵심기능 이해를 위해 부가기능까지 이해 필요..
  • 부가기능 변경 필요시..
    - 핵심기능 개수만큼 부가기능도 수정해야함
    • 부가기능 삭제

부가기능을 모듈화

AOP(Aspect Oriented Programming)을 통해 부가기능 모듈화

부가기능은 핵심기능과는 관점(Aspect), 관심이 다름

--> 핵심기능과 분리해서 부가기능 중심으로 설계, 구현 가능.

스프링이 제공하는 AOP

스프링AOP 이해

스프링 AOP 동작 이해

개념적 이해

스프링 실제 동작

시퀀스 다이어그램(Sequence Diagram)

AOP 적용 전

AOP 적용 후

  • DispatcherServlet과 ProductController 입장에서는 변화 전혀X
    - 호출되는 함수의 input, output이 완전 동일
    • "joinPoint.proceed()"에 의해 원래 호출하려고 했던 함수, 인수(argument)가 전달.
      -> createProduct(requestDto)

스프링 서버가 기동될 때, 핵심 기능 DI 되는 시점에 프록시 객체를 중간에 삽입해 이런 것들이 가능.

Spring AOP 어노테이션

  1. @Aspect
    • 스프링 빈(Bean) 클래스에만 적용 가능
  2. 어드바이스 종류
    AOP로 분류해 모아둔 코드가 실행되는 시점.
  • @Around: 핵심기능 수행 전과 후까지 체크(@Before + @After)
  • @Before: 핵심기능 호출 전 (ex. Client의 입력값 Validation 수행)
  • @After: 핵심기능 수행 성공/실패 여부와 상관없이 언제나 동작 (try, catch의 finally() 처럼 동작)
  • @AfterReturning: 핵심기능 호출 성공 시 (함수의 Return 값 사용 가능)
  • @AfterThrowing: 핵심기능 호출 실패 시. 즉, 예외(Exception)가 발생한 경우만 동작
    (ex. 예외가 발생 시 개발자에게 email이나 SMS 보냄)
  1. 포인트컷
    어드바이스가 "실행될 시점"을 정해줬다면, 포인트컷은 "실행될 장소"를 정해준다.
  • 포인트컷 Expression Language
    - 포인트컷 Expression 형태
execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name-pattern(param-pattern) throws-pattern?)

-> ?는 생략 가능

  • modifiers-pattern : public, private, *
  • return-type-pattern : void, String, List<String>, *
  • declaring-type-pattern
    - 클래스명(패키지명 필요)
    - com.example.springcore.controller.* - controller 패키지의 모든 클래스에 적용
    - com.example.springcore.controller.. - controller 패키지 및 하위 패키지의 모든 클래스
  • method-name-pattern(param-pattern)
    함수명
    - addFolders: addFolders() 함수에만 적용
    - add* : add로 시작하는 모든 함수에 적용
    파라미터 패턴(param-pattern)
    - (com.example.springcore.dto.FolderResquestDto) - FolderRequestDto 인수 (arguments) 만 적용
    - () - 인수 없음
    - (*) - 인수 1개 (타입 상관 X)
    - (..) - 인수 0~N개 (타입 상관없음)
  • Pointcut
    포인트컷 재사용 가능
    포인트컷 결합(combine) 가능
@Component
@Aspect
public class Aspect {
	@Pointcut("execution(* com.sparta.springcore.controller.*.*(..))")
	private void forAllController() {}

	@Pointcut("execution(String com.sparta.springcore.controller.*.*())")
	private void forAllViewController() {}

	@Around("forAllContorller() && !forAllViewController")
	public void saveRestApiLog() {
		...
	}

	@Around("forAllContorller()")
	public void saveAllApiLog() {
		...
	}	
}
profile
인정받는 개발자가 되고싶습니다.

0개의 댓글