Spring

[Spring] 스프링 AOP 개념

이덩우 2024. 3. 7. 18:41

1. AOP(Aspect-Oriented Programming)이란?

- 핵심 기능과 부가 기능

부가 기능을 분리하기 위해 다양한 디자인 패턴부터, 스프링이 제공하는 자동 프록시 생성기까지 알아봤다.

드디어! AOP에 대해 학습할 시간이다.

 

애플리케이션의 로직은 크게 핵심 기능부가 기능으로 나눌 수 있다.

  • 핵심 기능
    • 해당 객체가 제공하는 고유의 기능이다. 
    • 각 계층에서 수행하는 실제 고유한 로직이다.
  • 부가 기능
    • 핵심 기능을 보조하기 위해 제공되는 기능이다.
    • 로그 추적 로직, 일부 계층에서의 트랜잭션 기능 등이 있다.
    • 부가 기능은 단독으로 사용되지 않는다. 핵심 기능과 버무러져 사용된다.

그런데 만약, 핵심 기능과 부가 기능이 하나의 클래스에 작성되어 있다면?

끔찍하다! 공통된 부가 기능을 여러 클래스에 적용하기 위해 모든 클래스에 직접 부가 기능을 작성해야한다.

또한 부가 기능에 변경사항이 생겼다면..? 마찬가지로 모든 클래스를 변경해야한다.

 

소프트웨어를 개발할 때 변경 지점은 하나가 될 수 있도록 잘 모듈화 되어야 한다.

그러나 부가 기능처럼 특정 로직을 애플리케이션 전반에 적용하는 문제는 일반적인 *객체 지향 프로래밍 방식(OOP)*으로는 해결이 어렵다.

 

그래서 등장한 것이 관점 지향 프로그래밍(Aspect-Oriented-Programming)의 패러다임이다.

- Aspect

고대 개발자들 중 누군가는 이러한 부가 기능의 도입의 문제점들을 해결하기 위해 많은 시간을 고민해왔다.

그 결과 부가 기능을 핵심 기능에서 분리하고 한 곳에서 관리할 수 있도록 만들었다. 

이렇게 부가 기능을 별도로 정의하고, 또한 어디에 적용할지 선택하는 기능을 합해서 하나의 모듈로 만들었는데 이것이 바로 *애스펙트(Aspect)이다.*

애스펙트는 쉽게 이야기해 "어떤 부가 기능을 어디다 적용할거야~" 라고 정의한 것이다.

이전에 알아본 @Aspect 애노테이션이 바로 그 역할이다.

또한 스프링이 제공하는 어드바이저도 어드바이스 + 포인트컷을 가지고있어 개념상 하나의 애스펙트이다.

 

*이렇게 애스펙트를 사용한 프로그래밍 방식을 관점 지향 프로그래밍이라한다.*

AOP는 OOP를 대체하기 위한 것이 아니라, 횡단 관심사를 깔끔하게 처리하기 어려운 OOP의 부족한 부분을 보조하는 목적으로 개발되었따.

횡단 관심사 분리

 

AOP의 대표적인 구현으로 *AspectJ 프레임워크*가 있다. 물론 스프링 스스로도 AOP를 지원하지만 이 역시도 대부분 AspectJ의 문법을 차용하고 실무에 필요한 일부의 기능만 제공한다.

 


2. AOP 적용 방식

AOP를 사용할 때 부가 기능 로직은 어떤 방식으로 실제 로직에 추가될 수 있을까? 크게 세 가지 방법이 있다.

참고로 이렇게 실제 로직에 부가 기능 로직이 추가되는 것을 위빙(Weaving)이라 한다.

- 컴파일 시점

특별한 컴파일러를 사용

아예 코드 컴파일 시점에 실제 코드 자체를 조작해, 부가 기능이 합쳐진 .class 파일을 만드는 방식이다.

그냥 단순하게 되는건 아니고, 컴파일 타임에 AspectJ 컴파일러가 끼어들어 이를 처리해준다.

 

단점으로는 특별한 컴파일러 자체가 필요하다는 것이다.

설정이 번거롭기 때문에 잘 사용하진 않는다.

- 클래스 로딩 시점

바이트 코드 조작기

컴파일 결과로 .class 파일이 만들어지고, JVM 내 클래스 로더에 올라가기 직전에 가로채서 바이트 코드 자체를 조작하는 방식이다.

자바는 기본적으로 .class 파일을 JVM에 저장하기 전에 조작할 수 있는 기능을 제공한다. -> `Java Instrumentation`

수 많은 모니터링 툴이 이 방식을 사용해 개발한다!

 

단점으로는 이 방식도 클래스 로더 조작기를 설정하고, 지정하고 사용해야 하는데 이 과정이 번거롭기 때문에 잘 사용하지 않는다.

- 런타임 시점 (프록시)

