
OOP(객체 지향 프로그래밍)은 복잡한 소프트웨어 세계를 객체라는 개념으로 단순화하여 처리하는 방식이다. AOP(관점 지향 프로그래밍)은 코드의 관심사를 분리하여 각 모듈을 따로 관리 할 수 있게 도와준다. 예를 들어 핵심 로직은 그대로 두고 부가적인 공통 기능(로깅,시간측정)등은 따로 처리하는 것이다.
만약 서비스 로직에서 메서드가 실행되는 시간 측정 로직을 추가한다고 해보자 그러면 이런식으로 코드를 짤 수 있을 것이다.
/**
* 수업 생성 서비스
*/
public CourseCreateResponseDto createCourse(CourseCreateRequestDto data) {
// 측정 시작
long startTime = System.currentTimeMillis();
// 수업 생성 로직 ....
// 측정 완료
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
log.info("::: ExecutionTime: {}ms", executionTime);
}
}
이처럼 실행 시간을 측정하는 코드가 필요 할 때, 동일한 로직을 여러 메서드에 반복해서 작성 해야한다면 코드 중복이 발생한다. 만약 메서드가 100개라면 유지보수도 매우 어려워질것이다. 이러한 중복되는 코드를 제거하고, 공통된 관심사를 한곳에서 관리하는것이 바로 AOP이다.

핵심 기능 : 메서드의 주요 비즈니스 로직, 예를 들어 수업 생성 기능이 이에 해당한다.
부가기능 : 비즈니스 로직과는 별개로 반복적으로 수행되는 작업. 예를 들어 메서드의 실행 시간을 측정하는 로직 등이 있다.
횡단관심사 : 여러곳에서 공통적으로 발생하는 부가기능 예를 들어 여러 서비스 메서드에서 동일하게 적용되는 시간 측정 로직 등이 있다.
한마디로 AOP는 핵심기능과 부가기능을 분리해서 관리하는 것이다.
AOP를 이해하기 위해서는 다음의 주요 용어를 알아야한다.
포인트 컷 표현식 예시
execution(int createCourse(int, int)) // 반환타입 int, createCourse 이라는 매서드, 매개변수는 int 형 2개
execution(* createCourse(int, int)) // 반환타입 상관없음, createCourse 이라는 매서드, 매개변수는 int 형 2개
execution(* createCourse(..)) // 반환타입 상관없음, createCourse 이라는 매서드, 매개변수 상관없음
execution(* *(..)) // 반환타입 상관없음, 메서드이름 상관없음, 매개변수 상관없음
포인트컷 정의 예시
@Pointcut("execution(* com.standard.sparta.service..*(..))")
private void serviceLayer() {
}
com.standard.sparta.service 패키지와 그 하위 패키지의 모든 메서드에 적용된다.
타겟은 어드바이스가 실제로 적용되는 객체이다. AOP에서 특정 부가기능을 적용하려는 클래스나 메서드를 타겟이라고 한다.
조인포인트는 어드바이스(횡단관심사) 가 적용될 수 있는 실행 지점을 의미한다. 즉 우리가 메서드 기준으로 어드바이스를 동작시킴으로 메서드들이 조인포인트가 됩니다.
코드예시 : 조인포인트 사용
@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void afterReturningMethod(Object result) {
log.info("::: AFTER RETURNING ::: " + result);
}
이 코드는 메서드가 성공적으로 실행 된 후 , 반환된 결과를 로그로 기록하는 어디바이스이다.
애스팩트는 어드바이스와 포인트컷을 하나로 묶은 모듈이다. AOP에서 애스팩트는 여러 포인트컷과 어드바이스를 포함하여 하나의 기능을 정의하는 단위이다.
코드 예시 : 애스팩트 정의
@Slf4j
@Aspect
public class AspectPractice {
// 포인트컷 정의
@Pointcut("execution(* com.standard.sparta.service..*(..))")
private void serviceLayer() {}
// 어드바이스 정의
@Around("serviceLayer()")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("::: BEFORE :::");
try {
Object result = joinPoint.proceed();
log.info("::: AFTER RETURNING :::");
return result;
} catch (Exception e) {
log.info("::: AFTER THROWING :::");
throw e;
} finally {
log.info("::: AFTER :::");
}
}
}
serviceLayer()포인트컷에 해당하는 모든 메서드들에 대해 실행전, 실행 후 ,예외 발생 시 각각 로그를 기록한다.