티스토리 뷰
1. AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)이란?
[ AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)이란? ]
프로그래밍을 하다보면 공통적인 기능이 많이 발생한다. 이러한 공통 기능을 모든 모듈에 적용하기 위해 상속을 이용한다. 하지만 Java에서는 다중 상속이 불가능하며, 상속을 받아 공통 기능을 부여하기에는 한계가 있다.
예를 들어 우리가 개발한 API의 호출 시간을 측정하고 싶다고 하자. 이를 AOP없이 구현한다면 어떻겠는가? AOP를 적용하지 않는다면 중복 코드가 발생할 소지가 있고, 코드의 변경이 필요하면 여러 코드에 종속적으로 변경이 필요할 것이며, 핵심적인 비지니스 로직에 호출 시간 측정이라는 부수적인 로직이 추가되어 가독성과 효율성이 떨어지는 등의 문제가 발생할 수 있다. 이러한 문제점을 해결하기 위해 AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)이 등장하게 되었다. AOP는 새로운 프로그래밍 패러다임이 아니라 OOP(Object Oriented Programming, 객체 지향 프로그래밍)를 돕는 보조적인 기술로, 핵심적인 관심 사항(Core Concern)과 공통 관심 사항(Cross-Cutting Concern)으로 분리시키고 각각을 모듈화 하는 것을 의미한다. 예를 들어 우리가 개발한 API중에 회원 가입 API가 있다면, 핵심적인 관심 사항은 회원
가입이라는 비지니스 로직이 될 것이고, 공통 관심 사항은 호출 시간 측정 로직이 될 것이다.

[ AOP(Aspect Oriented Programming)의 장점 ]
- 공통 관심 사항을 핵심 관심사항으로부터 분리시켜 핵심 로직을 깔끔하게 유지할 수 있다.
- 그에 따라 코드의 가독성, 유지보수성 등을 높일 수 있다.
- 각각의 모듈에 수정이 필요하면 다른 모듈의 수정 없이 해당 로직만 변경하면 된다.
- 공통 로직을 적용할 대상을 선택할 수 있다
2. AOP 적용해보기
[ AOP 적용해보기 ]
다른 요소들과 마찬가지로, AOP를 적용하기 위해서는 먼저 의존성을 추가해주어야 한다.
implementation 'org.springframework.boot:spring-boot-starter-aop'
AOP 의존성을 추가하고 빌드를 하였으면 AOP를 활성화하겠다는 어노테이션을 추가해주어야 한다. SpringBoot의 애플리케이션 클래스에 @EnableAspectJAutoProxy 어노테이션을 추가해주도록 하자
@EnableAspectJAutoProxy
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
위의 두 과정을 거치면 AOP를 적용하기 위한 준비가 끝난 것이다. 그러므로 실제 AOP 로직을 작성해보고, 자세히 살펴보도록 하자.
@Aspect
@Component
@Log4j2
public class ExecutionTimeAop {
// 모든 패키지 내의 controller package에 존재하는 클래스
@Around("execution(* *..controller.*.*(..))")
public Object calculateExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
// 해당 클래스 처리 전의 시간
StopWatch sw = new StopWatch();
sw.start();
// 해당 클래스의 메소드 실행
Object result = pjp.proceed();
// 해당 클래스 처리 후의 시간
sw.stop();
long executionTime = sw.getTotalTimeMillis();
String className = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
String task = className + "." + methodName;
log.debug("[ExecutionTime] " + task + "-->" + executionTime + "(ms)");
return result;
}
}
우선 Aop 클래스로 설정하기 위해 @Aspect 어노테이션을 추가해주었으며, Spring의 빈으로 등록하기 위해 @Component 어노테이션을 추가해주었다. 그리고 우리가 하고자 하는 것은 모든 API의 실행 시간을 측정해주는 것이므로, @Around 어노테이션을 통해 controller 패키지에 존재하는 모든 클래스에 대해 해당 AOP를 적용하겠다고 설정해주었다.
그리고 실행 시간 측정을 위해 StopWatch를 생성하여 측정을 시작하였다 그리고 pjp의 proceed를 통해 실제 핵심 로직을 실행하여 Object 클래스로 결과를 받았다. 이후에 StopWatch를 중단하여 실행 시간을 밀리세컨드로 계산하여 로그를 출력하고 함수를 종료시키고 있다.
만약 실행 시간 측정을 밀리세컨드가 아닌 세컨드로 변경한다고 하면 어떻게 해야 할까? AOP를 적용하지 않았다면 관련 로직의 모든 코드를 수정해주어야겠지만, AOP를 적용함으로써 핵심 로직에 대한 수정 없이 이를 처리할 수 있게 되었다.
출처: https://mangkyu.tistory.com/121?category=761302 [MangKyu's Diary]
'Spring' 카테고리의 다른 글
| [망나니 개발자] @Bean, @Configuration, @Component 어노테이션 (0) | 2021.06.08 |
|---|---|
| [망나니 개발자] Bean Scope(빈 스코프)의 종류 (0) | 2021.06.08 |
| [망나니 개발자] 생성자 주입을 사용해야 하는 이유 (0) | 2021.06.08 |
| [망나니 개발자] 빈(Bean)의 생성과 소멸에 대한 관리(초기화와 소멸자) (0) | 2021.06.08 |
| [망나니 개발자] @Autowired 빈 탐색 전략과 @Qualifier와 @Primary (0) | 2021.06.08 |
