John's 개발자의 관심노트

Spring 삼각형 - "AOP" 개념을 예제로 알아보기 본문

[개발]/Spring WEB

Spring 삼각형 - "AOP" 개념을 예제로 알아보기

John-Co 2022. 11. 9. 19:17

Spring 삼각형

Spring 삼각형에는  "AOP", "IoC / DI", "PSA" 개념을 가지고 있다 라고 설명을 드렸습니다. 이번 글에서는 예제 코드를 통해서 "AOP" 에 대해 조금 더 자세하게 알아보겠습니다.

 

앞서 설명했듯이 AOP란 "관점지향 프로그래밍" 이라는 의미를 가지고 있습니다. 공통적으로 사용되는 코드와 핵심 코드를 나누어 관리하도록 한다는 의미를 가지며, 공통 관심사 즉 여러 클래스에서 공통적으로 사용되는 코드들을 모듈화시켜 필요한 위치, 필요한 시점에 맞추어 삽입하여 프로그래밍 할 수 있습니다.

 

AOP 개념을 활용한 예제 코드 작성에 앞서 다음 그림을 보며 AOP가 동작되는 위치를 확인해보도록 하겠습니다.

Spring 동작 구성도

AOP 는 "DispatcherServlet" 과 "Controller" 중간에 위치해 있습니다. 그림과같이 "@Before, @After, @AfterReturning, @Around" 등을 활용해서 원하는 시점에 공통 동작코드를 삽입할 수 있습니다.

 

위 그림을 통해서 각 어노테이션 별로 어느 시점에 공통 코드를 동작시킬 수 있는지 살펴보도록 하겠습니다.

 

🔎 @Before

Controller Method 가 실행되기 직전 시점

🔎 @After

Controller Method 가 실행이 완료된 시점 (실패와 상관없음)

🔎 @AfterReturning

Controller Method 가 실행이 정상적으로 완료된 시점

🔎 @Around

Controller Method 가 실행되기 직전부터 실행이 완료될 때 까지


1. 프로젝트 생성

IntelliJ 프로젝트 생성

Java 11 버전을 활용했고, Dependency 는 "Spring WEB" 한 개만 적용하였으며, Spring 의 AOP 기능을 사용하기위해서는 Dependency 추가 작업을 진행해주어야 합니다.

 

Project Directory 에서 "build.gradle" 파일의 "dependencies {" 부근에 다음과 같이 추가 해주도록 합니다.

implementation 'org.springframework.boot:spring-boot-starter-aop'

AOP Dependency 적용


2. "Timer" Annotation 생성

특정 Target 을 기준으로 "@Around" 를 활용하여 처리시간을 구해보는 기능을 구현하기 위해 어노테이션을 생성했습니다.

 

🔗 위치 : "com.example.springaop.annotation"

Annotation 코드

💻 line : 8

Annotation 타입을 언제까지 유지할 것인지 설정하는 부분입니다.

호출한 Target 이 소멸되기 전까지 유지되도록합니다.

💻 line : 9

Annotation 할 Type 을 지정하는 부분입니다.

Method 와 Type (Interface, Class 등) 을 설정합니다.


3. Controller 생성

AOP 테스트를 위해 간단한 Controller Method 들을 생성하도록 하겠습니다.

 

🔗 위치 : "com.example.springaop.controller"

Controller 코드

💻 line : 15 ~ 16

해당 클래스를 "Controller" 로 등록하고, "/api" 주소로 맵핑되도록 설정합니다.

💻 line : 19

get() Method 는 HTTP의 "Get" Method 요청 시 동작되도록 등록합니다.

💻 line : 25

"hello world" 문자열을 담은 응답 데이터를 반환합니다.

💻 line : 28

delete() Method 가 실행되기 전에 호출되는 어노테이션 입니다.

💻 line : 29

delete() Method 는 HTTP 의 "Delete" Method 요청 시 동작되도록 등록합니다.

* line : 28 의 경우는 아래 AOP 구현 시 추가적으로 설명하도록 하겠습니다.

💻 line : 35

AOP 동작을 하며, 처리 시간을 임의로 부여하기위해 1초간 Delay 하도록 합니다.


4. AOP 구현

특정 Class 와 Annotation 을 기준으로 위에서 언급한 "@Before, @AfterReturning, @Around" 를 구현해보도록 하겠습니다.

 

