Spring Framework Documentation에서 Spring AOP가 완벽한 AOP 구현을 제공하는 것을 목표로 삼고 있지 않는다는 표현과 함께 AspectJ와의 상호 보완적인 관계로써 활용한다라고 명시를 하고 있습니다. Spring AOP와 AspectJ는 어떠한 차이를 갖기에 상호 보완적인 관계로써 활용한다는 것일까요?
Spring AOP: Spring AOP는 pure Java로 구현되어 특별한 컴파일 프로세스를 사용하지 않고 런타임에서 Weaving을 진행합니다. 런타임 과정에서 AOP를 구현하기 위해서 AOP Proxy를 사용합니다.
AspectJ: AspectJ는 Java 언어의 확장 기능을 사용하여 구현되어 AspectJ를 위한 Compiler가 사용됩니다. 이에 따라서 AspectJ는 3가지 유형의 Weaving을 활용할 수 있습니다.
.class
파일과 .jar
파일 기반의 Weaving 진행하기.class
파일을 JVM에 로드할 때 Weaving 진행하기정리하자면 Spring AOP는 런타임에서 Weaving을 AspectJ는 컴파일 및 클래스 로드 시간에 Weaving을 한다는 점에서 차이가 존재합니다.
Spring AOP는 오로지 Spring Bean에서의 메서드 실행에 대한 Join Point만 지원하며 필드 참조나 할당에 대한 지원은 AspectJ를 사용하라고 안내하고 있습니다. 프레임워크에 따른 사용 가능한 Join Point를 열거해보면 아래 표와 같습니다.
Join Point | Spring AOP | AspectJ |
---|---|---|
메서드 호출 | No | Yes |
메서드 실행 | Yes | Yes |
생성자 호출 | No | Yes |
생성자 실행 | No | Yes |
정적 초기화 실행 | No | Yes |
객체 초기화 | No | Yes |
필드 참조 | No | Yes |
필드 할당 | No | Yes |
핸들러 실행 | No | Yes |
어드바이스 실행 | No | Yes |
왜 Spring AOP가 메서드 실행에 대한 Join Point만을 지원할 수 있는지 생각해보면 런타임에서 Weaving을 실행하기 때문에 Proxy를 활용한 우회로써만 AOP 구현이 가능하다는 점을 생각해보면 이해할 수 있습니다. AspectJ는 Compile 및 Class Loader 과정에서 AOP를 구현할 수 있으므로 부가적인 기능을 모든 곳에 추가할 수 있지만 Spring AOP는 오로지 런타임에서만 동작하기 때문에 메서드 실행에서 제한적으로 사용이 가능합니다.
당연히 컴파일 단계에서의 Weaving을 진행하는 AspectJ가 런타임 단계에서 Weaving을 진행하는 Spring AOP보다 빠릅니다. Spring AOP의 경우 애플리케이션이 시작할 때 프록시가 생성되는 과정이 추가로 필요하기 때문입니다.
밴치마크에 따르면 AspectJ가 Spring AOP보다 8~35배 정도의 속도 차이를 보인다는 것을 알 수 있습니다.
Spring AOP는 Spring IoC에 특화된 AOP로써 Spring Bean 객체에 대한 Advice와 같은 작업에 대해서 쉽고 효율적으로 사용하고자 구현되었음을 알 수 있었습니다.
포괄적이고 강력한 AOP를 구현하고자 한다면 AspectJ를 사용해아 한다는 것과 Spring AOP와 AspectJ를 잘 융합해서 활용하면 상황에 맞는 AOP를 구현할 수 있다는 점을 확인할 수 있었습니다.
Spring은 Documentation에서 아래와 같은 문장을 남겼습니다.
One of the central tenets of the Spring Framework is that of non-invasiveness. This is the idea that you should not be forced to introduce framework-specific classes and interfaces into your business or domain model.
Spring에서 목표하고자 하는 바인 non-invasiveness(비침습성)은 비즈니스 또는 도메인 모델에 프레임워크 전용 클래스 및 인터페이스의 강제 도입은 있어서는 안된다.
전용 클래스나 인터페이스의 강제 도입을 원하지 않기에 Runtime에서만 AOP를 활용하는 방식을 고집하지 않았을까? 라는 생각을 해보게 됬습니다.