새발블로그

[Spring] AOP (Aspect Oriented Programming) 본문

Server/Spring

[Spring] AOP (Aspect Oriented Programming)

EUG 2025. 9. 22. 12:47

1. AOP란?

  • AOP (관점 지향 프로그래밍)은 공통적인 관심사(로깅, 예외 처리, 보안 등)를 핵심 비즈니스 로직과 분리하는 기법입니다.
  • 이를 통해 코드의 재사용성, 유지보수성, 가독성을 크게 높일 수 있습니다.

대표적인 공통 관심사

  • 로그 출력
  • 메서드 실행 시간 측정
  • 예외 처리
  • 트랜잭션 관리
  • 인증/권한 체크

2. AOP 핵심 용어

용어 설명
Target 핵심 비즈니스 로직이 담긴 객체 (ex. Service 클래스)
Advice 삽입할 코드 (로그, 권한 체크 등)
JoinPoint AOP가 적용될 수 있는 지점 (메서드 실행 등)
Pointcut Advice를 적용할 JoinPoint를 지정하는 조건
Proxy Target을 감싸는 래퍼 객체. Proxy가 Advice 실행 후 Target 호출

3. Advice 종류

어노테이션설명
어노테이션 설명
@Before 메서드 실행 실행
@AfterReturning 메서드 정상 종료 후 실행
@AfterThrowing 메서드에서 예외 발생 후 실행
@After 성공/실패와 관계없이 항상 실행
@Around 메서드 전/후 모두 제어 (가장 강력)

4. Pointcut 표현식 예시

pointcut : 필터링할 위치를 지정하는 필터링 로직

어드바이스 실행 시기를 제어할 수 있다.

표현식 설명
execution(* com.example.service.*.*(..)) 특정 패키지 내 모든 메서드
args(String, String) 두 개의 String 파라미터 받는 메서드
@annotation(Loggable) 특정 어노테이션이 붙은 메서드만 대상
within(com.example.service..*) 특정 패키지 및 하위 클래스 전체

5. 실습 코드 예시

Service (Target)

public interface SampleService {
    Integer doAdd(String str1, String str2) throws Exception;
}

@Service
public class SampleServiceImpl implements SampleService {
    public Integer doAdd(String str1, String str2) {
        return Integer.parseInt(str1) + Integer.parseInt(str2);
    }
}
 

Advice (공통 로직)

@Aspect
@Component
@Log4j
public class LogAdvice {

    @Before("execution(* com.example.service.SampleService*.*(..))")
    public void logBefore() {
        log.info("=== BEFORE 실행 ===");
    }

    @AfterThrowing(pointcut = "execution(* com.example.service.SampleService*.*(..))", throwing = "exception")
    public void logException(Exception exception) {
        log.error("예외 발생: ", exception);
    }

    @Around("execution(* com.example.service.SampleService*.*(..))")
    public Object logTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed(); // 실제 메서드 실행
        long end = System.currentTimeMillis();
        log.info("TIME: " + (end - start) + "ms");
        return result;
    }
}
 

6. AOP 활성화 설정

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.example.service", "com.example.advice" })
public class RootConfig {
}
 
implementation 'org.aspectj:aspectjrt:1.9.20'
implementation 'org.aspectj:aspectjweaver:1.9.20'
 

7. Trouble Shooting

1. AOP가 동작하지 않음

  • 원인: @EnableAspectJAutoProxy 누락
  • 해결: @Configuration 클래스에 반드시 추가

2.  내부 메서드 호출 시 AOP 미적용

  • 원인: Proxy 기반 → 같은 클래스 내 자기 호출은 Proxy 거치지 않음
  • 해결: 구조 분리 (호출 대상 메서드를 다른 Bean으로 분리)

3. @Transactional이 AOP랑 충돌

  • 원인: @Transactional도 AOP 기반 → Advice 순서 문제 발생 가능
  • 해결: @Order 어노테이션으로 실행 순서 명시
@Aspect
@Order(1) // 실행 우선순위 지정
public class TransactionAdvice { ... }

4. Pointcut 표현식 오타

  • execution(* ..) 표현식에서 패키지, 클래스 경로가 정확하지 않으면 전혀 실행 안 됨
  • 해결: IDE의 코드 완성 기능 사용하거나, 단위 테스트로 확인

'Server > Spring' 카테고리의 다른 글

[Spring] Spring Batch + Scheduler  (0) 2025.10.07
[Spring] WebSocket + STOMP  (0) 2025.09.22
[Spring] 직렬화와 역직렬화  (0) 2025.09.22
[Spring] 파일 업로드 & 다운로드  (0) 2025.09.22
[Spring] Spring + MyBatis  (0) 2025.09.22