지난 포스팅에서 @Async 어노테이션을 사용하여 비동기 멀티 스레드를 구현하는 방식에 대해서 포스팅을 했었다.
해당 기능은 Spring AOP의 기능이라고 작성을 했었는데 이번 포스팅에서는 Spring AOP가 무엇인지, 또 어떻게 사용을 하는지 포스팅을 하고자 한다.
AOP란.
AOP(Aspect-Oriented Programming)는 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법으로 OOP를 보완하는 수단으로 사용.
프로젝트 전반적으로 여러 메소드들에서 반복되는 코드 또는 로직을 모듈화 하여 재사용 할 수 있게 해주는 기능
가장 흔한 예를 들자면 로깅을 하는 기능이 있다고 했을 때 각 메소드 마다 성능 측정 로깅을 넣는다고 하면 메소드 내부에 반복되는 코드들이 계속 늘어날 것이며 유지보수 또한 힘들것이다.
이렇게 반복되는 코드를 따로 끄집어내서 각 메소드에서는 Business logic만 작성 및 동작 시키는게 AOP라고 생각하면 될 것 같다.
AOP 적용 방법
1. 컴파일 시점
- 자바 코드가 컴파일 되는 시점에 적용이 되며 .class 파일에는 이미 코드상으로 해당 AOP 로직이 적용되어있는 상태이다.
- 로드타임, 런타임에 발생되는 성능 부하가 없다.
- 별도의 컴파일 과정이 따로 필요하다.
2. 로드 타임
- 컴파일 될 시점에는 해당 메서드에는 비즈니스 로직만 존재하며 해당 class 파일이 로딩 되는 시점에 AOP 로직이 적용이 된다.
- AspectJ를 사용할 수 있어서 다양한 문법을 사용할 수 있다.
- Load Time Weaving의 java agent 설정을 해줘야 한다.
- 로드 타임이 진행 될 때 부하가 생성된다.
3. 런타임
- Spring AOP가 사용하는 방법
- Spring Application에서 Bean을 만들 때 적용이 된다.
- 런타임 시 성능 부하가 발생한다.
- 별도의 처리 과정이 필요 없다(별도의 컴파일 과정, 별도의 Load Time Weaving 설정)
AOP 주요 용어
- Aspect
- Advice와 Pointcut이 포함된 모듈화 된 코드
- Target
- 적용을 할 대상
- Advice
- 공통화 시킬 로직을 작성하는 곳
- Join point
- Advice가 합류가 될 위치 또는 지점을 나타내는 용어
- 메서드 실행 시점, 생성자 호출 시점, 필드 접근 시점 등등 합류점
- Spring AOP에서는 메서드 실행 시점을 사용한다.
- Pointcut
- Advice가 실행 될 시점
Spring AOP 적용
- 프록시 기반의 AOP 구현체로 Spring Bean에만 적용이 된다.
- Spring AOP는 위에서 설명한 AOP 적용 방법 중 런타임 적용 방법을 사용한다.
- 프록시 패턴의 문제점을 보안하기 위해 스프링 IoC와 Dynamic 프록시를 사용하여 구현한다.
1. 의존성 주입
- Maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
</dependency>
- gradle
implementation group: 'org.springframework', name: 'spring-aop', version: '2.5.6'
2. @Aspect 어노테이션을 이용한 Bean 등록
@Component
@Aspect
public class LoggerAspect {
@Around("@annotation(CustomLogger)")
public Object CostomLogger(ProceedingJoinPoint joinPoint) throws Throwable{
// 시작 시간 체크
long startTime = System.currentTimeMillis();
// 기존 메소드 호출 (실행)
Object proceed = joinPoint.proceed();
// 종료 시간 체크
long elapsedTime = System.currentTimeMillis() - startTime;
// 소요 시간 출력
System.out.println(elapsedTime);
return proceed;
}
}
3. Pointcut 정의 하기
- @Around, @Before, @After, @AfterReturing, @AfterThrowing 어노테이션을 통해서 pointcut을 정의한다.
- pointcut 표현식으로 적용 시킬 위치를 표시할 수 있다. ex) execution, within 등등... (추후에 다음 포스팅에서 자세히 다뤄보자)
- @annotation 어노테이션을 사용해서 특정 어노테이션이 붙어있는 method에서 실행 시킬 수 있다.
@Around
- method 호출을 감싸는 형식의 어노테이션
- method 전과 후를 감싸서 Advice를 실행
- 아래 4가지의 경우를 하나의 @Around으로 사용이 가능
@Before
- method가 실행하기 이전에 무조건 Advice를 실행
@After
- method가 실행한 뒤 무조건 Advice를 실행
- method 로직 도중에 Exception이 발생하여 비정상 종료가 되어도 무조건 실행
@AfterReturing
- method가 정상 종료 후 Advice를 실행
@AfterThrowing
- method가 Exception이 발생해 예외를 던지는 경우에 실행
4. AOP 적용
@Service
@RequiredArgsConstructor
public class AspectService {
@CustomLogger
public void testSample(String path){
...
비즈니스 로직
...
}
}
- testSample 메소드 위에 내가 미리 정의한 CustomLogger라는 어노테이션을 붙이면 해당 메소드가 실행이 될 때 자동으로 AOP가 실행이 되는것을 확인할 수 있다.
이번 예제에서는 Spring AOP를 어노테이션을 이용한 방법을 포스팅했다.
그렇다면 어노테이션을 어떻게 만들어야 하는가에 대해서 궁금증이 생길 수 있을것이다.
다음 포스팅에서는 Spring에서 커스텀 어노테이션을 만드는 방법에 대해서 포스팅을 하도록 하겠다.
참고
인프런 강의 - 백기선의 '스프링 프레임워크 핵심 기술'
https://velog.io/@backtony/Spring-AOP-%EC%B4%9D%EC%A0%95%EB%A6%AC
'Spring' 카테고리의 다른 글
Spring JPA / Entity 매핑 (0) | 2023.06.21 |
---|---|
Spring JPA / JPA (0) | 2023.06.20 |
Object Storage 이미지 출력 (0) | 2023.06.09 |
@Asnyc를 이용한 멀티 스레드 (0) | 2023.06.08 |
멀티 스레드 환경을 위한 스레드 풀 (Thread pool) - ThreadPoolTaskExecutor (0) | 2023.06.06 |