본문 바로가기
BackEnd/Spring

Spring AOP

by 규난 2023. 8. 5.
728x90

이번 포스트에서는 Spring의 3대 요소 중 하나인 Spring AOP에 대해서 알아보도록 하겠습니다.

 

AOP(Aspect Oriented Programming)

일단 AOP가 뭔지 알아보기 전에 Asepect가 뭔지에 대해서 간단하게 알아보도록 하겠습니다.

Aspect란 애플리케이션의 핵심 기능을 담고 있지는 않지만, 애플리케이션을 구성하는 중요한 한 가지 요소이면서 핵심 기능에 부가되어 의미를 갖는 특별한 모듈을 가르킵니다. Aspect는 부가 기능을 정의한 코드인 어드바이스어드바이스를 어디에 적용할지 결정하는 포인트 컷을 함께 갖고 있으며, 이 둘을 합친 개념의 어드바이저는 단순한 형태의 Aspect라고 볼 수 있습니다.

 

Aspect를 간단하게 알아보았으니 이제 AOP에 대해서 알아보도록 하겠습니다.

AOP란 애플리케이션의 핵심 기능에서 부가 기능을 분리하여 Aspect라는 모듈로 만들어서 설계하고 개발하는 방법을 AOP라고 부릅니다.

즉 횡단 관심사(cross-cutting concern)를 분리하여 모듈성을 증가시키는 것이 목적인 기술입니다.

 

AOP는 핵심 기능이 모여있는 코드에 부가 기능 코드가 같이 들어가는 경우 부가 기능의 코드로 인해 OOP의 설계 원칙 중 OCP와 SRP를 지키기 힘들기 때문에 OOP를 대체하기 위해 나온 기술이 아니라 보조하기 위해 나온 기술입니다.

 

또한 AOP는 Decorator/Proxy pattern을 사용하는데, 이 두 개의 디자인 패턴 모두 프록시 객체를 사용하는 디자인 패턴입니다. 여기서 프록시는 클라이언트가 사용하려고 하는 실제 대상 객체인 것처럼 위장해서 클라이언트의 요청을 받아주는 역할을 하는 객체입니다.

Decorator pattern은 프록시를 사용해 대상 객체에 부가 기능을 런타임 시 동적으로 부여해 줍니다. 즉, 대상 객체를 래핑 하여 대상 객체의 기능을 확장하는 방식으로 사용됩니다.

Proxy pattern은 Decorator pattern과 다르게 대상 객체에 기능을 확장하거나 추가하는 방식이 아니라 프록시 객체가 호출되었을 때 Pointcut을 보고 부가 기능인 Advice를 적용할 건지 바로 핵심 기능을 호출할 건지에 대한 접근 제어를 하는 방식으로 사용됩니다. 

 

(포인트 컷과 어드바이스는 밑의 AOP 용어에서 설명하도록 하겠습니다.)

 

AOP의 적용 방식

  • 컴파일 시점에 적용
  • 클래스 로딩 시점에 적용
  • 런타임 시점에 적용 (프록시 방식의 AOP) - Spring AOP에서 사용하는 방식
    • 런타임 시점에 AOP를 적용하는 방식은 스프링 IoC/DI 컨테이너와 다이나믹 프록시, 데코레이터 패턴, 프록시 패턴, 자동 프록시 생성 기법, 빈 후처리기 조작 기법 등의 다양한 기술을 조합해서 스프링 빈에 AOP를 적용하는 방식입니다.

AOP의 용어

  • Target 
    • 부가 기능(advice)을 부여할 대상입니다. 핵심 기능이 담긴 대상 오브젝트가 될 수도 있지만 경우에 따라서 다른 부가 기능을 제공하는 프록시 객체가 될 수도 있습니다.
  • Advice
    • 타겟에 제공할 부가 기능 로직을 담은 모듈입니다. Advice의 종류는 여러 가지이기 때문에 다음 포스트에서 자세히 알아보도록 하겠습니다.
  • JoinPoint 
    • 어드바이스가 적용될 수 있는 모든 위치를 말합니다. 컴파일 시점 또는 클래스 로딩 시점에 AOP를 적용하는 방식은 바이트코드를 조작하기 때문에 생성자, 필드 값, static 메서드, 메서드 등 모든 지점에 어드바이스를 적용할 수 있지만 프록시 방식의 AOP를 적용하는 Spring AOP는 메서드 실행 지점에만 어드바이스를 적용할 수 있습니다.
  • Pointcut
    • 어드바이스를 적용할 조인 포인트를 선별하는 작업의 기능을 정의한 모듈입니다. Spring AOP의 조인 포인트는 메서드 실행 지점이므로 Spring의 Pointcut은 메서드를 선정하는 기능을 가지고 있습니다. 쉽게 말해 어느 메서드에 어드바이스를 적용할지 판단하는 필터링 로직을 담당하는 곳입니다.
  • Advisor
    • 어드바이저는 포인트 컷과 어드바이스를 하나씩 가지고 있는 객체입니다. 부가 기능을 어디에 적용할지 알고 있는 AOP의 가장 기본이 되는 모듈입니다. 어드바이저는 스프링에서만 사용되는 용어이고 자동 프록시 생성기가 스프링 컨테이너에 등록된 어드바이저 빈을 AOP 작업의 정보로 활용하게 됩니다.
  • Aspect
    • 한 개 또는 그 이상의 포인트 컷과 어드바이스의 조합으로 만들어지며 보통 싱글톤 형태의 객체로 존재하는 AOP의 기본 모듈입니다.

 

자동 프록시 생성기의 동작 과정

스프링의 자동 프록시 생성기인 AnnotationAwareAspectJAutoProxyCreator는 어플리케이션 로딩 시점에 스프링 컨테이너에서 @Aspect 애노테이션이 붙은 모든 빈을 조회해서 BeanFactoryAspectJAdvisorsBuilder를 통해 @Aspect 애노테이션 정보를 기반으로 Adviosor를 생성 후 해당 빈이 싱글톤인 경우에 BeanFactoryAspectJAdvisorsBuilder 내부 advisorsCache에 저장하게 됩니다.

 

이렇게 @Aspect 애노테이션을 사용해서 생성된 advisor와 수동으로 만든 advisor를 기반으로 프록시 적용 대상인 경우 프록시 객체를 스프링 컨테이너에 빈으로 등록하고 적용 대상이 아니라면 원본 객체를 빈으로 등록해서 관리하게 됩니다.

 

밑의 이미지는 김영한 님의 스프링 고급 편에서 자동 프록시 생성기의 동작 과정을 설명하는 이미지입니다.

이미지를 보시면 위에서 언급한 내용처럼 자동 프록시 생성기가 스프링 컨테이너에 등록된 advisor와 BeanFactoryAspectJAdvisorsBuilder에 캐싱 되어 있는 advisor를 조회하고 스프링 빈 대상이 되는 객체가 프록시 적용 대상인지 체크를 한 후 적용 대상인 경우 프록시 객체를 빈으로 등록하고 적용 대상이 아닌 경우 원본 객체를 빈으로 등록하는 과정을 보여주고 있습니다.

 

이번 포스트에서 Advice의 종류와 Pointcut까지 다루면 너무 길어질 거 같아서 포스트를 나눠서 올려야겠습니다.

다음 포스트에서는 Advice의 종류와 Pointcut에 대해서 포스팅하겠습니다.

728x90