코드스테이츠 - AOP

kwj1830·2022년 6월 20일
0

코드스테이츠

목록 보기
25/32
post-thumbnail

OOP적으로 봤을 때, 서비스 클래스는 다른 외부 기술에 의존하지 않고 순수한 자바 언어로 작성되어 있어야 좋다.

근데 결국 Jdbc를 쓰든, JPA를 쓰든 트랜잭션을 열고 롤백하고 트랜잭션을 닫으려면 서비스 클래스에 순수 비즈니스 로직만 담기 어렵다.

이에 우린 @Transactional 어노테이션을 통해 프록시를 활용한다. 순수한 자바, 비즈니스 로직만을 만든 채

어플리케이션의 흐름은 그냥 스프링(혹은 그에 준하는)에 맡기는 거다.

각 메서드나 클래스에 핵심 기능을 실행할 때 필요한 부가기능을 편리하게, 그리고 OOP에 맞게 디자인 하기 위해서 만들어진 것이 바로 AOP다.

AOP (Aspect-Oriented Programming)

OOP만을 생각한다면, 맨 위 사진처럼 트랜잭션을 활용할 때, 코드가 쓸데 없이 복잡하고 길어지기 마련이다.

이는 유지 보수상에도 좋지 않은게, 순수한 자바 로직만 있어야 보기도 편하고 코드 작성 길이도 줄어든다.

특히 상기 이미지에서 try, catch는 반복이다. DB Connect를 따오고, 이를 통해 sql을 날리고 롤백이나 커밋을 한다.

sql문을 제외하곤 거의 동일한 부분을 계속 코딩해야 한다는 것임.

시간 = 비용이다.

AOP는 저런 공통 부분을 한꺼번에 처리할 수 있게끔 만들어준다.


AOP 용어

애스팩트 (Aspect)

  • 여러 객체에 공통으로 적용되는 기능을 말한다.
  • 어드바이스 + 포인트컷을 모듈화한다. 모듈화된 것을 앱에 포함시키는 횡단 기능이다.
  • 여러 어드바이스와 포인트컷이 함께 존재한다.

조인포인트 (JoinPoint)

  • 클래스의 초기화, 객체 인스턴스화, 메서드 호출, 필드 접근, 예외 발생 등 앱 실행 흐름에서 특정 포인트를 뜻한다.
  • 앱의 새로운 동작을 추가하기 위해 조인포인트에 관심코드(Aspect code)를 추가할 수 있다.
  • 횡단 관심은 조인포인트 전/후에 AOP에 의해 자동으로 추가된다.
  • 추상적인 개념이다. AOP를 적용할 수 있는 모든 지점이라 생각할 수 있다.
  • 스프링은 프록시(Proxy) 방식을 사용한다. 이에 조인포인트는 항상 메서드 실행 지점이 된다.
  • AOP를 수행하는 메서드는 조인포인트 인스턴스를 인자로 받게 된다.

주요 기능

스프링은 프록시 방식으로 AOP를 실행하기 때문에 메서드 실행 지점에만 적용할 수 있다.
그러므로 조인포인트가 무적권 메서드 실행에만 적용할 수 있는게 아니다.
프록시를 사용할 경우 기존 클래스를 상속받는 가상 클래스가 생기고 그 안에 메서드를 오버라이딩 하는 방식으로 작동 한다.
스프링AOP는 스프링 빈에만 적용할 수 있다. @Transactional같은 메서드도 빈 등록을 해야만 사용할 수 있음.

JoinPoint 인터페이스의 주요 기능

  • joinPoint.getArgs() : joinPoint에 전달된 인자를 배열로 반환한다.
  • joinPoint.getThis() : AOP 프록시 객체를 반환한다.
  • joinPoint.getTarget() : AOP가 적용된 대상 객체를 반환한다.
  • joinPoint.getSignature() : 조인되는 메서드에 대한 설명을 반환한다.
    • 클라이언트가 호출한 메서드의 시그니처(리턴타입, 이름, 매개변수) 정보가 저장된 Signature 객체를 반환
    • 객체가 선언하는 모든 연산, 이름, 매개변수 객체들을 시그니쳐라 한다.
    • Signature 메서드로는
      getName() : 메서드 이름 반환
      toLongString() : 호출한 메서드의 리턴, 이름, 변수를 패키지 경로 퐇마해서 반환
      toShortString() : 호출한 메서드 시그니처를 축약한 문자열로 반환

