티스토리 뷰

https://0307kjb.tistory.com/8

 

 

7장. 스프링 삼각형과 설정 정보

스프링을 이해하는 데 POJO(Plain Old Java Object)를 기반으로 스프링 삼각형이라는 애칭을 가진 IoC/DI, AOP, PSA라고 하는 스프링의 3대 프로그래밍 모델에 대한 이해가 필수입니다. 스프링프레임워크를

0307kjb.tistory.com

 

AOP에 대해 간단 정리한 포스팅이니 참고용.

 

AOP란? Aspect Oriented Programming의 약자로, 여러 객체에 공통으로 적용할 수 있는 기능을 분리해서 재사용성을 높여주는 프로그래밍 기법이다. 즉 핵심 기능과 공통 기능의 구현을 분리함으로서 핵심 기능을 구현한 코드의 수정 없이 공통 기능을 적용하게 하는 것이다. 기본개념은 핵심 기능에 공통 기능을 삽입하는 것 즉 프록시 구조를 이루고 있다.

 

핵심 기능에 공통 기능을 삽입하는 방법에는 3가지가 존재한다.

1. 컴파일 시점에 코드에 공통 기능을 삽입하는 것

2. 클래스 로딩 시점에 바이트 코드에 공통 기능을 삽입하는 것

3. 런타임에 프록시 객체를 생성해 공통 기능을 삽입하는 것

 

1,2번의 경우 스프링 AOP에 지원하지 않고 AspectJ와 같은 AOP 전용도구를 사용해야 한다.

 

3번의 경우가 스프링 AOP를 적용, 프록시를 이용한 방식이다.

스프링 AOP는 프록시 객체를 자동으로 만들어준다. 그래서 프록시 클래스를 직접 구현할 필요없으며 단지 공통 기능을 구현한 클래스만 알맞게 구현하면 된다.

 

 

AOP 용어)

 

주요 용어에 대해 알아두자!

 

1. Advice : 언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의한다. 예를 들어, 메서드를 (언제) 호출하기 전에 (무언가) 공통기능을 적용하냐를 정의한다.

Advice의 종류는 Before, After, Around 등등이 존재한다. 한눈에 봐도 의미를 파악할 수 있을 것이다.

 

2. JoinPoint : Advice를 적용 가능한 지점을 의미한다. 메서드 호출, 필드 값 변경 등이 해당되며 스프링은 프록시를 통해 AOP를 구현하기에 메서드 호출에만 JoinPoint만 지원한다.

 

3. PointCut : JoinPoint의 부분 집합으로서 실제 Advice가 적용되는 JoinPoint를 나타낸다. 스프링에서는 정규 표현식 또느 AspectJ의 문법을 이용해 정의할 수 있다.

 

4. Aspect : 여러 객체에 공통으로 적용되는 기능을 말한다. (트랙잭션 또는 보안)

 

5. Weaving : Advice를 핵심 로직 코드에 적용하는 것.

 

 

 

그럼 코드를 통해 구현해보겠다!

 

TimeAspect.class

 

공통관심사를 구현할 클래스를 만들며 해당 클래스에 @Aspect 어노테이션을 붙여주어야 한다. 프록시는 스프링 프레임웤가 알아서 만들어준다.

 

spring 패키지 하위에 모든 메서드를 호출한다는 @Pointcut로 공통 기능 적용 대상 설정한다. (자세한 건 이따가)

@Around 어노테이션의 경우 Around Advice를 설정하여 메서드를 정의한 Pointcut에 공통 기능을 적용하는데 여기서 정의한 measure 메서드를 적용한다는 뜻.

ProceedingJoinPoint 타입 파라미터는 프록시 대상 객체의 메서드를 호출할 때 사용한다. proceed메서드는 실제 객체 대상의 메서드를 호출한다. 이 메서드를 호출하면 대상 객체의 메서드가 실행이 되므로 이 코드의 이전/이후에 공통 기능을 위한 코드를 위치시키면 된다는 뜻이다.

 

ProceedingJoinPoint 인터페이스 제공 메서드)

 

Signature getSignature( ) : 호출되는 메서드에 대한 정보를 구한다.

Object getTarget ( ) : 대상 객체를 구한다.

