핵심 로직과 부가기능을 분리하고, 부가 기능을 모듈화하여 애플리케이션 전체에 걸쳐 재사용할 수 있도록 하는 프로그램 패러다임
객체지향 프로그래밍(OOP)
비즈니스 로직을 모듈화하여 객체별로 역할을 정의
다수의 객체들에 분산되어 중복적으로 존재하는 공통 관심사가 존재하며, 이것은 프로그램을 복잡하게 만들고, 코드의 변경을 어렵게 한다.

관점지향 프로그래밍(AOP)
객체지향 프로그래밍의 공통 관심사가 중복적으로 존재한다는 문제점을 보완하기 위해 나온 개념
기존 OOP에서 핵심 관심사를 분리하여 프로그램 모듈화를 향상시키는 프로그래밍 스타일
객체 혹은 메소드 별로 필요한 부가적인 기능들을 모듈화, OOP와 함께 적용 가능
AOP는 객체를 핵심 관심사와 횡단 관심사로 분리
핵심 관심사 = 핵심 로직
횡단 관심사(Cross-Cutting Concern) = 부가 기능, 관점(Aspect)이라는 모듈로 정의하고 핵심 관심사와 엮어서 처리

로깅, 보안, 트랜잭션 관리 등이 존재한다.
Spring에서는 @Transactional 어노테이션을 사용하면, 트랜잭션 단위로 묶여서 동작
만약
@Transactional어노테이션이 없었다면 DB와 연동하는 Service 레이어의 모든 메소드마다 아래 코드를 작성해야 됨
@Transactional어노테이션은 메소드마다 필요한 부가 기능(여기서는 트랜잭션 처리)을 모듈화한 것!
class SomeService {
fun doTransaction() {
val tx = em.getTransaction(); //Transaction을 가져옴
tx.begin(); //트랜잭션 시작
...
// DB 관련 로직
...
tx.commit(); //commit해서 트랜잭션 종료
}
}
관점(Aspect)
구현하고자 하는 횡단 관심사의 기능
횡단 관심사(부가기능)를 모듈화한 단위
Advice와 PointCut을 합친 것
충고(Advice)
포인트컷(PointCut)
결합점(JoinPoint)
PointCut의 후보군
Aspect가 적용될 수 있는 위치
메소드가 호출되는 시점, 클래스의 생성자가 호출되는 시점, exception이 발생하는 시점, argument로 넘어오는 시점 등 애플리케이션 코드 내의 어디든지 적용이 가능
엮기(Weaving)
관점(Aspect)을 실제 코드에 적용하는 과정을 나타낸 것
Compile-time Weaving
AOP가 적용되어 있는 지 확인하고, 컴파일 시점에 AOP가 적용된 클래스로 바꿔주는 방법 (클래스 자체를 변경)
예를 들어 Service 클래스 내부의 어떤 메소드 위에 @Transactional을 붙였다고 가정함. 컴파일 시점에 컴파일러가 검사를 하다가@Transactional을 확인하면 Service 클래스를 doTransaction()이 포함된 클래스로 바꿔줌
Load-time Weaving
Java 기반 프로그램은 컴파일 후, 클래스 자체를 로딩하는 시점이 존재
이때 클래스가 자바 가상 머신이 이해할 수 있는 Byte Code라는 것으로 변경됨
JVM이 클래스를 로딩할 때 해당 클래스의 Byte Code를 변경하여 원본 클래스를 바꾸지 않고, AOP를 적용
Run-time Weaving
컴파일시점이나 로딩 시점 전부 아무 짓도 안 함
애플리케이션이 실행될 때 프록시 객체를 사용하여 실제 객체에 접근
예를 들어 Service 클래스 내부의 어떤 메소드 위에 @Transactional을 붙였다고 가정함. 런타임 시점에 @Transactional 역할을 수행할 프록시라는 가짜 객체가 생성됨. Controller에서 Service 레이어에 접근할 때 @Transactional 역할을 담당하는 프록시 객체를 통해 Transactional 기능을 수행한 후, Service 클래스로 접근함

AOP 프록시(Proxy)
대상 객체(Target Object)에 Advice가 적용된 후 생성되는 객체
실제 객체에 접근할 때 사용할 부가기능이 정의되어 있는 가짜 객체
대상 객체(Target Object)
쉽게 말해 AOP란 부가 기능을 모듈화하고, 내 애플리케이션 코드 중에 적용할 부분을 찾아 적용하는 것!
대표적으로 Spring AOP와 AspectJ로 나뉜다.
두 프레임워크의 가장 큰 차이점은 실제 코드에 적용하는 방법(Weaving)이 다르다는 것이다!
Run-time Weaving만 지원
런타임 때 프록시를 만들고, 이 프록시를 거쳐가며 동작하기 때문에 오버헤드가 존재 (시간이 더 걸린다.)
일반 메소드만 JoinPoint로 사용할 수 있다.
항상 프록시에 해당하는 클래스를 만들어야 한다.
이때 Aspect를 적용하려는 Class가 final class일 경우(상속을 받을 수 없는 클래스일 경우) Aspect를 적용할 수 없다.
Java의 final 또는 static method에도 적용되지 않는다.
Aspect를 적용할 때 Spring에서 관리하는 Bean에만 적용이 가능하다.
Spring AOP는 AOP를 간단하게 만들겠다는 것이 목표이기 때문에 특정 경우에만 사용이 가능하다.
프록시 객체를 만들게끔 Aspect를 정의하면 끝남
일반 메소드만 가능 Bean에서만 동작 가능
Compile Time Weaving과 Load-time Weaving을 지원
컴파일 또는 클래스를 로딩할 때 미리 만들기 때문에 Spring AOP에 비해 8~35배 정도 빠르다.
클래스를 변경하거나 Byte Code를 변경하기 때문에 모든 부분에 JoinPoint를 적용할 수 있다. (어디든지 Aspect를 적용할 수 있다.)
AspectJ는 컴파일 시점에 할지, 클래스를 로드할 때 할지 결정해야하기 때문에 별도의 컴파일러나 weaver가 필요하므로, Spring AOP에 비해 복잡하다.
https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:fdl:aop