배경
위의 그림과 같이 프로그램을 작성하다 보면 로깅, 보안 등 공통적으로 나타나는 기능들이 있다. 예를들어 DB커넥션을 할때 DB 커넥션을 연결하고, Statement객체를 세팅하고 쿼리문을 실행하고 예외처리를 실행하는데 이때 DB연산을 제외한 코드는 어떤 데이터베이스 연산을 하든 공통적으로 나타나는 코드이다. 이렇든 코드는 횡단관심사 + 핵심관심사로 이루어져 있는데 이런 횡단 관심사를 따로 분리해서 한 곳에서 관리 하는것을 AOP라고 한다.
상세
이때 어떤 횡단 관심사를 언제 어디에 사용할까? 라는 의문점이 생기게 되는데 이때 나온 개념이 Advice, JointPoint, PointCut이다.
간단하게 각각 무엇인지 살펴보자
Advice
어떤 부가기능을 언제 사용할지에 대한 정의이다.
종류로는 다음과 같이 있다.
- @Before
코드가 실행되기 전 - @After
코드가 실행된 후 - @AfterReturning
코드가 정상적으로 실행된 후 - @AfterThrowing
코드가 예외를 발생시킨 후 - @Around
코드가 실행되기 전후
JointPoint
Advice를 적용시킬 위치이다.
메소드를 호출할때, 변수에 접근할때, 객체를 초기화할 때, 객체에 접근할 때 등 AOP가 적용되는 위치를 JointPoint라고 하는데 스프링 AOP는 메소드를 호출할 때만 적용한다.
Pointcut
Advice를 적용할 JointPoint를 선별하는 작업이다.
예를들어 signUp메소드 수행시 시간측정을 하는 부가기능을 사용하고 싶을 때 siginUp메소드만을 지정해주어 Advice를 적용시킬 수 있다.
Target
부가기능이 적용될 대상이다.
위의 Pointcut의 예시에서 signUp 메소드만이 Adivce가 적용이 되어 signUp 메소드가 Target이 된다.
AOP의 구현 방법
위에서 말한 AOP를 적용하는 것을 Weaving이라고 한다.
weaving을 적용하는 방법은 다음과 같은데 하나씩 살펴보자
컴파일 타임 위빙
AspectJ라는 특수한 컴파일러가 Aspect코드와 Base코드를 입력받아 Weaving클래스를 생성한다.
런타임 위빙(프록시 패턴)
실제 런타임상에서 method 호출시 위빙이 이루어지는 것이다. (Source file, class 파일에도 변화가 없다.) 타겟 클래스의 프록시를 생성하여 비즈니스 코드와 Advice가 포함된 메소드를 호출하는 방식이다. 실제 Spring AOP 에서 이 방식을 사용하고 있다.
JDK Dynamic Proxy & CGLIB Proxy
이때 Spring에서는 자동으로 Target의 프록시 객체를 생성해 주는데, JDK Proxy(Dynamic Proxy)와 CGLib Proxy를 만들 수 있다.
두 방식의 가장 큰 차이점은 Target의 어떤 부분을 상속 받아서 프록시를 구현하느냐에 있다.
- JDK Dynamic Proxy
- 프록시 팩토리에 의해 런타임 시 다이나믹하게 만들어지는 오브젝트
- 프록시 팩토리에게 인터페이스 정보만 제공해주면 해당 인터페이스를 구현한 클래스 오브젝트를 자동으로 생성
- 따라서 인터페이스가 반드시 존재해야 하며, 부가기능 코드를 직접 작성 - CGLib Proxy
- 클래스 상속을 이용하여 생성하기 때문에 인터페이스가 존재하지 않아도 가능
- 또한 JDK Proxy는 내부적으로 Reflection을 사용해서 추가적인 비용이 들지만, CGLib는 그렇지 않음.
- 여러 성능 상 이점으로 인해 Spring Boot에서는 CGLib를 사용한 방식을 기본으로 채택
로드타임 위빙
클래스가 JVM에 로드되는 시점에때 advice가 위빙이 되는 것을 말한다.
마치며
public class ex {
public void intit() {
this.move():
}
@Transactional
public void move() {
}
}
위의 코드와 같이 스프링 프로젝트를 진행하던 중 일반 메소드 내에 트랜잭션 어노테이션이 걸린 메소드를 넣었는데, 트랜잭션이 작동하지 않았다. AOP와 관련된 문제임을 깨닫고 AOP에 대해서 공부하며 정리할 겸 글을 쓰며 다음 글에서 트랜잭션과 AOP를 좀 더 다뤄볼 예정이다.
'Spring' 카테고리의 다른 글
Spring Security 1: Spring Security (0) | 2023.08.02 |
---|---|
Servlet과 Spring MVC (0) | 2023.03.06 |
Spring vs Spring boot (0) | 2022.11.09 |
Maven & Gradle (0) | 2022.11.08 |
BeanFactory & ApplicationContext (0) | 2022.11.08 |