AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 공통된 기능(로깅, 트랜잭션, 보안 등)을 분리하여 코드의 중복을 줄이고 유지보수를 용이하게 하는 기법이다.
Spring에서는 Spring AOP를 통해 AOP 기능을 지원한다.
Spring AOP에서는 다음과 같은 핵심 개념이 존재한다.
Aspect (관점, 단면)
Advice (충고, 기능 구현부)
Pointcut (접점, 적용 위치 설정)
JoinPoint (연결 지점)
Weaving (위빙)
Spring Boot 프로젝트에서 AOP를 사용하려면 spring-boot-starter-aop 의존성을 추가해야 한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeMethodExecution(JoinPoint joinPoint) {
System.out.println("[Before] 메서드 실행: " + joinPoint.getSignature().getName());
}
@AfterReturning("execution(* com.example.service.*.*(..))")
public void afterReturningMethod(JoinPoint joinPoint) {
System.out.println("[AfterReturning] 메서드 성공: " + joinPoint.getSignature().getName());
}
@AfterThrowing("execution(* com.example.service.*.*(..))")
public void afterThrowingMethod(JoinPoint joinPoint) {
System.out.println("[AfterThrowing] 예외 발생: " + joinPoint.getSignature().getName());
}
}
@Before : 메서드 실행 전에 실행됨@AfterReturning : 메서드가 정상적으로 실행된 후 실행됨@AfterThrowing : 예외 발생 시 실행됨@Pointcut("execution(* com.example.service.UserService.*(..))")
public void userServiceMethods() {}
execution(* 패키지명.클래스명.메서드명(..)) 형식으로 특정 메서드에 적용 가능@Before("userServiceMethods()")
public void logBeforeUserServiceMethods(JoinPoint joinPoint) {
System.out.println("[Before] UserService 메서드 호출: " + joinPoint.getSignature().getName());
}
@Pointcut을 활용하여 여러 곳에서 공통적으로 사용할 수 있음@Transactional을 통한 트랜잭션 관리Spring AOP를 사용하면 코드의 중복을 줄이고 로깅이나 트랜잭션 관리 같은 공통 관심 사항을 분리할 수 있어 유지보수가 편리하다. 특히 @Transactional처럼 자동으로 트랜잭션을 관리해 주는 기능도 AOP 기반이라는 점이 흥미로웠다.
AOP 남용 시 코드가 복잡해질 수 있으므로 적절한 범위에서 적용하는 것이 중요하다는 점을 다시 한번 느꼈다.