티스토리 뷰

스프링 AOP(Aspect-Oriented Programming)는 핵심 비즈니스 로직에 영향을 주지 않고 공통적인 관심사를 처리하는 데 사용됩니다. AOP를 활용하면 코드 중복을 줄이고 유지보수를 용이하게 만들 수 있습니다.

 

AOP의 주요 사용처

 

1. 로깅

  • 애플리케이션의 메서드 호출, 매개변수, 반환값, 실행 시간 등을 기록
  • 개발 중 디버깅 및 운영 중 문제 분석에 유용
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Method called: " + joinPoint.getSignature());
    }
}

 

2. 보안

  • 메서드 실행 전 사용자 권한을 검증
  • 특정 기능에 대한 접근 제한 구현
@Aspect
@Component
public class SecurityAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void checkAccess(JoinPoint joinPoint) {
        // 권한 확인 로직
        System.out.println("Checking user access for method: " + joinPoint.getSignature());
    }
}

 

3. 트랜잭션 관리

  • 데이터베이스 작업의 시작, 커밋, 롤백 등 트랜잭션 처리
  • @Transactional 어노테이션도 내부적으로 AOP를 사용
@Transactional
public void performDatabaseOperation() {
    // 데이터베이스 작업
}

 

4. 성능 모니터링

  • 메서드 실행 시간을 측정하여 병목 구간을 파악
@Aspect
@Component
public class PerformanceAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long elapsedTime = System.currentTimeMillis() - start;
        System.out.println("Execution time: " + elapsedTime + "ms");
        return result;
    }
}

 

5. 예외 처리

  • 애플리케이션 전반에서 발생하는 예외를 처리
  • 특정 예외를 로그로 남기거나 사용자 친화적인 메시지 반환
@Aspect
@Component
public class ExceptionHandlingAspect {
    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
    public void handleException(JoinPoint joinPoint, Throwable ex) {
        System.out.println("Exception in method: " + joinPoint.getSignature());
        System.out.println("Exception: " + ex.getMessage());
    }
}

 

6. 데이터 검증

  • 메서드 호출 전 입력 데이터의 유효성을 검증
@Aspect
@Component
public class ValidationAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void validateArguments(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg == null) {
                throw new IllegalArgumentException("Arguments must not be null");
            }
        }
    }
}

 

7. 캐싱

  • 동일한 메서드 호출 결과를 캐싱하여 성능 최적화
@Aspect
@Component
public class CachingAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object cacheResult(ProceedingJoinPoint joinPoint) throws Throwable {
        // 캐싱 로직 (예: 결과 반환 전 캐시에 저장)
        return joinPoint.proceed();
    }
}

 

8. 감사

  • 사용자 활동 기록
  • 누가 어떤 데이터를 언제 수정했는지 로그로 남김
@Aspect
@Component
public class AuditingAspect {
    @After("execution(* com.example.service.*.*(..))")
    public void auditAction(JoinPoint joinPoint) {
        System.out.println("Audit log: " + joinPoint.getSignature());
    }
}

 

AOP의 장점

  1. 코드 중복 제거: 공통적인 로직을 한 곳에서 관리
  2. 유지보수 용이: 핵심 로직과 보조 로직이 분리되어 가독성 향상
  3. 운영 효율성: 로깅, 성능 모니터링, 보안 등의 기능을 중앙 관리

 

감사합니다.

최근에 올라온 글
Total
Today
Yesterday