Object[ ] getArgs( ) : 파라미터 목록을 구한다.

 

 

공통 기능을 적용하는데 필요한 코드를 구현했으니 스프링 설정 클래스를 살펴보자.

설정 클래스

@Aspect를 붙여 AOP를 적용할 클래스를 공통 기능으로 적용하려면 @EnableAspectJAutoProxy 어노테이션을 설정 클래스에 붙여야 한다. 해당 어노테이션을 추가하면 스프링은 @Aspect 어노테이션이 붙은 빈 객체를 찾아서 빈 객체의 @Pointcut설정과 Advice설정을 확인 후 사용한다.

 

Advice의 일종인 @Around 어노테이션은 Pointcut으로 publicTarget 메서드를 설정했는데, 이건 spring 패키지 하위의 모든 빈 객체의 메서드를 설정한 후에 measure메서드를 적용한다는 뜻이다.

 

주석 처리한 부분을 다시 해제하면 오류가 난다!

이유는 간단하다. AOP를 적용할 빈 객체는 반환형이 인터페이스여야 한다. (프록시 패턴에 의한)

 

구현된 클래스들

 

Main.class
result

com.sun.proxy.$Proxy12에 주목하자. 우리가 생성한 Rec xxx, Impl xxx 타입이 아닌 스프링에서 생성한 프록시 타입이 주어진다. 이 뜻은 AOP를 적용한다면 빈 설정 시 반환형은 인터페이스이여야 하고 상속의 기준으로서 반환해야 한다.

즉 메인 클래스에서 Calculator rec -> RecCalculator rec으로 바꾼다면 타입이 다르게 되서 에러가 나는 것이다.

빈 객체가 인터페이스를 상속하면 인터페이스를 이용해 프록시를 생성

 

만약 빈 객체가 인터페이스를 상속할 때 인터페이스가 아닌 클래스를 이용해 프록시를 생성하고 싶다?

@EnableAspectJAutoProxy(proxyTargetClass = True)로 수정하면 된다. 수정 후 Calculator rec => RecCalculator rec으로 수정해도 에러가 나지 않는 것을 확인 할 수 있다.

 

 

execution 명시자 표현식에 대해 알아보자

executuion(수식어 패턴? 리턴타입패턴 클래스이름패턴?메서드이름패턴(파라미터패턴))

 

수식어 패턴은 생략 가능, 리턴타입패턴은 말그대로 리턴 타입을 명시한다. 클래스이름패턴과 메서드이름패턴은 클래스 이름 및 메서드 이름을 패턴으로 명시한다. 파라미터 패턴은 매칭될 파라미터에 대해서 명시한다. 각 패턴은 '*'를 이용해 모든 값을 표현가능하며 '..'를 이용해 타입이 0개 이상이라는 의미를 나타낸다.

 

또한,

 

@Around의 Pointcut 설정과 재사용이 가능한데 => @Around("execution(public * spring..*(..))") 처럼 직접 명시도 가능하다. 그리고 다른 Aspect 클래스에서 Pointcut으로 설정한 메서드를 가져올 수 있다는 점도 기억하자.

예시) @Around("spring.DiffAspect.diffMethod()") => spring 패키지에 DiffAspect 클래스에 diffMethod이 호출되면 호출되라! 처럼 말이다. 여러 Aspect에서 공통으로 사용하는 Pointcut이 있다면 별도 클래스에 Pointcut을 정의하고(얘는 Aspect 명시 x ) 각 Aspect 클래스에서 해당 Pointcut을 사용하도록 구성하면 관리가 수월하다.

이렇게 된다면 @Pointcut을 설정한 클래스는 빈으로 등록할 필요없으며 @Around 어노테이션에서 해당 클래스에 접근 가능하면 해당 Pointcut을 사용할 수 있다.

' > 초보 웹 개발자를 위한 스프링5 프로그래밍 입문' 카테고리의 다른 글

8장. DB연동  (0) 2021.10.09
6장. 빈 라이프사이클과 범위  (0) 2021.10.05
5장. 컴포넌트 스캔  (0) 2021.10.03
4강. 의존 자동 주입  (0) 2021.10.01
3강. 스프링 DI  (0) 2021.09.30
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함