개발/Spring

Spring AOP 활용법

hanks 2026. 2. 24. 09:42

Spring AOP(Aspect-Oriented Programming)의 핵심 개념을 알아보고, 실제 프로젝트에서 어떻게 활용할 수 있는지 예시 코드와 함께 살펴봅니다.

왜 Spring AOP를 사용해야 할까요?

① 횡단 관심사(Cross-Cutting Concerns) 문제

애플리케이션을 개발하다 보면 로깅, 보안, 트랜잭션 관리 등 여러 모듈에서 공통적으로 사용되는 기능들이 발생하는데요, 이러한 기능들을 횡단 관심사라고 부릅니다. 이러한 횡단 관심사를 각 모듈에 흩뿌려놓으면 코드 중복이 심해지고 유지보수가 어려워지는 문제가 발생합니다.

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.");
}

}

위 코드처럼 로깅 코드가 createUserupdateUser 메서드에 반복적으로 나타나는 것을 볼 수 있습니다. AOP를 사용하면 이러한 중복을 제거하고 핵심 로직에 집중할 수 있게 됩니다.


② AOP의 등장 배경

AOP는 횡단 관심사를 모듈화하여 핵심 로직에서 분리하고, 필요한 시점에 적용할 수 있도록 해주는 프로그래밍 패러다임입니다. Spring Framework는 AOP를 효과적으로 지원하며, 개발자는 AOP를 통해 코드의 재사용성을 높이고 유지보수를 용이하게 할 수 있습니다.


Spring AOP 핵심 개념

항목 설명 예시
Aspect (애스펙트) 횡단 관심사를 모듈화한 것. 어드바이스와 포인트컷을 포함합니다. 로깅, 보안, 트랜잭션 관리
Advice (어드바이스) 실제로 수행되는 기능. 횡단 관심사에 해당하는 코드를 담고 있습니다. 로깅 코드, 보안 검사 코드, 트랜잭션 시작/종료 코드
Pointcut (포인트컷) 어드바이스를 적용할 위치를 지정하는 표현식. 특정 메서드 실행 전, 특정 예외 발생 시
Join point (조인 포인트) 어드바이스가 적용될 수 있는 지점. 메서드 실행, 예외 발생 등. 메서드 실행 시점, 필드 접근 시점
Weaving (위빙) 애스펙트를 핵심 로직에 적용하는 과정. 컴파일 시, 클래스 로딩 시, 런타임 시에 수행될 수 있습니다.  

Spring AOP 구현 방법

① 의존성 추가

먼저, 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 어노테이션을 사용하여 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 패키지 안의 모든 클래스의 모든 메서드를 의미합니다.

③ Advice 종류

Spring AOP는 다양한 Advice 종류를 제공합니다.

  • @Before: 조인 포인트 실행 전에 실행됩니다.
  • @After: 조인 포인트 실행 후에 실행됩니다 (성공, 실패 여부와 관계없이).
  • @AfterReturning: 조인 포인트가 정상적으로 완료된 후에 실행됩니다.
  • @AfterThrowing: 조인 포인트에서 예외가 발생했을 때 실행됩니다.
  • @Around: 조인 포인트 실행 전후에 실행됩니다. 직접 조인 포인트를 실행할지 여부를 결정할 수 있습니다.

④ 예시: Around Advice를 사용한 성능 측정

@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는 횡단 관심사를 효과적으로 관리하고 코드의 재사용성을 높이는 강력한 도구입니다. AOP의 핵심 개념을 이해하고 실제 프로젝트에 적용해보면 코드 품질을 향상시키고 유지보수를 용이하게 할 수 있을 것입니다. 물론, AOP를 남용하면 오히려 코드가 복잡해질 수 있으니, 적절한 사용이 중요하겠죠?

출처: Spring AOP