일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 인증
- deepseek vs chatgpt
- AWS
- postgis
- 로그인
- IntelliJ
- 공동인증서
- exception
- Mono
- webflux
- NGINX
- PostgreSQL
- Spring Boot
- 본인인증
- 보안
- spring security
- 딥시크
- 본인확인
- ktlin
- Flux
- docker
- API
- Kotlin
- AOP
- 코틀린
- Spring
- 허깅 페이스
- 컨퍼런스
- db
- netty
- Today
- Total
[수미수의 개발 브로구]
[WebFlux] WebFlux AOP 사용하기 본문
들어가기 전
Spring WebFlux 는 리액티브 프로그래밍 모델을 기반으로 하며, 일반적으로 AOP (Aspect-Oriented Programming) 은 Spring 의 핵심 기능 중의 하나이다. 해당 기능은 어플리케이션에서 공통적으로 사용되는 기능을 분리하여 관점 지향 프로그래밍을 통해 공통 기능을 처리 할 수 있게 해준다. 이러한 공통 기능은 일반 Spring 에서 Filter, Interceptor, AOP 를 통해서 구현 할 수 있다.
Spring WebFlux 는 비동기/논블럭킹으로 동작 하기 때문에, AOP를 사용하여 비동기 요청 및 응답 처리 과정에서 로깅, 및 기타 공통 기능을 분리하여 재사용성과 유지 보수성을 높일 수 있다.
AOP 를 사용하기 위해서는 WebFlux 에서도 @Aspect 어노테이션을 사용하여 AOP 클래스를 정의하고, 적용하고자 하는 메서드에 Advice 를 정의하여 사용하면 된다.
해당 글에서는 요청/응답 처리 구간에서 응답 시간을 측정하여 응답 값에 추가하여 응답 하는 예제를 통해서 AOP를 어떻게 사용 하는지에 대해서 이야기 하고자 한다.
코드 분석
@Around("execution(* com..*Controller.*(..))")
fun process(pjp: ProceedingJoinPoint): Any {
val signatureArgs = pjp.args
// 1. 시간 측정 시작
val stopWatch = StopWatch()
stopWatch.start()
val strRequest = StringBuilder("[RestRequest]")
if (signatureArgs.isNotEmpty()) {
val request = signatureArgs[0] as Any
strRequest.append(" : ${gson.toJson(request)}")
}
// 2. 요청 Body 로깅
log.info(strRequest.toString())
return (pjp.proceed() as Mono<ResponseEntity<Any>>)
.flatMap {
stopWatch.stop()
// 3. 응답 시간 측정
val response = ResponseEntity<Any>(RestResponse(ApiResponseCode.OK.code, ApiResponseCode.OK.message, stopWatch.totalTimeMillis.toString(), "","", it.body), it.statusCode)
log.info("[RestResult] : ${gson.toJson(response)}")
// 4. 응답
Mono.just(
response
)
}
}
위 소스 코드는 비동기 요청/응답 구간에서 공통 기능을 AOP 로 구현한 예제이다. 그 기능으로는 Presentation Layer 인 Controller 로 호출 전 시간을 측정 한 뒤 , 해당 Controller 메서드를 나갈 때 까지의 경과 시간을 응답 값으로 같이 추가 하는 예제 이다.
시간 측정
시간 측정은 아래와 같이 StopWatch 클래스를 사용하여, 시간 측정을 시작 한다.
// 1. 시간 측정 시작
val stopWatch = StopWatch()
stopWatch.start()
요청 값 로깅
요청 값에 대한 로깅은, 아래와 같이 SignatureArgs 객체의 값이 없을 경우, 요청 된 json 값을 String 으로 변환하여 출력 되도록 한다.
val strRequest = StringBuilder("[RestRequest]")
if (signatureArgs.isNotEmpty()) {
val request = signatureArgs[0] as Any
strRequest.append(" : ${gson.toJson(request)}")
}
// 2. 요청 Body 로깅
log.info(strRequest.toString())
응답
함수형 프로그래밍 스타일로 proceed 를 호출 한 결과 값을 핸들링 하여, 시간 객체를 종료 시킨 후 RestResponse 객체에 담은 후 응답 객체를 만든 후 Mono 객체로 변환하여 Return 한다.
return (pjp.proceed() as Mono<ResponseEntity<Any>>)
.flatMap {
stopWatch.stop()
// 3. 응답 시간 측정
val response = ResponseEntity<Any>(RestResponse(ApiResponseCode.OK.code, ApiResponseCode.OK.message, stopWatch.totalTimeMillis.toString(), "","", it.body), it.statusCode)
log.info("[RestResult] : ${gson.toJson(response)}")
// 4. 응답
Mono.just(
response
)
}
RestResponse Response DTO 샘플
아래는 Response 로 사용되는 DTO 클래스의 구조이다. 응답 지연시간 정보는 아래 elapsedTime 필드에 적용되어 응답 하게 된다.
data class RestResponse<T> (
val returnCode:String,
val returnMsg:String,
val elapsedTime: String,
val errorCode: String,
val errorMsg: String,
val returnData: T
)
'Language & Framework > WebFlux' 카테고리의 다른 글
[WebFlux] WebFlux Server Request 에 Custom Header 추가하기 (0) | 2023.09.15 |
---|---|
[WebFlux] Spring WebFlux API 서버 만들기 (0) | 2023.08.27 |
[WebFlux] WebClient Connection Reset By Peer 오류 발생 (0) | 2023.08.18 |
[WebFlux] Spring WebFlux R2DBC를 이용한 데이터베이스 연동 (0) | 2023.08.14 |
[WebFlux] Spring WebFlux 프로젝트 생성 하기 (0) | 2023.08.14 |