[Spring] AOP vs Method

김민범·2025년 1월 30일

Spring

목록 보기
28/29

AOP(Aspect-Oriented Programming)와 단순히 공통 메서드를 분리하는 방법은 기능적으로 비슷해 보일 수 있지만, 관점 지향 프로그래밍(AOP)이 제공하는 강력한 이점이 있는 방식이다.


AOP vs 메서드 분리

AOP (Aspect-Oriented Programming)공통 메서드 분리 (OOP 방식)
적용 방식어노테이션이나 포인트컷을 사용하여 특정 메서드에 자동 적용되는 방식직접 메서드를 호출해야 하는 방식
침투성기존 비즈니스 로직 코드에 전혀 영향을 주지 않는 방식해당 메서드를 명시적으로 호출해야 하는 방식
관심사 분리 (Separation of Concerns)핵심 비즈니스 로직과 부가 로직을 완전히 분리하는 방식부가 로직이 핵심 로직과 혼재될 가능성이 높은 방식
유지보수성새로운 기능 추가 시 기존 코드 수정 없이 Aspect만 변경하면 되는 방식모든 호출 부분을 찾아 수정해야 하는 방식
적용 범위전역적으로 특정 로직을 적용할 수 있는 방식 (@Around, @Before, @After 등)적용하려면 개별 메서드에서 직접 호출해야 하는 방식
성능런타임에서 Proxy 기반으로 동작하는 방식 (성능 영향이 있음)메서드 호출 방식이므로 성능 영향이 적은 방식

🎯 언제 AOP를 사용해야 할까?

AOP는 반복적으로 사용되는 부가 기능(관점, Aspect)비즈니스 로직과 완전히 분리하는 방식이다.

AOP가 적합한 경우

  1. 로깅 (Logging)

    • 모든 API 요청/응답을 로그로 남겨야 하는 경우
    • 실행 시간 측정을 위해 특정 메서드 실행 시간을 기록해야 하는 경우
  2. 트랜잭션 관리 (Transaction Management)

    • @Transactional 같은 어노테이션을 이용하여 트랜잭션을 자동 관리하는 방식
  3. 보안 (Security)

    • 특정 API에 대한 접근 권한을 검증하는 로직을 분리하는 방식 (@PreAuthorize, @CheckMembership 등)
  4. 예외 처리 (Exception Handling)

    • 특정 예외가 발생할 경우 일괄 처리하여 JSON 응답을 변환하는 방식
  5. 캐싱 (Caching)

    • 특정 메서드의 결과를 캐싱하여 중복 요청을 방지하는 방식
  6. 모니터링 (Monitoring & Metrics)

    • API 요청 횟수, 평균 응답 시간 등의 성능 모니터링을 자동으로 추가하는 방식

예제 코드 비교

1️⃣ AOP 적용 예제 (현재 코드)

💡 @CheckMembership을 통해 프리미엄 유저가 아닐 경우 특정 데이터를 마스킹하는 방식

@Around(value = "@annotation(com.example.connect.global.aop.annotation.CheckMembership) && args(userId, id)",
        argNames = "joinPoint,userId,id")
public Object checkMembership(ProceedingJoinPoint joinPoint, Long userId, Long id) throws Throwable {

    Object result = joinPoint.proceed();

    if (!MembershipType.PREMIUM.equals(getCurrentUser().getMembershipType())) {
        if (result instanceof UserImageDetailResDto) {
            return maskUserImageDetailResDto((UserImageDetailResDto) result);
        }
    }

    return result;
}

AOP를 적용하면 코드에 @CheckMembership만 붙이면 되는 방식
모든 API에서 이 로직을 자동으로 실행하여 비즈니스 로직과 분리되는 방식


2️⃣ 공통 메서드 분리 (OOP 방식)

💡 checkMembership을 직접 호출해야 하는 방식

public UserImageDetailResDto getUserImage(Long userId, Long id) {
    UserImageDetailResDto result = userImageService.getImageById(userId, id);

    if (!MembershipType.PREMIUM.equals(getCurrentUser().getMembershipType())) {
        return maskUserImageDetailResDto(result);
    }

    return result;
}

비즈니스 로직 안에서 직접 메서드를 호출해야 하는 방식
매번 checkMembership()을 호출해야 해서 코드가 중복될 가능성이 높은 방식
다른 API에서 적용하려면 동일한 로직을 매번 추가해야 하는 방식


결론: AOP가 더 나은 이유

🎯 AOP는 "자동 적용"이 가능하며, 기존 코드에 영향을 주지 않는 방식

  • @CheckMembership 어노테이션만 추가하면 자동 적용되므로 비즈니스 로직이 깔끔하게 유지되는 방식이다.
  • 어떤 API에 적용할지 명확하게 컨트롤 가능 (@Before, @Around 등으로 실행 위치를 선택할 수 있는 방식**이다.
  • 새로운 API를 추가할 때도 @CheckMembership만 붙이면 동일한 로직을 적용할 수 있어 유지보수가 용이한 방식이다.

➡ 단순한 코드 재사용이라면 "공통 메서드 분리"가 적합한 방식이다.
➡ 하지만 전역적으로 특정 로직을 자동 실행해야 한다면 "AOP"가 훨씬 유리한 방식이다! 🚀

0개의 댓글