탑신병자 듀오 팀 티모입니다.
오늘은 AOP에 대해서 알아보겠습니다.
AOP(Aspect Oriented Programming)은 곧 관점 지향 프로그래밍을 뜻합니다.
이는 애플리케이션 내에서 핵심 로직과 부가 기능을 분리하여,
애플리케이션 전체에 걸쳐 사용되는 부가 기능을 모듈화하여 재사용하기 위해 생겨났습니다.
부가 기능은 핵심 로직을 실행하기 위해서 행해지는 것들이며,
- 데이터베이스 연결
- 파일 입출력
- 모니터링 및 로깅
- 동기화
- 오류 검사 및 처리
- 성능 최적화(캐싱)
등의 다양한 기능들을 뜻합니다.
서로 다른 클래스에서 반복적으로 쓰이는 코드는 수정 시 모든 클래스에 일일이 적용해야 하는 번거로움이 존재합니다.
이 유지 보수를 효율적으로 하기 위한 해결법이 AOP입니다.
각 클래스에 흩어진 기능을 Aspect로 모으고 모듈화를 진행합니다.
각 모듈에는 특정 기능인 Advice와 적용해야 할 지점(클래스 및 메소드)인 PointCut 등이 존재합니다.
AOP에서의 주요 용어입니다.
- Aspect : AOP의 대상인, 소스 코드상에서 다른 부분에 계속 반복해서 쓰는 코드(흩어진 관심사)를 모듈화 한 것을 지칭합니다. 즉, 여러 객체에 공통적으로 적용될 기능을 뜻합니다.
- Target : Aspect를 적용할 대상이 되는 곳입니다.
- Advice : 실질적인 부가 기능 로직을 정의하는 곳입니다.
- Join Point - Advice를 적용할 지을 뜻합니다. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용 가능합니다.
- PointCut : Join Point의 상세한 스펙을 정의한 것이며, 실제로 Advice가 적용되는 Join Point를 나타냅니다.
'A란 메서드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있습니다.
AOP가 적용되는 방식은 시점에 따라 크게 3가지로 구분됩니다.
- 컴파일 시점
자바 코드가 class 파일로 컴파일 될 때 모듈화된 부가 기능 로직을 추가할 수 있습니다.
단, AspectJ라는 특별한 컴파일러를 사용해야 합니다.
AspectJ 컴파일러는 Aspect를 확인해서 해당 클래스가 적용 대상인지 먼저 확인하고, 적용 대상인 경우에 부가 기능 로직을 적용합니다.
추가로, 이렇게 원본 로직에 부가 기능 로직이 추가되는 것을 위빙(Weaving)이라 합니다. - 클래스 로딩 시점
자바가 class 파일을 JVM(자바 가상 머신) 내부의 클래스 로더에 따로 보관합니다.
위와 비슷하지만, class 파일을 JVM에 저장하기 전의 시점에 Aspect를 적용합니다. - 런타임 시점(프록시)
자바 파일이 컴파일되고, JVM에 class 파일 로드도 끝난 후 자바가 실행 중일때 AOP의 코드를 적용합니다.
실제 대상 코드는 그대로 유지되고 프록시를 통해 부가 기능이 적용됩니다.
특별한 컴파일러나, 복잡한 옵션, 클래스 로더 조작기를 사용하지 않아도 스프링만 있으면 AOP를 적용할 수 있기 때문에 스프링 AOP는 런타임 방식을 사용합니다.
AOP 어노테이션입니다.
- @Component
- 컴포넌트 어노테이션을 명시해 스프링 컨테이너가 객체를 생성하도록 합니다. - @Aspect
- 스프링 컨테이너에 AOP 담당 객체임을 알립니다. - @Around
- 대상 지정과 적용 시점을 지정합니다. (pointcut, advice)
아래는 스프링에서의 AOP 적용 예시입니다.
먼저 의존성을 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
이후 @Aspect 어노테이션을 붙여 이 클래스가 Aspect를 나타내는 클래스라는 것을 명시한 후
@Component를 붙여 스프링 빈으로 등록합니다.
package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeTraceAop {
@Around("execution(* hello.hellospring..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("START: " + joinPoint.toString());
try {
return joinPoint.proceed();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("END: " + joinPoint.toString()+ " " + timeMs +
"ms");
}
}
}
지금까지 AOP에 대해 간단히 알아보았습니다.
감사합니다.
'Programming' 카테고리의 다른 글
안드로이드 앱개발(1) (0) | 2023.07.06 |
---|---|
UML : 클래스 다이어그램 표기법 (0) | 2023.07.03 |
[Vue]Vuex 핵심 개념 (0) | 2023.06.25 |
Keycloak (0) | 2023.06.23 |
[C#] .NET Winform 간단한 UI 구성 방법 (0) | 2023.06.22 |
댓글