어드바이스 지점 중 Before, After Returning, After Throwing, After은 매개변수로 JoinPoint를 사용한다.
Around는 ProceedingJoinPoint를 매개변수로 사용한다.

  • proceed() : 다음 어드바이스나 타겟을 호출한다.
    Around는 얘를 써야 하기 때문

어드바이스 (Advice)

  • 조인포인트에서 수행되는 코드를 말한다.
  • Aspect를 언제 적용할 지를 정의한다.
  • 시스템 전체 Aspect에 API 호출을 제공한다.
  • 스프링에서는 5개의 동작 시점이 제공된다.
    - Before : 메서드 실행 전 동작 (일반적으론 void)
    - After Returning : 메서드가 성공적으로 리턴되면 동작 (리턴 값이 존재해야함)
    - After Throwing : 메서드 실행 중, 예외가 발생하면 동작
    - After : 메서드가 실행된 후 무적권 실행
    - Around : 메서드 호출 자체를 가로채서 실행 전, 후 모든 부분에 로직을 삽입할 수 있다.

    어노테이션으로 지정할 수 있다.
    기본적으로 순서를 보장하지 않기 때문에, @Aspect, @Order 어노테이션을 활용해아 한다.
    클래스 단위로 적용할 수 있음. 사용할 때엔 애스택트들을 별도의 클래스로 분리해야 한다.

    Around

    Around는 가장 강력한 어드바이스다. 이 어드바이스 하나로 상기 4개 모든 기능을 수행할 수 있다.
    proceed()를 통해 대상을 실행하고, 여러번 실행할 수도 있다.
    다만 각 어노테이션 이름이 워낙 명시적이어서 실제 설계시엔 각각의 어드바이스를 잘 활용해야 하겠다.

포인트컷 (Pointcut)

  • 조인포인트중에서 어드바이스가 적용될 위치를 선별하는 기능.
  • AspectJ 표현식을 사용해서 지정한다.
  • 스프링은 프록시를 사용하므로 메서드 실행지점만 가능하다.
  • @Pointcut 어노테이션을 사용하여 표시 한다.

포인트컷 표현식과 지시자

@Pointcut("execution(* transfer(..))") //이런 식으로 사용함
void exampleMethod() {} // 포인트컷의 서명

포인트컷은 &&, ||, !를 사용해서 결합할 수 있다.

위빙 (Weaving)

  • 어드바이스를 적용하는 것을 위빙이라고 한다.

타겟 (Target)

  • AOP를 적용할 핵심 로직을 의미한다

어노테이션(Annotation)을 활용한 AOP

스프링은 AOP를 지원함. @AspectJ를 활용하면 됨.

@AspectJ

@AspectJ 는 Java AOP 소프트웨어의 사실상의 표준이다. (개많이씀)

스프링 역시 AspectJ를 통한 AOP 개발을 지원한다. 때문에 스프링AOP와 AspectJ 두가지 방법 모드 스프링에서 해석이 가능함.

스프링 AOP은 그럼에도 AspectJ 컴파일러나 위버에 의존하지 않는다.

@Configuration에 AspectJ 지원을 활성화 하려면 @EnableAspectJAutoProxy을 추가로 선언해준다.

AspectJ 지원이 활성화 되면 @AspectJ가 선언된 빈을 스프링에서 자동으로 감지하고 스프링AOP를 구성하는데 사용한다.

profile
https://potent-grey-e01.notion.site/36c7ffc9d32e4e83b325da26ed8d1728<-- 포트폴리오

0개의 댓글