AOP(Aspect-Oriented Programming)
OOP를 보완하는 수단으로, 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법이다.
- 왼쪽 그림의 A, B, C Class에서 같은 색의 띠가 공통되는 로직이라고 생각해보자.
- 만약 노란색 띠의 로직의 문제가 생긴다면 A, B, C Class 제각각 수정을 해야 한다.
- 공통되는 로직들을 오른쪽 그림처럼 한 곳에 모아 모듈로 간편하게 만들어 사용하는 것을 AOP라고 한다.
- 보안, 로깅, 트랜잭션 등에 주로 사용하는 것으로 알고 있다.
AOP의 주요 개념
Aspect
- Advice와 PointCut을 합친 개념이다.
Advice
- 해야 할 일들을 담고 있는 모듈
Target
- 적용이 되는 대상
PointCut
- 어드바이스를 어디에 적용을 해야 하는지에 대한 정보
JoinPoint
- 어드바이스가 적용될 수 있는 위치(생성자 호출 직전, 호출 후 등등)
Weaving
- 포인트 컷에 의해 결정된 타깃의 조인 포인트에 어드바이스를 삽입하는 과정
JAVA 구현체
AspectJ
- 컴파일, 로드 타임 시점에서 사용
스프링 AOP
- 런타임 시점에서 사용
AOP 적용 방법
컴파일 시점
- 자바 파일을 클래스 파일로 만들 때 AOP를 적용하는 방법
- 장점: 로드, 런타임에 성능 부하가 없음
- 단점: 별도의 컴파일 과정 필요
로드 타임 시점
- 컴파일 후 클래스 파일을 로딩하는 시점에 AOP를 적용하는 방법
- 장정: 다양한 문법을 사용할 수 있다.
- 단점: 클래스 로딩 시 약간의 부하 생길 수 있음, 로드 타임 위버를 설정해야 한다.
런타임 시점
- 클래스를 읽어 온 후 빈을 생성할 때 AOP를 적용하는 방법
- 장점: 별도의 컴파일, 로드 타임 위버가 필요 없고 문법이 간단하다.
- 단점: 빈을 만드는 초기에 성능이 추가되어 비용이 든다. 다양한 조인 포인트가 필요할 때 불리
런타임 시점에서 사용되는 스프링 AOP에 대해 알아보도록 한다.
프록시 패턴 이해하기
스프링 AOP는 프록시 패턴 기반으로 만들어졌으므로 프록시 패턴에 대해 아는 게 유리하다.
프록시 패턴
- 다른 객체를 대변하는 객체를 만들어서 주 객체에 대한 접근을 제어할 수 있다
예제
- ItemService를 Interface로 만들었다.
- 실제 사용할 클래스와 프록시 클래스는 이 인터페이스를 상속하여 구현한다.
- ItemService를 구현하여 메서드 호출 시 출력을 하게 작성하였다.
- 메서드들은 Tread.sleep으로 시간차를 두고 출력을 하게 만들었다.
- @Service를 통해 빈으로 등록하였다.
- Proxy용 클래스를 하나 만들고 ItemService를 구현한다.
- 프록시는 빈으로 등록한 ItemServiceImpl를 가지고 있다.
- 각 메서드에서 시간 차이를 계산하는 로직 사이에 각 로직에 맞는 itemServiceImpl의 메서드들을 선언한다.
- 그리고 AppRunner에서 ItemService를 받아올 때 Proxy 클래스를 받아올 수 있도록 @Primary를 붙여 우선순위를 부여한다.
- AppRunner에서 결과를 확인해보면 정상적으로 프록시 객체가 실행되어 ItemServiceImpl의 동작을 제어한 것을 알 수 있다.
- 하나 이렇게 사용하면 메서드마다 중복 코드가 발생하고 새로운 프록시 객체를 만들어야 하는 불편함이 있다.
스프링 AOP를 이용하면 시간을 계산하는 로직을 하나만 작성하고 원하는 곳에 설정할 수 있다.
스프링 AOP
스프링 IoC 컨테이너가 제공하는 기반 시설과 Dynamic 프록시를 사용하여 여러 복잡한 문제를 해결할 수 있다.
동적 프록시
- 동적으로 프록시 객체를 생성한다.
스프링 IoC
- 기존 빈을 대체하는 동적 프록시 빈을 만들어 등록시켜준다.
스프링 AOP 특징
- 프록시 기반의 AOP 구현체, 스프링 빈에만 AOP를 적용할 수 있다.
- 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제에 대한 해결책을 제공하는 것이 목적이다.
- 우선 스프링 aop를 사용하기 위해서 pom.xml에 의존성을 추가한다.
- 프록시 패턴 예제에서 생성한 ProxyItemService는 삭제한다.
- @Aspect를 이용하여 스프링 AOP를 적용시킬 수 있다.
- @Aspect가 붙어있는 logPerf메서드가 해야 할 일들을 담고 있는 Adivce가 된다.
- @Around에 PointCut을 정해 타겟들을 설정할 수 있다.
- 간단히 설명하자면 우선 첫 번째 *는 리턴 타입으로 모든 타입을 리턴을 허용한다는 뜻이다.
- 그리고 클래스를 패키 지명을 포함하여 작성한다.
- 그 후 .*은 모든 지정한 클래스의 모든 메서드들에 대해 적용하라는 뜻이다.
- 마지막 괄호는 파라미터에 대한 설정인데 (..)란 0개 이상을 의미한다.
- 즉 ItemService의 모든 메서드에서 리턴 값은 상관이 없고 0개 이상의 파라미터를 가진 대상에게 적용한다는 뜻이다.
- 실행결과를 확인해보면 정상적으로 동작하는 것을 알 수 있다.
표현식에 대해 잘 이해가 가지 않으시면 "스프링 aop pointcut 표현식" 키워드로 검색하시면 많은 정보들이 있습니다.
Annotaiton으로 PointCut 적용하기
- 만약 특정 메서드에만 적용하고 싶다면 어떻게 해야 할까?
- 표현식을 좀 더 정교하게 써서 할 수도 있을 것이다.
- 하지만 간단하게 annotaion을 만들어 그 annotaiton에만 AOP를 적용할 수도 있다.
- PerLogging Annotation이 붙은 메서드에만 Advice를 적용한다고 할 수도 있다.
- 그리고 아래와 같이 createItem에만 @PerLogging을 붙인다.
- PerLogging annotaion를 만들고 실행시켜보면 PerLogging이 붙어있는 create Item만 AOP가 적용된 것을 알 수 있다.
'스프링 > 스프링 핵심 기술' 카테고리의 다른 글
SpEL(Spring Expression Language) (0) | 2019.12.17 |
---|---|
데이터 바인딩 추상화: Editor, Converter, Formatter (0) | 2019.12.16 |
Validation 추상화 (0) | 2019.12.16 |
ResourceLoader, Resource 추상화 (0) | 2019.12.16 |
7. IoC 컨테이너: ApplicationEventPublisher (0) | 2019.12.14 |