Spring AOP에 대해서 알아보자
Spring의 AOP에 대해서 알아보자
애플리케이션은 크게 핵심 기능과 부가 기능으로 나눠진다.
핵심 기능은 말그대로 애플리케이션을 작동하는 데 있어서 필요한 로직들이고 Serivce, Repository의 비즈니스 로직
부가 기능은 핵심 기능을 보조하는 기능이라고 생각하면 된다. 예를 들어 로그, 예외 처리, 트랜잭션 등등...
이러한 부가 기능들을 공통적으로 여러 핵심 기능에서 사용한다고 해보자.
예를 들어 Controller 단, Service 단, Repository단에서 모두 로그를 적용한다면?
위 그림처럼 각각 로직에 모두 로그를 적용시키는 방법이 있을 것이다. 하지만 이렇게 똑같은 코드를 반복적으로 작성하는 것은 비효율적이다. 그래서 이런 부가기능들을 모듈화 시켜 핵심 기능과 부가 기능을 분리시켜 따로 한 곳에서 관리시키도록 한 것이 AOP다.
이러한 횡단 관심사를 따로 관점을 분리해서 본다는 점에서 관점 지향 프로그래밍(Aspect-Oriented-Programming)이라고 한다.
AOP는 OOP와 대치되는 개념이 아닌 횡단 관심사를 깔끔하게 처리하지 못하는 OOP의 단점을 보완하기 위해 만들어진 프로그래밍 기법이라고 생각하면 된다.
그럼 AOP에 대해선 이제 알겠는데, 그럼 이걸 어떻게 사용해?
스프링에서는 @Aspect를 이용하여 쉽게 구현할 수 있다.
로그 예제를 통해 알아보자
@Service
@Slf4j
public class MemberService {
public void join(String name) {
log.info("[Log] MemberService 호출");
}
}
@Aspect
@Slf4j
@Component
public class LogAspect {
@Pointcut(value = "execution(* com.example.laboratory.service..*(..))")
private void serviceLog() {}
@Around("serviceLog()")
public Object proceedService(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[AOP] Service LOG TEST");
return joinPoint.proceed();
}
}
간단하게 Service 로직에서는 로그를 찍고, LogAspect 파일에서도 로그를 찍어서 적용되는 순서를 보자.
위 코드에서 @Aspect를 선언하여 부가 기능을 정의할 수 있다.
포인트컷은 표현식으로 이 부가 기능을 어느 범위에 적용할지 설정할 수 있는데, 위 예제에서는 service 패키지 하위에 있는 클래스에 모두 적용하도록 했다.
@Around("repositoryLog()")
public Object proceedController(ProceedingJoinPoint joinPoint) throws Throwable {
//메소드 호출 전처리
Object object = joinPoint.proceed();
//메소드 호출 후처리
return object
}
위 코드처럼 @Around는 메소드메서드 호출 자체를 가로채서 메서드 실행 전후에 처리할 로직을 삽입할 수 있다.
@SpringBootTest
class MemberServiceTest {
@Autowired
private MemberService memberService;
@Test
void aopTest() {
memberService.join("test");
}
}
위 테스트 코드를 실행시켜보면 memberSerivce가 호출되기 전에 LogAspect가 실행된 것을 볼 수 있다.