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의 코드 완성 기능 사용하거나, 단위 테스트로 확인