AOP (Aspect Oriented Programming, 관점 지향 프로그래밍)는 OOP의 한계를 보완하는 프로그래밍 패러다임이다. OOP는 주로 '기능' 단위로 클래스를 구현하고, AOP는 '공통 관심사' (로깅, 트랜잭션 처리, 보안, 성능 측정, etc.)를 모듈화하여 코드 중복을 줄이고 유지보수가 쉽도록 구현한다.
별도 설정 없이 spring-boot-starter-aop 의존성만 추가하면 바로 사용할 수 있다. 선언적 AOP를 지원하여, @Aspect 어노테이션 기반으로 Aspect 작성, Pointcut, Advice 선언이 가능하다.
| 어노테이션 | 역할 |
|---|---|
@Aspect | 해당 클래스가 Aspect임을 선언 |
@Before | 메서드 실행 전에 Advice 실행 |
@After | 메서드 실행 후에 Advice 실행 |
@AfterReturning | 메서드 정상 실행 후 Advice 실행 |
@AfterThrowing | 예외 발생 후 Advice 실행 |
@Around | 메서드 실행 전후 모두 Advice 실행 |
execution(* com.example.domain.*Service.find*(..))
/* execution: 지시자
* *: 반환값
com.example.domain: 패키지
*Service: 클래스 (타입)
.find*: 메서드
(..): 파라미터
*/
execution(* com.example.user.*.*(..)): user 패키지 아래의 모든 클래스의 전체 메서드 대상, 모든 반환값 유형
execution(* com.example.user.UserService.*(..)): user 패키지 아래 UserService 클래스의 전체 메서드 대상
execution(* com.example.user.UserService.find*(..)): user 패키지 아래 UserService 클래스에서 find로 시작하는 메서드 대상
execution(String com.example.user.UserService.*(..)): user 패키지 아래 UserService 클래스에서 반환값이 String인 메서드 대상
✏️ Spring의 Proxy
Spring 컨테이너가 빈 (원본 객체) 대신 프록시 객체를 생성하여 외부에서는 원본처럼 보이지만, 부가기능 (AOP, 트랜잭션, etc.)을 자동으로 추가할 수 있도록 만든다.동작 방식
- Bean 등록 시점에 프록시 객체가 실제 객체 대신 컨테이너에 등록된다.
- 클라이언트가 Bean을 사용할 때 프록시가 먼저 실행한다.
- 전처리 (Advice) 실행
- 실제 원본 메서드 호출
- 후처리 (Advice) 실행
- 결과 반환