📌 Java8 Reactor 프레임워크
- Java 8 이전에도 자바에서 리액티브 프로그래밍을 수행할 수 있었지만, Java 8에서는 리액티브 스트림(Reactive Streams)이라는 개념을 표준 라이브러리로 도입했습니다.
- 리액티브 스트림은 비동기 및 논블로킹 환경에서 데이터 스트림을 처리하는데 사용되는 표준 인터페이스를 정의합니다. 이 인터페이스는 Publisher, Subscriber, Subscription, Processor 등을 포함합니다.
- Java 8의 Reactor 프레임워크는 이 리액티브 스트림 스펙을 구현하고, 리액티브 프로그래밍을 위한 유용한 도구와 함수를 제공합니다. Reactor는 Flux와 Mono라는 두 가지 핵심 타입을 제공하여 데이터 스트림을 다룰 수 있습니다.
📌 Spring WebFlux와 Reactor
- Spring WebFlux는 Spring Framework의 모듈 중 하나로, 리액티브 프로그래밍을 지원하는데 Reactor를 활용합니다.
- Spring WebFlux는 백엔드에서 비동기 및 논블로킹 웹 애플리케이션을 개발하는데 사용되며, 데이터 스트림 처리를 위해 Reactor의 Flux와 Mono를 활용합니다.
- Spring WebFlux는 Java 8의 리액티브 스트림 스펙을 준수하고, 이를 기반으로 구축되었습니다. 따라서 Reactor와 Spring WebFlux를 사용하여 리액티브 애플리케이션을 개발할 수 있습니다.
- Reactor의 Flux는 다수의 값 또는 이벤트를 처리하기 위해, Mono는 하나의 값 또는 이벤트를 처리하기 위해 사용됩니다. Spring WebFlux는 이러한 타입을 사용하여 웹 요청과 응답을 처리하고, 비동기적으로 데이터를 다루며, 높은 확장성과 성능을 제공합니다.
요약하면, Spring WebFlux는 Java 8의 Reactor 프레임워크를 활용하여 리액티브 웹 애플리케이션을 개발하는데 사용되며, Reactor는 리액티브 스트림 스펙을 구현하는 핵심 라이브러리입니다. 이 두 가지 기술을 함께 사용하여 비동기 및 논블로킹 애플리케이션을 구축할 수 있습니다.
📌 WebClient
Spring WebFlux는 서버 측 리액티브 프로그래밍을 지원하고, WebClient는 클라이언트 측 리액티브 웹 통신을 위한 도구로 사용됩니다
- WebClient는 Spring Framework의 일부로 제공되는 리액티브 웹 클라이언트입니다.
- 이것은 외부 서비스나 API에 HTTP 요청을 보내고, 비동기 방식으로 응답을 처리하기 위한 도구입니다.
- WebClient는 Spring WebFlux의 클라이언트 측 구현으로 사용되며, 리액티브 스트림과 함께 외부 리소스와 통신할 때 유용합니다.
- 주로 백엔드 서버가 외부 서비스와 통신하거나 데이터를 가져오는 데 사용됩니다.
두 기술은 리액티브 프로그래밍 모델과 비동기 처리를 기반으로 하며, 함께 사용하여 완전한 리액티브 애플리케이션을 개발할 수 있습니다.
📌 WebClient 생성
✏️ build.grale 파일에 spring-boot-starter-webflux를 추가합니다.
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
}
group = 'api.study'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
tasks.named('test') {
useJUnitPlatform()
}
✏️ API를 호출하기 위해 WebClient를 초기화 하는 방법을 살펴보겠습니다.
import java.time.Duration;
import javax.net.ssl.SSLException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
public class ApiserviceApplication {
public static void main(String[] args) throws SSLException {
ConnectionProvider provider = ConnectionProvider.builder("custom-provider")
.maxConnections(20)
.maxIdleTime(Duration.ofSeconds(58))
.maxLifeTime(Duration.ofSeconds(58))
.pendingAcquireTimeout(Duration.ofSeconds(60))
.pendingAcquireMaxCount(-1)
.evictInBackground(Duration.ofSeconds(30))
.lifo()
.build();
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
WebClient client = WebClient.builder()
.clientConnector(
new ReactorClientHttpConnector(
HttpClient.create(provider)
.secure(t -> t.sslContext(sslContext))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 20000)
.doOnConnected(
conn -> conn.addHandlerLast(new ReadTimeoutHandler(30)) //sec
.addHandlerLast(new WriteTimeoutHandler(60)) //sec
)
.responseTimeout(Duration.ofSeconds(60))
)
).build();
}
}
📌 clientConnector 메소드
WebClient의 clientConnector 메서드는 Spring WebFlux에서 비동기 HTTP 클라이언트의 연결 설정을 구성하기 위해 사용됩니다. 이 메서드를 사용하여 커스텀 클라이언트 커넥터를 설정하거나 HTTP 클라이언트에 대한 여러 연결 속성을 구성할 수 있습니다.
여기서 Connector는 ClientHttpConnector 인터페이스를 구현하는 클래스를 받는 함수형 인터페이스입니다.
ClientHttpConnector는 HTTP 클라이언트의 연결 설정을 다루는 인터페이스로, 다양한 클라이언트 커넥터 구현체를 지원합니다.
일반적으로 사용하는 클라이언트 커넥터 구현체 중 하나는 ReactorClientHttpConnector입니다.
이 구현체는 Reactor 기반의 비동기 HTTP 클라이언트를 사용하며, Spring WebFlux와 함께 사용됩니다. 예제와 같이 clientConnector 메서드를 사용하여 ReactorClientHttpConnector를 설정할 수 있습니다
📌 ConnectionProvider
ConnectionProvider는 리액티브 프로그래밍 모델을 사용하여 데이터베이스나 외부 서비스와의 연결 관리를 담당하는 Spring의 기능 중 하나입니다. 이를 통해 애플리케이션이 비동기 및 논블로킹 방식으로 데이터베이스 또는 외부 서비스와 효율적으로 통신할 수 있습니다.
Spring에서는 ConnectionProvider 인터페이스와 구현체를 제공합니다. 주요 목적은 연결을 생성, 풀링, 관리하고, 연결이 사용 가능한지 여부를 결정하는 것입니다. 이를 통해 여러 클라이언트 또는 스레드가 동시에 데이터베이스나 외부 서비스와 통신할 때 공유 연결을 사용하거나 연결을 재사용할 수 있습니다.
📌 ConnectionProvider 메소드 설명
ConnectionProvider의다양한 메소드가 사용되었습니다. 아래에서 주어진 메소드들에 대한 간단한 설명입니다.
- ConnectionProvider.builder("custom-provider"): ConnectionProvider를 생성하기 위한 빌더를 시작합니다.
- "custom-provider"는 이 ConnectionProvider의 이름을 설정합니다. 이름은 식별 용도로 사용됩니다.
- maxConnections(20): maxConnections 메서드는 풀링된 최대 연결 수를 설정합니다.
- 여기에서는 최대 20개의 연결을 유지하도록 설정되었습니다.
- maxIdleTime(Duration.ofSeconds(58)): 연결이 유휴 상태로 유지될 수 있는 최대 시간을 설정합니다.
- Duration.ofSeconds(58)은 58초 동안 유휴 상태의 연결을 유지하도록 설정합니다.
- maxLifeTime(Duration.ofSeconds(58)): 연결의 최대 수명을 설정합니다.
- Duration.ofSeconds(58)은 58초 동안의 연결 수명을 설정합니다.
- pendingAcquireTimeout(Duration.ofSeconds(60)): 대기 중인(획득되지 않은) 연결의 최대 대기 시간을 설정합니다.
- Duration.ofSeconds(60)은 60초 동안 대기할 수 있는 시간을 의미합니다.
- pendingAcquireMaxCount(-1): 최대 대기 중인 연결 요청의 수를 설정합니다.
- -1은 제한이 없음을 의미하며, 대기 중인 요청 수에 제한을 두지 않음을 나타냅니다.
- evictInBackground(Duration.ofSeconds(30)): 백그라운드에서 연결을 해제할 주기를 설정합니다.
- Duration.ofSeconds(30)은 30초마다 백그라운드에서 연결 해제 작업을 실행합니다.
- lifo(): 연결을 가져올 때 Last-In-First-Out(LIFO) 순서로 가져오도록 설정합니다.
- LIFO는 가장 최근에 반환된 연결을 가장 먼저 사용하도록 하는 방식입니다.
- build(): ConnectionProvider 객체를 최종적으로 생성합니다.
ConnectionProvider를 사용하면 데이터베이스 연결, 원격 서비스 연결 또는 기타 외부 리소스에 대한 연결 관리를 자동화하고 최적화할 수 있습니다. 이는 리액티브 스트림과 함께 사용하여 여러 요청을 동시에 처리하고 논블로킹 방식으로 데이터를 가져올 때 특히 유용합니다.
Spring 프레임워크와 Spring Data 프로젝트에서 다양한 데이터베이스에 대한 ConnectionProvider 구현체를 제공하므로, 특정 데이터베이스 기술을 사용하는 경우에도 리액티브 방식으로 데이터베이스와 통신할 수 있습니다.
📌 ReactorClientHttpConnector
ReactorClientHttpConnector는 Spring WebFlux에서 사용되는 HTTP 클라이언트 커넥터 중 하나로, Reactor 프레임워크를 기반으로 한 비동기 HTTP 클라이언트를 생성하고 Spring WebFlux 애플리케이션과 통합하는 데 사용됩니다. 이 커넥터는 Spring의 WebClient를 통해 원격 서버와의 비동기 HTTP 통신을 담당합니다.
- 비동기 및 논블로킹: ReactorClientHttpConnector는 비동기 및 논블로킹 프로그래밍 모델을 따릅니다. 이는 요청을 보내고 응답을 기다리는 동안 다른 작업을 계속 수행할 수 있도록 해주며, 서버로부터 데이터를 받을 때까지 블로킹하지 않습니다.
- Reactor 기반: ReactorClientHttpConnector는 Reactor 프레임워크의 Mono 및 Flux 타입을 사용하여 비동기적으로 HTTP 요청 및 응답을 처리합니다. 이러한 리액티브 타입은 비동기적인 데이터 스트림 처리에 적합하며, 리액티브 프로그래밍 모델과 통합됩니다.
- Spring WebClient와 통합: ReactorClientHttpConnector는 Spring의 WebClient와 함께 사용됩니다. WebClient는 HTTP 요청을 정의하고 보내는 데 사용되며, 이 커넥터를 통해 원격 서버와의 통신을 처리합니다.
- HTTP 요청 구성: ReactorClientHttpConnector를 사용하면 HTTP 요청의 구성을 세부적으로 조정할 수 있습니다. 예를 들어, 요청 헤더, 쿼리 매개변수, 요청 본문 및 인증과 같은 요청 구성 요소를 설정할 수 있습니다.
- 풀링 및 연결 관리: 이 커넥터는 HTTP 연결 풀링과 연결 관리를 효과적으로 처리하여 리소스를 효율적으로 활용합니다.
ReactorClientHttpConnector를 사용하면 Spring WebFlux 애플리케이션에서 비동기 HTTP 요청을 보내고 비동기적으로 응답을 처리할 수 있습니다. 이것은 비동기 및 논블로킹 웹 애플리케이션을 개발할 때 중요한 요소 중 하나이며, Reactor와 Spring WebFlux와의 통합을 간편하게 수행할 수 있도록 합니다.
📌 다음 섹션에서는 WebClient를 사용해서 API를 전송, 처리하는 프로세스를 살펴보도록 하겠습니다.
WebFlux, WebClient 사용하여 API 호출 - 2편 (tistory.com)
'Programing > Java & Spring' 카테고리의 다른 글
WebFlux, WebClient 사용하여 API 호출 - 3편 (0) | 2023.10.05 |
---|---|
WebFlux, WebClient 사용하여 API 호출 - 2편 (0) | 2023.09.26 |
함수형 인터페이스(Funcational Interface) (0) | 2023.09.22 |
스프링(Spring) 에서 RequestURI, RequestURL 차이 (0) | 2023.09.08 |
Java Default Method (디펄트 메소드) (0) | 2023.09.08 |
스프링(Spring)에서 RestTemplate, Https 통신 (0) | 2023.09.08 |
AOP(Aspect-Oriented Programming) 개념 및 예시 (0) | 2023.09.08 |
[JAVA] content-disposition (0) | 2013.12.31 |
[SPRING3.0] 메세지 처리 (0) | 2013.09.12 |
[SPRING3.0] 페이스북 공유하기① (0) | 2013.09.11 |