Spring AOP (1) : 기본 개념

YUZE·2024년 11월 29일
1

Auction

목록 보기
2/5
post-thumbnail

핵심 기능과 부가 기능


현재 진행하고 있는, 옥션 프로젝트에서 보면, paymet기능, auction기능 admin 기능에서 공통적으로 접근자에 대한 권한체크 가 선행되어야 한다.

이는, 도메인에 대한 핵심 로직이 아닌 권한 체크 라는 부가 기능이다.

개발을 하면서, 이 권한 체크를 반복적으로 하게 된다면 가독성이 좋지 않고, 우리 프로젝트에서는 인증 인가가 아직 도입되지 않았지만, 도입 될 경우, 토큰을 사용하는 대부분의 엔드포인트에서 권한 체크 로직을 작성해야 된다.

외에도, 아래와 같이 다양한 문제가 발생한다.


부가 기능 적용 문제

  • 부가 기능을 적용할 때 아주 많은 반복이 필요
  • 부가 기능이 여러 곳에 퍼져서 중복 코드를 발생
  • 부가 기능을 변경할 때 중복 때문에 많은 수정이 필요
  • 부가 기능의 적용 대상을 변경할 때 많은 수정이 필요

💡 그렇다면, 여러 곳에서 공통으로 사용하고 있는 부가 기능을 모듈화 해서 한 곳에 보관할 수 없을까?



AOP


관점 지향 프로그래밍으로, 부가 기능을 핵심 기능에서 분리하고, 한 곳에서 관리해보자는 것에서 시작된 개념

⇒ 핵심 기능과 부가 기능을 분리 목적



JAVA에서 AOP를 구현할 수 있는 방법


1. AspectJ 프레임워크를 직접 이용

  • AOP의 대표적인 구현으로, AspectJ 프레임워크가 있다.

2. Spring AOP 이용

schema based approach

  • AOP 설정을 XML 파일에서 정의하는 방식
  • 스프링 설정 파일(applicationContext.xml)에 <aop:config><aop:aspect> 등의 태그를 사용

@AspectJ annotaion style

  • AspectJ 스타일의 어노테이션(@Aspect, @Before, @Pointcut)을 사용하여 AOP를 정의
  • Spring aop는 AspectJ를 직접 사용하는 것은 아니다. AspectJ 문법을 차용했을 뿐

스프링 공식 문서



AOP 적용 방식


AOP를 통해 부가 기능 로직은 어떤 방식으로 실제 로직에 추가될 수 있을까?

  • 컴파일 시점
  • 클래스 로딩 시점
  • 런타임 시점(프록시)

1. 컴파일 시점 (컴파일 타임 위빙)

  • 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함
  • .java 가 컴파일 되면서 .class가 되는 시점에 발생
  • AspectJ 컴파일러가 컴파일 시점에, AspectJ 모듈을 적용 대상에 로직을 붙인다
  • 복잡하다는 단점
  • AspectJ 프레임워크를 이용해서만 구현 가능

2. 클래스 로딩 시점 (로드 타임 위빙)

  • 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함
  • 자바를 실행하면 자바 언어는 .class 파일을 JVM 내부의 클래스 로더에 보관한다. 이때 로더에 올리는 시점에 중간에서 .class 파일을 가로채 조작한 다음 JVM에 올림
  • 복잡하다는 단점
  • AspectJ 프레임워크를 이용해서만 구현 가능

3. 런타임 시점 (런타임 위빙)

  • 실제 대상 코드는 그대로 유지 됨
  • 컴파일이 끝나고, 클래스 로더에 클래스도 다 올라가서 이미 자바가 실행되고 난 다음(main 메서드가 이미 실행된 다음)에 Aop가 적용 됨
  • 자바 언어가 제공하는 범위 안에서 부가 기능을 적용해야 함
  • 프록시를 통해 스프링 빈에 부가 기능을 적용할 수 있음
  • 프록시를 사용하기 때문에, 메서드 실행지점에만 적용 가능
  • Spring AOP는 이 방식을 사용

AOP 적용 위치

  • 적용 가능 지점(조인 포인트): 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행
    • 이렇게 AOP를 적용할 수 있는 지점을 조인 포인트(Join point)라 한다.
  • AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에 해당 기능을 모든 지점에 다 적용할 수 있다.
  • 프록시 방식을 사용하는 스프링 AOP는 메서드 실행 지점에만 AOP를 적용할 수 있다.
  • 프록시는 메서드 오버라이딩 개념으로 동작한다.
    • 따라서 생성자나 static 메서드, 필드 값 접근에는 프록시 개념이 적용될 수 없다.
    • 프록시를 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다
  • 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다


AOP 기본 용어


[Join Point] 어디에 적용할 것인가

  • AOP를 적용할 수 있는 모든 지점을 의미한다
  • 추상적인 개념
  • 스프링 AOP는 프록시 방식을 사용하므로 조인 포인트는 항상 메서드 실행 지점으로 제한
  • 조인 포인트는 가능한 위치를 의미하며, 실제 적용되는 지점은 포인트컷으로 필터링
  • 타겟 객체의 메서드 실행 시점
  • JointPoint 인터페이스의 메서드
    getArgs()메서드 아규먼트를 반환
    getThis()프록시 객체를 반환
    getTarget()대상 객체를 반환
    getSignature()어드바이스 또는 메서드의 설명(description)을 반환
    toString()어드바이스 되는 메서드의 설명을 출력한다.

[Pointcut] 좀 더 자세히, 어디에?

  • 어드바이스를 적용할 조인 포인트를 선별
    • 특정 조건에 의해 필터링 된 조인 포인트
    • 메서드 선택 기준이라고 생각하면 된다
  • 실제 Advice가 적용되는 지점
  • 스프링 AOP에서는 메서드 PointCut의 대상
  • 프록시를 사용하는 스프링 AOP는 메서드 실행 지점만 포인트컷으로 선별 가능

[Target] 부가 기능을 부여할 대상

  • AOP가 적용될 대상
  • 포인트 컷으로 결정

[Advice] 어떤 부가 기능을 부여할 것인가

  • 특정 조인 포인트에 적용할 부가 기능
  • 어느 시점에, 어떤 기능을?
  • 부가 기능 실행되는 시점을 지정할 수 있다
    @Before메서드 실행 전에 실행
    @After메서드 실행 후에 실행(예외 발생 되더라도 실행 됨)
    @AfterReturning메서드가 정상적으로 종료된 후 실행
    @AfterThrowing메서드에서 예외가 발생한 후 실행
    @Around메서드 실행 전후를 모두 제어

[Aspect] 어드바이스 + 포인트 컷을 모듈화 한 것

  • Spring에서는 클래스에 @Aspect어노테이션을 사용하여 정의
  • 여러 어드바이스와 포인트 컷이 함께 존재
  • 횡단 관심사를 캡슐화 한 모듈 → AOP를 모아둔 클래스

[Advisor] 하나의 어드바이스 + 하나의 포인트 컷

  • 어떤 메서드에 어느 시점에 어떤 기능을 부여할 것인지?
  • 스프링 AOP에서만 사용되는 용어

[Weaving] 어드바이스를 적용하는 동작

  • 포인트 컷으로 결정한 타겟의 조인 포인트에 어드바이스를 적용하는 것
  • 핵심 기능에 영향을 주지 않고 부가 기능을 추가할 수 있음
  • 스프링 AOP에서는 Runtime Weaving을 사용
  • Aspect와 애플리케이션 코드를 결합하는 과정
profile
안녕하세요

0개의 댓글

관련 채용 정보