프록시 사용

런타임 시점은 컴파일 및 클래스 로더를 통해 클래스 정보도 JVM에 올라가고 메인 메서드가 실행된 이후를 말한다.

위 두 방식은 단점이 많아서 *실제로 스프링도 프록시를 통한 AOP 기능만 제공한다.*

자바 언어가 제공하는 범위 안에서, 스프링과 같은 컨테이너의 도움을 받고 프록시, DI, 빈 후처리기 같은 개념을 총동원해 만든 기술이다.

 

물론 프록시 방식의 AOP도 제약은 있다. 완전히 코드 자체를 조작해버리는 위 방식들과 다르게 프록시를 이용하다보니, final 키워드에 민감하고, 또 생성자의 경우 어찌할 도리가 없다. 오직 부가 기능을 메서드에 적용하는 것에 제한되기 때문이다. -> 메서드 오버라이딩을 통해 구현된다. 

 

하지만 그대로 스프링을 통해 굉장히 편하게 AOP를 사용할 수 있다. 생각해봐라! 자동 프록시 생성기도 스프링이 등록해주는 덕분에 애스펙트만 등록하면 손쉽게 구현할 수 있다.


3. AOP 적용 위치(조인 포인트)

프록시 방식의 AOP를 적용할 때는 당.연.히 특정 메서드를 호출할 때를 기준으로 알아봤었다.

근데 생각해보면 생성자나, 필드나 혹은 static 메서드도 부가 기능을 넣을 수 있지 않겠나?

 

*이렇게 AOP를 적용하는 위치, 즉 적용 가능 지점을 조인 포인트(Join Point)라고 한다.*

AspectJ 프레임워크를 직접 사용해 컴파일 시점, 혹은 클래스 로딩 시점에 적용하는 AOP는 실제 코드를 조작하기 때문에 모든 조인 포인트에 AOP를 적용할 수 있다.

 

하지만 프록시 방식을 사용하는 *스프링 AOP의 조인 포인트는 메서드 실행 시점으로 제한된다.*

또한 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다는 제약도 있다.

 


4. AspectJ vs 스프링 AOP

말만 들어보면 스프링 AOP는 기능에 제약도 많은 것 같고, 그냥 AspectJ 프레임워크를 직접 사용하는게 더 좋아보인다.

그렇지만 프레임워크를 직접 사용하면 설정하는게 너무 까다롭다. 특별한 전용 컴파일러, 전용 문법, 그리고 애플리케이션 실행 옵션도 변경해야한다.

실무에서 운영하는 상황을 고려하면 만만치 않다. 너무 복잡한 것이다!

 

반면 스프링 AOP는 별도의 추가 자바 설정 없이 편리하게 AOP를 사용할 수 있다 (자동 프록시 생성기 등등..)

결정적인 것은, 실무에서는 스프링이 제공하는 AOP 기능만 사용해도 99.99%의 문제가 해결된다!

스프링이 제공하는 AOP 기능만 해도 내용이 많다. 스프링 AOP가 제공하는 기능을 학습하는 것에 집중하자.

 


5. AOP 용어 정리

  • 조인 포인트(Join Point)
    • 어드바이스가 적용될 수 있는 위치
    • 메서드 실행 지점, 생성자 호출 지점, 필드 값 접근, static 메서드 접근 같은 위치
    • 추상적인 개념
    • 스프링 AOP는 프록시 방식을 사용하므로 조인 포인트가 *항상 메서드 실행 지점으로 제한된다.*
  • 포인트컷(Pointcut)
    • 조인 포인트 중에서 어드바이스가 적용될 위치를 필터링하는 기능
    • 주로 AspectJ 표현식을 사용해서 지정
  • 타겟(Target)
    • 어드바이스를 받는 객체, 실제 객체를 의미
  • 어드바이스(Advice)
    • 부가 기능 그 자체
    • 몇 가지 종류가 있음
      1. @Aroud
      2. @Before
      3. @After
      4. 등등
  • 애스펙트(Aspect)
    • 포인트컷 + 어드바이스를 모듈화한 것
    • 하나의 애스팩트 안에 여러 포인트컷과 여러 어드바이스가 함께 존재할 수 있다.
  • 어드바이저(Advisor)
    • 하나의 어드바이스 + 하나의 포인트 컷
    • 스프링 AOP에만 사용되는 특별한 용어
  • 위빙(Weaving)
    • 바느질, 엮는다 이런 뜻
    • 실제로 포인트컷으로 결정한 타겟의 조인 포인트에 어드바이스를 적용하는 것
  • AOP 프록시
    • AOP 기능을 구현하기 위해 만든 프록시 스프링은 JDK 동적 프록시나 CGLIB를 사용

 

 

출처 : 인프런, 김영한의 스프링 핵심 원리 - 고급편