티스토리 뷰
https://www.baeldung.com/spring-aop-vs-aspectj
글을 번역 한 후 몇가지 부분을 제거하고 수정했습니다. 원본을 보고 싶을경우 원본 문서를 확인 부탁드립니다.
1. 관점 지향 프로그래밍(AOP; Aspect-OrientedProgramming)란
- 문제를 바라보는 관점을 기준으로 프로그래밍 하는 기법
- 공통 관심사(crosscuttinh concerns, 애플리케이션 내 코드가 중복되고 강력하게 결합되어있는 로직)를 구현하는 툴
- AOP를 사용하여 개별 로직(관심사, concerns)들을 모듈화하고 코드를 복제하거나 의존성을 만들지 않고도 이러한 개별 로직을 애플리케이션의 여러 영역에 적용할 수 있음.
2. AOP 개념
용어 | 의미 |
Aspect | 여러 객체에 공통으로 적용되는 기능 애플리케이션의 여러 위치에 흩어져 있고 일반적으로 실제 비즈니스 로직과는 다른 표준 코드/기능(ex. 트랜잭션 관리, 보안) 각 Aspect는 특정 cross-cutting(공통 사항) 기능에 중점을 둡니다. |
Pointcut | 조인포인트의 부분 집합으로. 조인 포인트가 포인트컷과 일치할 때마다 해당 포인트컷과 관련된 지정된 Advice가 실행됩니다. |
Advice | 언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의. (ex. ‘메서드 호출하기 전’(언제)에 ‘트랙잭션 시작’(공통 기능) 기능을 적용) |
Joinpoint | 메서드 실행, 생성자 호출 또는 필드 할당과 같은 Advice를 적용 할 수 있는 특정 지점입니다. |
Weaving | Advice를 핵심 로직 코드에 적용하는 것. |
3. 스프링 AOP와 AspectJ
이제 기능, 목표, weaving, 내부 구조, 결합 지점 및 단순성과 같은 여러 항목에 걸쳐 Spring AOP 및 AspectJ에 대해 논의해 보겠습니다.
3.1. 기능 및 목표
간단히 말해서 Spring AOP와 AspectJ는 목적이 다릅니다.
Spring AOP는 프로그래머가 직면하는 가장 흔한 문제를 해결하기 위해 Spring IoC 전반에 걸쳐 간단한 AOP 구현을 제공하는 것을 목표로 합니다. 완전한 AOP 솔루션으로 의도된 것이 아닙니다. Spring 컨테이너에 의해 관리되는 빈에만 적용할 수 있습니다.
반면 AspectJ는 완전한 AOP 솔루션을 제공하는 것을 목표로 하는 독창적인 AOP 기술입니다. Spring AOP보다 강력하지만 훨씬 더 복잡합니다. AspectJ가 모든 도메인 객체에 적용될 수 있다는 점도 주목해 볼 필요가 있습니다.
3.2. Weaving
AspectJ와 Spring AOP는 성능/유용성에 따라 서로 다른 유형의 Weaving을 사용합니다.
- 컴파일 시 weaving
- 컴파일 방식에서는 핵심 로직을 구현한 자바 소스 코드를 컴파일 할 때, 알맞은 위치에 공통 코드를 삽입하면, 컴파일 결과 AOP가 적용된 클래스 파일이 생성된다.
- 컴파일 방식을 제공하는 AOP 도구는 공통 코드를 알맞은 위치에 삽입할 수 있도록 도와주는 컴파일러나 IDE를 함께 제공한다.
- AspectJ에서 지원하는 방식이다.
- 클래스 로딩 시 weaving
- AOP 라이브러리는 JVM이 클래스를 로딩할 때 클래스 정보를 변경할 수 있는 에이전트를 제공한다.
- 이 에이전트는 로딩한 클래스의 바이너리 정보를 변경하여 알맞은 위치에 공통 코드를 삽입한 새로운 클래스 바이너리 코드를 사용하도록 한다.
- 즉, 원본 클래스 파일은 변경하지 않고 클래스를 로딩할 때에 JVM이 변경된 바이트 코드를 사용하도록 함으로써 AOP를 적용한다.
- 이 방식 또한 AspectJ에서 지원하는 방식이다.
- 런터임 시 weaving
- 원본 소스 코드나 클래스 정보 자체를 변경하지 않는점에서 클래스 로딩 waving과 유사하지만, 클래스 로더가 클래스 파일을 JVM에 로드할 때까지 weaving이 연기된다는 차이점이 있습니다.
- 프록시를 이용하여 AOP를 적용합니다.
- 프록시 기반의 AOP는 핵심 로직을 구현한 객체에 직접 접근하는 것이 아니라 중간에 프록시를 생성하여 프록시를 통해서 핵심 로직을 구현한 객체에 접근하게 된다.
- 프록시는 핵심 로직을 실행하기 전 또는 후에 공통 기능을 적용하는 방식으로 AOP를 구현한게 된다.
- 프록시 기반에서는 메서드가 호출될 떄에만 Advice를 적용할 수 있기 때문에 필드값 변경과 같은 Joinpoint에 대해서는 적용할 수 없는 한계가 있다.
- JDK 동적 프록시 또는 CGLIB 프록시를 사용하여 대상 객체의 프록시를 사용하여 애플리케이션을 실행하는 동안 ASPECT가 woven됩니다.
3.3 내부 구조 및 Application
Spring AOP는 프록시 기반 AOP 프레임워크입니다. 이는 대상 개체에 aspects를 구현하기 위해 해당 개체의 프록시를 생성을 한다는 것을 의미 합니다. 이는 다음 두 가지 방법 중 하나를 사용하여 수행됩니다.
- JDK 동적 프록시 : Spring AOP에서 선호 하는 방식. 대상 객체가 하나의 인터페이스를 구현할 때마다 JDK 동적 프록시가 사용됩니다.
- CBLIB 프록시 : 대상 객체가 인터페이스를 구현하지 않았다면 CGLIB 프록시를 사용합니다.
반면 AspectJ는 클래스가 aspect로 직접 컴파일되기 때문에 런타임에 아무 것도 하지 않습니다.
따라서 Spring AOP와 달리 디자인 패턴이 필요하지 않습니다. Aspect를 코드에 weave 하기 위해 AspectJ 컴파일러 (ajc)로 알려진 컴파일러를 도입합니다. 이를 통해 프로그램을 컴파일한 다음에 작은(< 100k) 런타임 라이브러리를 제공하여 프로그램을 실행합니다.
3.4 JointPoint
3.3절에서 우리는 Spring AOP가 프록시 패턴을 기반한다는것을 봤습니다. 이 때문에 대상 Java 클래스를 subclass화하고 횡단 관심사(crosscutting concerns)를 적용해야합니다.
하지만 한계가 따릅니다. ‘final’ 클래스는 횡단 관심사(또는 aspect)를 적용할수 없습니다. final class는 재정의 할수 없기때문에 런타입 예외가 발생되기 때문입니다.
그러나 AspectJ의 weave는 런타입 전에 실제 코드에 직접 횡단 관심사를 입력합니다. Spring AOP와 달리 대상 객체를 서브클래싱화할 필요가 없으므로 다른 많은 JointPoint를 지원합니다.
Spring AOP에서는 동일한 클래스 내에서 호출(self-invocation)되는 메서드에 aspect가 적용되지 않는다는 점도 주의깊게 봐야한다.
Joinpoint | Spring AOP Supported | AspectJ Supported |
Method Call | No | Yes |
Method Execution | Yes | Yes |
Constructor Call | No | Yes |
Constructor Execution | No | Yes |
Static initializer execution | No | Yes |
Object initialization | No | Yes |
Field reference | No | Yes |
Field assignment | No | Yes |
Handler execution | No | Yes |
Advice execution | No | Yes |
동일한 클래스 내에서 메서드를 호출할 때 Spring AOP가 제공하는 프록시의 메서드를 호출하지 않기 때문이다. 이 기능이 필요하면 다른 빈에서 별도의 메소드를 정의하거나 AspectJ를 사용해야합니다.
3.5 Simplicity
Spring AOP는 빌드 프로세스 사이에 추가 컴파일러나 weaver는 도입하지 않기때문에 좀 더 간단하게 사용할수 잇습니다. 런타임 위빙을 사용하므로 일반적인 빌드 프로세스와 원활하게 통합됩니다. 단순해 보이지만 Spring에서 관리하는 Bean에서만 작동합니다.
그러나 AspectJ를 사용하려면 AspectJ 컴파일러(ajc)를 도입하고 모든 라이브러리를 다시 패키징해야합니다. (post-compiler 나 load-time-compiler로 전환하지 않는한)
물론 이것은 이전보다 더 복잡합니다. AspectJ java 도구(컴파일러(ajc), 디버거(ajdb), 문서 생성지(ajdoc), 프로그램 구조 브라우저(ajbrowser) 포함)을 도입했기 때문입니다. IDE 또는 빌드 도구와 통합해야합니다.
3.6 성능
성능에 관해서는, compile-time 위빙은 runtime 위빙보다는 훨씬 빠릅니다. Spring AOP는 프록시 기반 프레임워크이므로 애플리케이션 시작 시 프록시 생성이 있다. 또한 ASPECT 당 몇가지 메서드 호출이 더 있다면 성능에 부정적인 영향을 미칩니다.
반명 AspectJ는 애플리케이션이 실행되기 전에 Aspect를 메인 코드에 weaves하므로 Spring AOP와 달리 추가적인 런타임 오버 헤드가 발생지 않는다.
이러한 이유로 벤치마크는 AspectJ가 Spring AOP보다 거의 8~35배 빠르다고 말한다.
4. 요약
Spring AOP | Spring AOP |
순수 자바로 구현 | JAVA 프로그래밍 언어의 extensions을 사용하여 구현 |
별도의 컴파일 과정이 필요 없음 | LTW가 설정되지 않은 경우 AspectJ 컴파일러(ajc)가 필요 |
runtime 위빙만 가능 | runtime 위빙 사용 불가능, compile-time, post-compile, load-time 위빙 지원 |
덜 강력함 - 메서드 레벨 위빙만 지원 | 더 강력함 - 필드, 메서드, 생성자 등등 위빙 지원 |
Spring 컨테이너가 관리하는 Bean에서만 구현 가능 | 모든 도메인 객체에서 구현 가능 |
메소드 실행 포인트컷만 지원 | 모든 포인트컷 지원 |
프록시는 대상 객체로 생성되고 aspects 는 이러한 프록시에 적용됩니다. | aspects는 애플리케이션이 실행되기 전에(런타임 전에) 코드에 직접 weaved됩니다. |
AspectJ보다 훨씬 느림 | 더 나은 성능 |
배우기 쉽고 적용하기 쉬움 | Spring AOP보다 비교적 복잡함 |
5. 올바른 프레임워크 선택
사용자의 요구사항에 따라 나눠집니다.
- 프레임워크
- 애플리케이션에 스프링 프레임워크을 적용하지 않았을 경우, Spring AOP는 스프링 컨테이너의 범위 밖에 있는 모든 것들을 관리할수 없기 때문에 사용할수 없다.
- 그러나 스프링 프레임워크를 사용하는 애플리케이션이라면, Spring AOP를 쉽게 배울수 있고 적용할수 있기 때문에 사용하기에 좋다.
- 유연성(Flexibility)
- 제한된 조인포인트 지원을 감안한다면 Spring AOP는 완전한 AOP 솔루션은 아니지만 프로그래머가 직면하는 가장 일반적인 문제를 해결해줍니다.
- AOP를 최대한 활용하고 다양한 조인포인트를 원할 경우 AspectJ를 선택하면 된다.
- 성능
- 제한된 Aspect를 사용하는 경우 사소한 성능 차이가 있습니다.
- 그러나 응용 프로그램에 수만개 이상의 ASPECT를 사용하고 있는 경우 런타임 위빙을 사용하는 것보다는 AspectJ를 사용하는 것이 더 좋다.
- AspectJ는 Spring AOP보다 8~35배 빠른것으로 알려져 있기 떄문.
- 각각의 장점
- 이 두 프레임워크는 서로 완벽하게 호환됩니다.
- 가능하다면 Spring AOP를 사용하고 지원되지 않는 조인포인트에서는 ApectJ를 활용하자.
'[Spring Framework]' 카테고리의 다른 글
[Spring] Spring 애플리케이션에서 테스트하기 (1) | 2022.09.23 |
---|---|
[Spring] Swagger 한글 깨짐 (0) | 2021.03.10 |
[Spring] Swagger 사용법 (0) | 2021.03.10 |
[Spring] loadUserByUsername의 username이 null인 경우. (0) | 2020.12.17 |
[spring] private와 inner method에서의 spring trasaction 동작 (0) | 2019.05.22 |
- Total
- Today
- Yesterday
- gradle
- sgw
- JetBrains Mono
- spring
- java
- Mockito
- junit5
- 한글깨짐
- aspectj
- Jenkins
- ThreadPool
- IntelliJ
- Executor
- chmod
- codepoint
- spring-security
- 확인창
- jdk13
- 파스칼 표기법
- 카멜 표기법
- Visual Studio 2022
- thread priority
- Redis
- JAVA8
- JUnit
- Thread
- java11
- hot-deploy
- JPA
- jdk12
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |