코린이의 기록

WebFlux framework 본문

Framework

WebFlux framework

코린이예요 2020. 7. 23. 19:07
반응형

 

 

 

 

목차

     

     

     

     

    Webflux 개념을 알기전에 Reactive Programming이란 무엇인가 살펴볼 필요가 있겠음.

    Reactive Programming ?

    일반적으로 Reactive Programming(반응 형 프로그래밍)은 비동기(Asynchronous)식 및 이벤트 기반(event-driven)Non Blocking 응용 프로그램에 관한 것이다. Reactive application의 주요 측면은 Backpressure의 개념으로, 생산자(producer)가 소비자(consumer)를 압도하지 않도록하는 메커니즘이다. 예를 들어 HTTP 연결이 너무 느릴 때 데이터베이스에서 HTTP 응답으로 확장되는 반응 구성 요소의 파이프 라인에서 데이터 저장소는 네트워크 용량이 확보 될 때까지 속도가 느려지거나 완전히 중지 될 수 있다. Reactive Programming은 명령의 논리에서 선언적 비동기 구성으로의 주요 전환으로 이어진다.

     

    Webflux란 ?

    Webflux는  비동기 Non-blocking reactive 개발을 할 수 있으며 효율적으로 동작하는 고성능 웹 어플리케이션 개발을 할 수 있는 서비스간 호출이 많은 마이크로서비스 아키텍쳐에 적합한 프레임워크다.

     

    Mono ?

    Mono는 0-1개의 결과만을 처리하기 위한 Reactor의 객체

    Mono<String> mono = Mono.just("Alex");
    Mono<String> mono = Mono.empty();

    Flux ? 

    Flux는 0-N개인 여러 개의 결과를 처리하는 객체

    Flux<String> flux = Flux.just("A", "B", "C");
    Flux<String> flux = Flux.fromArray(new String[]{"A", "B", "C"});
    Flux<String> flux = Flux.fromIterable(Arrays.asList("A", "B", "C"));
     
    //To subscribe call method
     
    flux.subscribe();

    Reactor를 사용해 일련의 스트림을 코드로 작성하다 보면 보통 여러 스트림을 하나의 결과를 모아줄 때 Mono를 쓰고, 각각의 Mono를 합쳐서 여러 개의 값을 여러 개의 값을 처리하는 Flux로 표현할 수도 있습니다.

     

    Spring WebFlux Module

    Server Side

    1. 어노테이션 기반

    2. 함수형 프로그래밍 기반

     

    왼쪽은 전통적인 spring-webmvc 모듈 기반, 오른쪽은 spring-webflux 모듈 기반인 반응형 stack을 나타낸다. 

     

    WebFlux는 다른 비동기 런타임을 지원하는 Netty와 Indertow 뿐만 아니라 Servlet 3.0 Non-blocking  IO API를 지원하는 서블릿 컨테이너에서 실행될 수 있다.

    각각의 런타임은 반응형 Backpressure을 사용하여 InputStream 과 OutputStream 대신 Flux <DataBuffer>로 요청 및 응답의 본문을 노출하는 반응형 ServerHttpRequest와 ServerHttpResponse에 조정된다.(adjust) 

    REST 스타일 JSON 및 XML 직렬화 및 역 직렬화는 Flux <Object>로 지원되며 HTML보기 렌더링 및 서버 전송 이벤트도 지원된다.

     

    1. Annotiation 기반의 모델

    Spring MVC에서 사용 되는 @Controller 모델과 동일한 어노테이션이 Webflux에서도 지원된다. 

     

    동작 흐름

    • MVC : request - Dispatcher Servlet - Handler Mapper - Controller - B/L - Controller - ViewResolver ...
    • WebFlux : request - HttpHandler - WebHandler - Handler Mapper / Handler Adapter - Controller - B/L -Controller - ViewResolver ...

    반응형 Controller의 예시

    @RestController
    public class PersonController {
    
    	private final PersonRepository repository;
    
    	public PersonController(PersonRepository repository) {
    		this.repository = repository;
    	}
    
    	@PostMapping("/person")
    	Mono<Void> create(@RequestBody Publisher<Person> personStream) {
    		return this.repository.save(personStream).then();
    	}
    
    	@GetMapping("/person")
    	Flux<Person> list() {
    		return this.repository.findAll();
    	}
    
    	@GetMapping("/person/{id}")
    	Mono<Person> findById(@PathVariable String id) {
    		return this.repository.findOne(id);
    	}
    }

     

    2. 함수형 프로그래밍 기반의 모델

    함수형 프로그래밍 모델은 Handler function과 Router function으로 나누어 구현한다. 

    Handler Function

    들어오는 HTTP요청을 ServerRequest객체를 가져와 Mono<ServerResponse> 형태로 return한다. ServerRequest는 다양한 HTTP request 요소(method, URI, Query Parameter)의 접근을 제공한다. 

     

    아래는 request body를 Mono<String>으로 추출하는 예시이다. 

    Mono<String> string = rerquest.bodyToMono(String.class);

    아래는 body를 Flux으로 추출하는 예시이다. 여기서 Person은 body의 내용에서 역직렬화 할 수 있는 class이다. 

    Flux<Person> people = request.bodyToFlux(Person.class);

     

     

    Router Function

    들어오는 요청은 ServerRequest 객체를 가져와 Mono<HandlerFunction>을 반환하는 함수인 RouterFunction을 사용하여 Handler Function에 rounting 된다.

    Client Side

    WebFlux에는 RestTemplate에 대한 fully non-blocking reactive 대안을 제공하는 기능적 반응성 WebClient가 포함되어 있다. 요청 및 응답의 본문이 InputStream및 OutputStream이 아닌 Flux <DataBuffer>인 경우, 반응형 ClientHttpRequest 및 clientHttpResponse로 네트워크 입/출력을 expose한다. 또한 서버 측에서와 동일한 반응성 JSON, XML 및 SSE 직렬화 메커니즘을 지원하므로 유형이 지정된 객체로 작업할 수 있다. 다음은 Reactor Netty와 같은 특정 HTTP client를 연결하기위해 ClientHttpConnector 구현이 필요한 WebClient를 사용하는 예이다.

    WebClient client = WebClient.create("http://example.com");
    
    Mono<Account> account = client.get()
    		.url("/accounts/{id}", 1L)
    		.accept(APPLICATION_JSON)
    		.exchange(request)
    		.then(response -> response.bodyToMono(Account.class));

    AsyncRestTemplate은 Non-blocking 상호 작용도 지원한다. 가장 큰 차이점은 기본적으로 여전히 InputStream 및 OutputStream을 기반으로 하기 때문에 Twitter와 같은 Non-blocking streaming을 지원할 수 없다는 것이다. 

     

    Reference

    Webflus framework tutorial : https://docs.spring.io/spring-framework/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html

     

    반응형
    Comments