초이로그

Spring AOP 본문

우아한테크코스/테코톡 정리

Spring AOP

수연초이 2022. 10. 14. 16:20
[10분 테코톡] 🌕제이의 Spring AOP
[10분 테코톡] 🐸뚱이의 AOP - Advice Target Pointcut
를 정리한 글

부가 기능

서비스에서는 비즈니스 로직이라고 불리는 핵심 기능만 필요하다. 이 외에 시간을 재거나, 권한을 체크하거나, 트랜잭션을 거는 것은 모두 일종의 인프라 로직이라고 한다. 아래는 부가 기능이 섞여있는 서비스 코드의 예시이다. 

인프라 로직

  • 애플리케이션 전 영역에서 나타날 수 있다
  • 중복 코드를 만들어낼 가능성 때문에 유지보수가 힘들어진다 ➡️ 유지보수가 어려워진다
  • 비즈니스 로직과 함께 있으면 비즈니스 로직을 이해하기 어려워진다
  • 인프라 로직은 로깅, 트랜잭션, 권한 검사, 성능 측정 등 하나의 관심사를 갖는다. 비즈니스 로직을 수행하는데 있어서 부가 기능이 되는 인프라 로직의 중복이 횡단으로 나타나기 때문에 이를 횡단 관심사(cross-cutting concern)라고 한다.

AOP(Aspect-Oriented Programming)

  • 관점 지향 프로그래밍. 횡단 관심사에 따라 프로그래밍한다.
  • 여러 오브젝트에 나타나는 공통적인 부가 기능을 모듈화하여 재사용하는 기법이다.
  • 더 객체지향적으로 코드를 구성할 수 있도록 보완해준다.
  • AOP는 OOP와 같은 일종의 패러다임으로, 각 언어마다 AOP의 구현체가 있다.
    • 자바는 AspectJ를 사용한다.

 

어떤 부가기능을 어디에 적용할까? (AOP 용어)

  • Target: 어떤 대상에 부가 기능을 부여할 것인가? 부가 기능이 부여되는 대상
  • Advice: 어떤 부가 기능을 언제 부여할 것인가? (Join Point가 메서드 실행이 기준일 때⬇️)
    • Before: 메서드가 호출되기 전
    • AfterReturning: 메서드가 실행돼서 제대로 된 결과값을 리턴했을 때
    • AfterThrowing: 메서드 실행 시점에서 무언가 예외가 터졌을 때
    • After: 메서드가 끝났을 때
    • Around: 메서드 실행 전 후

  • Join Point: 어디에적용할 것인가? 메서드, 필드, 객체, 생성자 등
    • Java의 AspectJ에서는 메서드가 호출될 때, 실행될 때, 필드에 접근할 때, 객체가 생성될 때 등 다양하게 Join Point를 구현하여 여러가지 상황에서 부가 기능을 실행 가능하다.
    • Spring AOP에서는 메서드가 실행될때만으로 한정한다.
  • Point Cut: 실제 advice가 적용될 지점 선별
    • Spring AOP에서는 Join Point가 메서드가 실행될 때이므로 advice가 적용될 메서드를 선정하는 기능을 한다.

 

AOP의 구현 방법

  • 컴파일: 컴파일 시점(.java파일을 .class 파일로 변환)에 해당하는 aspect들을 끼워 넣어 AOP를 적용한다.
  • 클래스 로드 시: 클래스 로더가 .class 파일을 메모리 상에 올릴 때 AOP를 적용한다.
  • 프록시 패턴:J라는 타겟 클래스를 부가 기능을 제공하는 프록시로 감싸서 실행한다.
    • Spring AOP의 사용 방식. Spring은 IoC와 DI를 기반으로 하기 때문에 가능한 방식이다.

예시)

AOP가 적용되지 않은 AuthController의 authService 주소: org.woowacourse.aop.service.AuthService

AOP가 적용된 AuthController의 authService 주소: org.woowacourse.aop.service.AuthService$$EnhancerBySpringCGLIB$$B1be6d68

프록시이며, 프록시의 target안에 authService가 존재한다

 

AOP가 적용되지 않는 경우?

  • 동일 클래스의 메서드를 실행하는 경우 AOP가 적용되지 않는다. 즉, 타겟 오브젝트가 타겟 오브젝트 안에 있는 메서드를 실행하는 경우 AOP가 적용되지 않은 target 객체의 메서드를 그대로 실행하기 때문에 적용되지 않는다.
  • AuthService 안에 있는 private 메서드에 AOP를 적용하는 경우의 예시이다.
    • 프록시로 감싼 객체가 실제로 타겟 객체의 join이라는 메서드를 실행할 때 inner 메서드는 AOP로 감싼 프록시 객체가 아니기 때문이다. 즉, 자기 자신을 호출하므로 AOP로 감싸지지 않은 본래의 메서드가 호출된다.
public void join(JoinRequest joinRequest) { // AOP 적용 X
	inner();
    memberRepository.save(joinRequest.toMember());
}

@PerformanceCheck // AOP가 적용되었지만 실행되지 않는다.
private void inner() {
	System.out.println("페퍼");
}
  • 서비스의 private 메서드의 @Transactional이 작동하지 않는 이유이다.

 

Spring AOP의 사용 예시

  • 트랜잭션 처리 - @Transactional
    • 스프링 AOP 중 하나이다.  
    • 서비스 로직을 하나의 트랜잭션으로 생성할 때, 로직의 시작점에 트랜잭션을 열고 끝나는 시점에 트랜잭션을 커밋하는 코드가 들어가야한다. @Transactional 애너테이션을 사용하면 트랜잭션과 관련된 인프라 로직은 AOP로 분리하고 비즈니스 로직에만 집중 가능하다.
  • Interceptor & Filter
  • 성능 검사
  • 로깅

 

Spring AOP vs. AspectJ

  • AspectJ
    • Java에서 구현되었으며 다양한 Join Point를 통해 완벽한 AOP의 기능을 모두 제공한다.
    • 스프링에서 지원하는 IoC나 DI 기능이 없기 때문에 런타임 시점에는 제공하지 못하고 컴파일, 포스트 컴파일, 로드 타임에 제공한다.
    • 모든 Java Object에 제공 가능하다.
  • Spring AOP
    • 개발자들이 만날 수 있는 문제를 해결하기 위한 목적으로 간단하게 AOP의 기능을 프록시 패턴을 통해 제공한다 
    • 메서드 레벨만 지원하며, weaving(AOP를 끼워넣는 시점)도 런타임 시에만 가능하다. 스프링 컨테이너가 객체의 생성을 관리하기 때문에 가능하다. 따라서 타겟 오브젝트(대상)도 스프링 컨테이너가 관리하는 빈만 가능하다.

 

'우아한테크코스 > 테코톡 정리' 카테고리의 다른 글

데이터베이스 락  (2) 2022.11.09
JDK Dynamic Proxy vs CGLIB Proxy  (3) 2022.10.18
인덱스  (0) 2022.10.14
CI/CD와 무중단 배포  (0) 2022.10.09
트랜잭션  (0) 2022.10.08