🔗 위치 : "com.example.springaop.controller"

AOP Source Code

💻 line : 10 ~ 11

해당 클래스를 AOP 로 등록하고, Application 실행 전에 Bean Factory 에 Bean 으로 등록합니다.

AOP 클래스는 Bean 으로 등록되어야 정상적으로 동작할 수 있습니다.

💻 line : 14

AOP 가 동작할 Target 시점을 설정하는 부분입니다.

해당 부분의 의미는 controller 패키지 내에 있는 모든 Method 들을 Target 으로 하겠다라는 의미입니다.

 

❔ AspectJ 표현식 ("* execution()")

@PointCut 으로 Target 시점을 설정할 때 쓰이는 표현식입니다.

 

() : 파라미터가 없는 메소드
(..) : 파라미터 상관없이 모든 메소드
.* : 해당 패키지 내의 모든 클래스
.*.* : 해당 해키지 내의 모든 클래스 내의 메소드
ex1) excution(* hello()) hello 라는 모든 메소드 중 파라미터 없는 함수 지칭
ex2) excution(* hello(..)) hello 라는 모든 메소드
ex3) excution(* com.example.aopexample.Controller.*()) Controller 클래스 내의 파라미터가 없는 모든 메소드
ex4) excution(* com.example.aopexample..*.*(..)) aopexample 및 그 하위 패키지 내에 있는 모든 메소드

 

💻 line : 19

"Timer" Annotation 이 실행되는 시점을 Target 으로 하도록 설정합니다.

💻 line : 24

cut() Method 가 Target 으로 하는 시점이 동작하기 전에 before() 함수가 호출되도록 설정합니다.

💻 line : 26~27

Target 으로 하는 Class 명과 Mapping 된 HandlerMethod 의 이름을 출력합니다.

💻 line : 30

cut() Method 가 Target 으로 하는 시점이 동작되고 정상처리가 완료된 시점에 after() 함수가 호출되도록 설정합니다.

💻 line : 32

HandlerMethod 가 처리된 이후 Client 에게 전달 할 응답 데이터를 출력합니다.

💻 line : 35

cut() Method 가 Target 으로 하는 시점과 enableTimer() Method 가 Target 으로 하는 시점이 동시 발생되는 구간동안 around() Method 가 실행되도록 설정합니다.

💻 line : 37~43

stopWatch() 클래스를 활용해서 Target 으로 하는 시점동안의 처리 시간을 카운팅하여 출력합니다.

⭐️@Around 시점을 Target 으로 지정하는 경우에는, "ProceedingJoinPoint" 객체를 전달 받아 실행 전,후를 한번에 관여할 수 있습니다.

 

모든 코드를 작성한 이후, Project Directory 구조는 아래와 같습니다.

Project Directory

 

해당 어플리케이션을 테스트 하기위해서 "Talend API Tool" 을 사용하였습니다. 해당 Tool 에 대한 설치방법 및 간단한 사용법은 아래 링크를 참고해주세요.

 

HTTP Protocol Test 프로그램 사용법 "Talend API Tester"

Talend API Tester 라는 프로그램은, WEB Application 을 개발하거나, WEB Server 등을 개발할 때, REST API를 테스트하거나, HTTP Protocol 을 테스트 하기 위한 프로그램이다. 설치방법 "Chrome 웹 스토어" 접속 (Google

johnconomics.tistory.com

아래는 Talend API Tool 을 활용해서 "GET", "DELETE" 요청을 보내고 난 이후 결과화면 입니다.

테스트 결과 화면

💻 Talend API Tool 결과

상단 좌측 그림에서 보면 "DELETE" 의 경우는 Body 영역에 응답데이터가 없는 반면에, "GET" 의 경우는 Body 영역에 "hello world" 문자열이 있는 것을 확인할 수 있습니다.

 

💻 WEB Application 출력 결과

상단 우측 그림에서 보면 "@Timer" 가 붙은 "delete" 메소드가 실행 될 때는 "total time" 실행 시간을 출력하는 것을 볼 수 있으며, 붙지 않은 "get" 메소드의 경우는 출력되지 않는 것을 확인할 수 있습니다. 또한 "get" 메소드 의 Response Value 를 보시면 "hello world" 라는 문자열이 담겨있는 것을 확인할 수 있습니다.

반응형