
AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 핵심 비즈니스 로직과 공통적인 기능(로깅, 트랜잭션, 보안 등)을 분리하여 모듈화하는 프로그래밍 기법이다.
OOP(객체 지향 프로그래밍)와 함께 사용되며, 여러 객체에서 공통으로 적용해야 하는 기능을 따로 관리할 수 있도록 한다.
Spring 기반의 애플리케이션을 개발할 때, 여러 클래스에서 반복적으로 사용되는 기능이 있다.
예를 들어, 로그 기록, 권한 체크, 트랜잭션 관리 등의 기능은 여러 서비스 로직에서 공통적으로 필요하다.
이러한 공통 기능을 모든 클래스에 직접 작성하면 코드의 중복이 증가하고 유지보수가 어려워진다.
AOP는 이러한 문제를 해결하기 위해 공통 기능을 하나의 모듈(Aspect)로 분리하여 관리할 수 있도록 도와준다.
| 용어 | 설명 |
|---|---|
| Aspect | 공통 기능을 정의한 모듈 (예: 로깅, 트랜잭션) |
| Join Point | AOP가 적용될 수 있는 모든 지점 (메서드 실행, 예외 발생 등) |
| Pointcut | Advice가 적용될 지점을 정의하는 표현식 |
| Advice | Aspect에서 수행할 코드 (Before, After 등) |
| Weaving | Aspect를 핵심 로직에 적용하는 과정 |
AOP는 크게 컴파일 시 적용, 런타임 시 프록시를 이용한 적용 방식이 있다.
Spring AOP는 런타임 시 프록시(Proxy)를 생성하여 AOP를 적용하는 방식을 사용한다.
spring-boot-starter-aop를 추가해야 한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeMethodExecution() {
System.out.println("메서드 실행 전 로그 기록");
}
}
import org.springframework.stereotype.Service;
@Service
public class SampleService {
public void execute() {
System.out.println("비즈니스 로직 실행");
}
}
실행 결과
메서드 실행 전 로그 기록
비즈니스 로직 실행
→ AOP가 적용되어, execute() 메서드 실행 전에 로그가 출력된다.
| Advice 종류 | 설명 | 예제 |
|---|---|---|
| @Before | 메서드 실행 전에 실행됨 | @Before("execution(* com.example.service.*.*(..))") |
| @After | 메서드 실행 후 실행됨 | @After("execution(* com.example.service.*.*(..))") |
| @AfterReturning | 메서드가 정상적으로 실행된 후 실행됨 | @AfterReturning("execution(* com.example.service.*.*(..))") |
| @AfterThrowing | 메서드 실행 중 예외 발생 시 실행됨 | @AfterThrowing("execution(* com.example.service.*.*(..))") |
| @Around | 메서드 실행 전후를 감싸서 실행 | @Around("execution(* com.example.service.*.*(..))") |
| 장점 | 단점 |
|---|---|
| 공통 기능을 분리하여 코드 중복 감소 | 프록시 방식으로 인한 성능 오버헤드 |
| 핵심 로직과 부가 기능을 분리하여 유지보수 용이 | 잘못된 AOP 설정으로 디버깅이 어려울 수 있음 |
| 비즈니스 로직을 간결하게 유지 가능 | 적용 범위를 설정하지 않으면 불필요한 곳에서도 실행될 위험 |