AOP

이경현·2024년 11월 12일

1112
AOP

AOP는 aspect-oriented programming의 약자로 관점 지향 프로그래밍이라고도 말한다.
AOP는 프로그램 구조에 대한 또 다른 사고 방식을 제공하여 객체 지향 프로그래밍(OOP)을 보완한다.
OOP에서 모듈화의 핵심 단위가 "클래스"라고 한다면, AOP에서는 핵심 단위가 "관점"이다.
반복되고 공통적으로 사용되는 부분을 분리함으로써 모듈성을 증가시키는 프로그래밍 방법이다.

"관점 지향"이라는 말이 잘 와닿지 않는데,
분업을 떠올리면 좀 더 이해가 쉽다.
로깅과 트랜잭션, 보안 기능을 AOP의 대표적인 예시로 많이 등장하는데,
트랜잭션을 예로 들어보자. 비즈니스 로직 전과 후에 트랜잭션을 위한 처리를 해주어야 한다.

  1. 비즈니스 로직 전: 비즈니스 메서드가 현재 실행중인 데이터베이스 트랜잭션에서 실행되야 하는지 새로운 독립적인 트랜잭션에서 실행되어야하는지 결정한다.
  2. 비즈니스 로직 실행
  3. 비즈니스 로직 후: 예외가 발생했다면 트랜잭션을 롤백 처리하고, 그렇지 않다면 커밋한다.

Serive 계층에는 요구사항을 처리하기 위한 수많은 메서드가 있는데,
트랜잭션 처리가 필요한 메서드마다 로직 전 후로 코드를 작성해야 한다면 매우 번거로워진다.
또한 에러가 발생하기 쉽고 관리가 어려워진다.

가장 핵심적인 비즈니스 로직에 집중하고 싶다면? 관심사를 분리하자.

비즈니스를 위해 필요한 부분과 트랜잭션 처리를 위해 필요한 부분은 관심사가 다르다고 볼 수 있다.
이를 분리한다면 각각의 관심사에 집중할 수 있다.
여러 메서드에 반복적으로 사용되며 흩어져있던 코드가 한 곳으로 모아지게 되기 때문에,
아래와 같은 장점이 있다.

  1. 수정이 편해진다.
  2. 반복되는 코드가 줄어든다.
  3. 재사용성이 높아진다.
  4. 비즈니스 로직에 집중할 수 있다.

AOP용어

  1. Cross-cutting concerns(횡단 관심사)
    로직 전 또는 후에 실행되어야하는 공통적인 작업.
  2. Advice
    aspect가 해야하는 작업과 시기.
  3. Target
    advice가 적용될 객체.
  4. Join Point
    advice를 적용할 수 있는 지점들. 메서드, 필드, 객체, 생성자 등. Spring AOP에서는 메서드가 실행될 때만 적용되도록 한정하고 있다.
  5. Point Cut
    실제 advice가 적용될 지점. advice가 적용될 수 있지만 적용되지 않는 곳도 존재할 것이다. point cut은 join point 중에서도 advice가 적용되는 지점을 말한다.
  6. Proxy
    advice를 target 객체에 적용하면 생성되는 객체. Aspect를 구현하기 위해 프레임워크로부터 만들어진 객체라고도 말한다. Spring 프레임워크에서 AOP proxy는 JDK dynamic proxy 또는 CGLIB proxy이다.
  7. Aspect
    AOP에서는 횡단관심사를 aspect라는 특별한 객체로 모듈화한다. 이는 advice와 point cut을 합친 것으로, 무엇을 언제 어디서 할지에 대한 정보가 모두 정의되어 있다.
  8. Weaving
    target 객체에 aspect를 적용해서 새로운 프록시 객체를 생성하는 절차. aspect는 target 객체의 join point로 위빙된다. 위빙은 대상 객체의 생애 중 다음과 같은 시점에서 수행될 수 있다.

구현방법

AOP는 패러다임이기 때문에, 각 언어마다 구현체가 있다. Java 프로젝트에서 AOP를 구현하기 위해 지원하는 프레임워크는 AspectJ, JBoss AOP, Spring AOP가 있다고 한다.

Spring에서는 다음 3가지 방법 중 한 가지를 선택하여 AOP를 구현할 수 있다. Spring 공식문서에서는 일반적인 애플리케이션의 경우 AspectJ pointcut을 활용하여 AOP를 사용할 것을 권장하고 있다.
1. @AspectJ 어노테이션 활용
2. 스키마 기반 접근법(schema-based approach)
3. Spring AOP API 활용

의존성이 아래와 같이 구성되어 있기 때문에, spring-boot-starter-data-jpa 나 spring-boot-starter-data-aop를 의존성으로 추가하면,
Spring AOP와 AspectJ를 모두 사용할 수 있다.

@AspectJ 어노테이션 활용

  1. @AspectJ 를 사용하기 위한 설정
    @AsjpectJ의 지원을 허용하는 것이 가장 첫 번째 단계이다. 설정 파일에 다음과 같이 @EnableAspectJAutoProxy 어노테이션을 활용하여 허용할 수 있다.

  2. Aspect 구현하기

Aspect는 앞서 용어 정리에서 언급한 듯이 Advice와 Pointcut으로 구성된다. 우선 Advice의 경우 아래처럼 5개의 어노테이션을 지원한다.
@Pointcut 어노테이션은 반복적으로 사용되는 pointcut을 지정할 수 있다. 해당 어노테이션을 활용하지 않고, advice 어노테이션 안에 pointcut을 지정해도 된다.

아래는 com.example.aop.annotation.service에 있는
모든 메서드에 Before Advice와 After Advice를 적용하는 예시인데,

@Pointcut 어노테이션을 활용해 반복되는 pointcut을 변수로 만들어 활용하고 있다.

Spring AOP API 활용

  1. 스프링 빈 대상이 되는 객체를 생성한다.(@Bean, 콤포넌트 스캔 대상)
  2. 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기에 전달한다.
  3. 모든 Advisor 빈을 조회하고 Pointcut을 통해 클래스와 메서드 정보를 매칭해보면서 프록시를 적용할 대상인지 판단한다.
  4. 객체의 모든 메서드를 포인트컷에 비교해보면서 조건이 하나라도 만족한다면 프록시를 생성하고 프록시를 빈 저장소로 판단한다.
  5. 만약 프록시 생성 대상이 아니라면 들어온 빈 그대로 빈 저장소로 반환한다.
    빈 저장소는 객체를 받아서 빈으로 등록합니다.

Aspect 구현
여기서도 Advice를 정의해줘야한다. Spring AOP에서는 Advice 유형에 따른 인터페이스를 아래와 같이 지원한다.

예시
MethodInterceptor 인터페이스를 활용하여 Around Advice를 생성하고 Target에 적용했다.

0개의 댓글