Spring AOP(Aspect-Oriented Programming)의 핵심 개념을 알아보고, 실제 프로젝트에서 어떻게 활용할 수 있는지 예시 코드와 함께 살펴봅니다.
애플리케이션을 개발하다 보면 로깅, 보안, 트랜잭션 관리 등 여러 모듈에서 공통적으로 사용되는 기능들이 발생하는데요, 이러한 기능들을 횡단 관심사라고 부릅니다. 이러한 횡단 관심사를 각 모듈에 흩뿌려놓으면 코드 중복이 심해지고 유지보수가 어려워지는 문제가 발생합니다.
java public class UserService {
public void createUser(User user) {
// 로깅 시작
System.out.println("Creating user: " + user.getName());
// 핵심 로직
// ... 사용자 생성 로직 ...
// 로깅 종료
System.out.println("User created successfully.");
}
public void updateUser(User user) {
// 로깅 시작
System.out.println("Updating user: " + user.getName());
// 핵심 로직
// ... 사용자 업데이트 로직 ...
// 로깅 종료
System.out.println("User updated successfully.");
}
}
위 코드처럼 로깅 코드가 createUser와 updateUser 메서드에 반복적으로 나타나는 것을 볼 수 있습니다. AOP를 사용하면 이러한 중복을 제거하고 핵심 로직에 집중할 수 있게 됩니다.
AOP는 횡단 관심사를 모듈화하여 핵심 로직에서 분리하고, 필요한 시점에 적용할 수 있도록 해주는 프로그래밍 패러다임입니다. Spring Framework는 AOP를 효과적으로 지원하며, 개발자는 AOP를 통해 코드의 재사용성을 높이고 유지보수를 용이하게 할 수 있습니다.
| 항목 | 설명 | 예시 |
|---|---|---|
| Aspect (애스펙트) | 횡단 관심사를 모듈화한 것. 어드바이스와 포인트컷을 포함합니다. | 로깅, 보안, 트랜잭션 관리 |
| Advice (어드바이스) | 실제로 수행되는 기능. 횡단 관심사에 해당하는 코드를 담고 있습니다. | 로깅 코드, 보안 검사 코드, 트랜잭션 시작/종료 코드 |
| Pointcut (포인트컷) | 어드바이스를 적용할 위치를 지정하는 표현식. | 특정 메서드 실행 전, 특정 예외 발생 시 |
| Join point (조인 포인트) | 어드바이스가 적용될 수 있는 지점. 메서드 실행, 예외 발생 등. | 메서드 실행 시점, 필드 접근 시점 |
| Weaving (위빙) | 애스펙트를 핵심 로직에 적용하는 과정. 컴파일 시, 클래스 로딩 시, 런타임 시에 수행될 수 있습니다. |
먼저, Spring AOP를 사용하기 위해 pom.xml 또는 build.gradle 파일에 AOP 관련 의존성을 추가해야 합니다.
xml
org.springframework.boot spring-boot-starter-aop
gradle // build.gradle dependencies { implementation 'org.springframework.boot:spring-boot-starter-aop' }
@Aspect 어노테이션을 사용하여 Aspect 클래스를 정의합니다. 이 클래스에는 Advice와 Pointcut이 정의됩니다.
java import org.aspectj.lang.JoinPoint; 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 logBefore(JoinPoint joinPoint) {
System.out.println("Method " + joinPoint.getSignature().getName() + " will be executed.");
}
}
@Aspect: 이 클래스가 Aspect임을 나타냅니다.@Component: Spring Bean으로 등록합니다.@Before: execution(* com.example.service.*.*(..)) 포인트컷에 지정된 메서드가 실행되기 전에 logBefore 메서드를 실행합니다.
execution(* com.example.service.*.*(..))는 com.example.service 패키지 안의 모든 클래스의 모든 메서드를 의미합니다.Spring AOP는 다양한 Advice 종류를 제공합니다.
@Before: 조인 포인트 실행 전에 실행됩니다.@After: 조인 포인트 실행 후에 실행됩니다 (성공, 실패 여부와 관계없이).@AfterReturning: 조인 포인트가 정상적으로 완료된 후에 실행됩니다.@AfterThrowing: 조인 포인트에서 예외가 발생했을 때 실행됩니다.@Around: 조인 포인트 실행 전후에 실행됩니다. 직접 조인 포인트를 실행할지 여부를 결정할 수 있습니다.@Around 어드바이스를 사용하여 메서드 실행 시간을 측정하는 Aspect를 만들어 보겠습니다.
java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component;
@Aspect @Component public class PerformanceAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measurePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 핵심 로직 실행
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
System.out.println("Method " + joinPoint.getSignature().getName() + " executed in " + executionTime + "ms");
return result;
}
}
ProceedingJoinPoint는 @Around 어드바이스에서만 사용 가능하며, 핵심 로직을 직접 실행할 수 있도록 해줍니다. joinPoint.proceed()를 호출해야 실제 메서드가 실행됩니다.Spring AOP는 횡단 관심사를 효과적으로 관리하고 코드의 재사용성을 높이는 강력한 도구입니다. AOP의 핵심 개념을 이해하고 실제 프로젝트에 적용해보면 코드 품질을 향상시키고 유지보수를 용이하게 할 수 있을 것입니다. 물론, AOP를 남용하면 오히려 코드가 복잡해질 수 있으니, 적절한 사용이 중요하겠죠?
출처: Spring AOP
| Spring WebFlux vs MVC 비교 (0) | 2026.02.24 |
|---|---|
| Spring Batch 입문 가이드 (0) | 2026.02.24 |
| Spring JPA N+1 문제 해결 (0) | 2026.02.24 |
| Spring Security JWT 인증 구현 (0) | 2026.02.23 |
| Spring Boot 3 새로운 기능 정리 (0) | 2026.02.23 |