29.2 The “Spring WebFlux Framework”

Spring WebFlux는 Spring Framework 5.0에서 소개된 새로운 사후 대응 웹 프레임 워크입니다. Spring MVC와 달리 서블릿 API를 필요로하지 않으며, 완전히 비동기적이고 비 블로킹이며, the Reactor project를 통해 Reactive Streams 사양을 구현합니다.

스프링 5부터 spring-wewbflux 등장.

spring-webflux 와 spring-mvc 중 어느 것을 사용 할 지 결정하려면?

  • non-blocking I/O가 어떻게 동작하며, 어떠한 효과를볼 수 있는 지 배워야한다

프레임워크를 고르는 기준 중 하나!

  • 의존성을 확인하는 것

    • 블로킹 방식의 persistence API(JPA, JDBC)나 network API를 사용한다면 spring-mvc가 적합

    • Spring MVC 어플리케이션에 원격 서비스를 호출하는 일이 있다면, Reactive WebClient를 사용하는 것을 권장한다. 스프링 MVC 컨트롤러 메서드에서 Reactive 타입(Reactor, RxJava 등)을 직접 반환 가능. 호출 당 지연이 길수록, 호출 간 상호 의존이 클수록, 더 큰 이득을 볼 수 있음

Spring WebFlux에는 기능적인 & 어노테이션 기반의 두 가지가 있습니다.

Spring-web 모듈은 스프링 웹플럭스의 기초가 되는 리액티브 기반을 포함한다.

스프링 웹 플럭스에서 제공하는 프로그래밍 모델?

1) 웹 플럭스 컨트롤러 (어노테이션 기반)

스프링 MVC와 일치(spring-web 모듈과 동일한 어노테이션 기반 컨트롤러)

스프링 MVC와 WebFlux 컨트롤러는 반환 타입으로 리액티브(Reactor, RX java)를 지원

스프링 MVC와 WebFlux 구별 어려움

2) 웹 플럿프 fn

가볍고, Java 8의 람다 기반의 함수형 프로그래밍 모델.

라우팅과 Request 처리를 할 수 있는 작은 라이브러리 또는 유틸리티의 셋.

어노테이션 기반은 다음 예제와 같이 Spring MVC 모델에 매우 가깝습니다.

Mono는 0-1개의 결과만을 처리하기 위한 Reactor의 객체이고, Flux는 0-N개인 여러 개의 결과를 처리하는 객체임.

@RestController
@RequestMapping("/users")
public class MyRestController {

	@GetMapping("/{user}")
	public Mono<User> getUser(@PathVariable Long user) {
		// ...
	}

	@GetMapping("/{user}/customers")
	public Flux<Customer> getUserCustomers(@PathVariable Long user) {
		// ...
	}

	@DeleteMapping("/{user}")
	public Mono<User> deleteUser(@PathVariable Long user) {
		// ...
	}

}

기능 변형인 "WebFlux.fn"은 다음 예와 같이 라우팅 구성을 실제 요청 처리와 분리합니다.

@Configuration
public class RoutingConfiguration {

	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
		return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
				.andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
				.andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
	}

}

@Component
public class UserHandler {

	public Mono<ServerResponse> getUser(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> deleteUser(ServerRequest request) {
		// ...
	}
}

WebFlux는 Spring Framework의 일부이며 자세한 정보는 reference documentation에서 확인할 수 있습니다.

라우터 정의를 모듈화 할 때 원하는 만큼의 RouterFunctionBean을 정의 할 수 있습니다. 우선 순위를 적용해야 할 경우 bean에 순서를 매길 수 있습니다.

시작하려면 응용 프로그램에 spring-boot-starter-webflux 모듈을 추가하십시오.

응용 프로그램에서 spring-boot-starter-webspring-boot-starter-webflux 모듈을 모두 추가하면 SpringBoot은 WebFlux가 아닌 Spring MVC를 자동 구성합니다. 이 동작은 많은 Spring 개발자가 반응적인 WebClient를 사용하기 위해 Spring-MVC 애플리케이션에 spring-boot-starter-webflux를 추가하기 때문에 선택되었습니다. 선택한 응용 프로그램 유형을 SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)으로 설정하여 선택 사항을 적용 할 수 있습니다.

29.2.1 Spring WebFlux 자동 구성

Spring Boot는 대부분의 응용 프로그램에서 잘 작동하는 Spring WebFlux의 자동 구성 기능을 제공합니다.

자동 설정은 Spring의 기본값 위에 다음과 같은 기능을 추가합니다.

  • HttpMessageReaderHttpMessageWriter인스턴스 용 코덱 구성 (이 문서의 뒷부분에서 설명 함)

  • WebJars에 대한 지원을 포함하여 정적 리소스 제공 지원 (이 문서의 뒷부분에서 설명)

Spring Boot WebFlux 기능을 유지하면서 WebFlux configuration을 추가하려는 경우 @EnableWebFlux가 아닌 WebFluxConfigurer형식의 @Configuration 클래스를 추가 할 수 있습니다.

Spring WebFlux를 완벽하게 제어하려면 @EnableWebFlux로 주석이 달린 @Configuration을 추가하면됩니다.

29.2.2 HTTP Codecs with HttpMessageReaders and HttpMessageWriters

Spring WebFlux는 HTTP 요청과 응답을 변환하기 위해 HttpMessageReaderHttpMessageWriter 인터페이스를 사용한다. 클래스 경로에서 사용할 수 있는 라이브러리를 보고 합리적인 기본값을 갖도록 CodecConfigurer로 구성됩니다.

Spring Boot는 CodecCustomizer인스턴스를 사용하여 추가 사용자 정의를 적용합니다. 예를 들어, spring.jackson.*구성 키는 Jackson 코덱에 적용됩니다.

코덱을 추가하거나 사용자 정의해야하는 경우 다음 예제와 같이 사용자 정의 CodecCustomizer구성 요소를 만들 수 있습니다.

import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration
public class MyConfiguration {

	@Bean
	public CodecCustomizer myCodecCustomizer() {
		return codecConfigurer -> {
			// ...
		}
	}

}

Boot’s custom JSON serializers and deserializers를 활용할 수도 있습니다.

29.2.3 정적 콘텐츠

기본적으로 스프링 부트는 classpath에있는 /static (또는 /public 또는/resources또는 /META-INF/resources) 디렉토리의 정적 컨텐츠를 제공합니다. Spring WebFlux의 ResourceWebHandler를 사용하므로 WebFluxConfigurer를 추가하고 addResourceHandlers메소드를 재정 의하여 해당 동작을 수정할 수 있습니다.

기본적으로 리소스는 /**에 매핑되지만 spring.webflux.static-path-pattern 속성을 설정하여 조정할 수 있습니다. 예를 들어, 모든 리소스를 /resources/** 로 재배치하는 것은 다음과 같이 수행 할 수 있습니다.

spring.webflux.static-path-pattern=/resources/**

spring.resources.static-locations를 사용하여 정적 자원 위치를 사용자 정의 할 수도 있습니다. 이렇게하면 기본값이 디렉토리 위치 목록으로 바뀝니다. 이렇게하면 기본 시작 페이지 검색이 사용자 지정 위치로 전환됩니다. 따라서 시작시 임의의 위치에 index.html이 있으면 응용 프로그램의 홈 페이지입니다.

앞에서 설명한 "표준"정적 리소스 위치 외에도 Webjars content에 특별한 경우가 있습니다. /webjars/**에 경로가있는 자원은 Webjars 형식으로 패키지 된 경우 jar 파일에서 제공됩니다.

Spring WebFlux 응용 프로그램은 Servlet API에 엄격하게 의존하지 않으므로 war 파일로 배포 할 수 없으며 src/main/webappdirectory를 사용하지 않습니다.

29.2.4 템플릿 엔진

REST 웹 서비스뿐만 아니라 Spring WebFlux를 사용하여 동적 HTML 컨텐트를 제공 할 수도 있습니다. Spring WebFlux는 Thymeleaf, FreeMarker 및 Mustache를 포함한 다양한 템플릿 기술을 지원합니다.

Spring Boot는 다음 템플릿 엔진에 대한 자동 구성 지원을 포함합니다.

이 템플릿 엔진 중 하나를 기본 구성으로 사용하면 템플릿이 src/main/resources/templates에서 자동으로 선택됩니다.

29.2.5 Error Handling

스프링 부트 (Spring Boot)는 합리적인 방법으로 모든 오류를 처리하는 WebExceptionHandler를 제공합니다. 처리 순서에서의 위치는 WebFlux가 제공한 핸들러 바로 직전이며 마지막으로 간주됩니다. 시스템 클라이언트의 경우, 오류, HTTP 상태 및 예외 메시지와 함께 JSON 응답을 생성합니다. 브라우저 클라이언트의 경우 동일한 데이터를 HTML 형식으로 렌더링하는 "whitelabel" 오류 핸들러가 있습니다. 오류를 표시하기 위해 자체 HTML 템플리트를 제공 할 수도 있습니다 (next section 참조).

이 기능을 사용자 지정하는 첫 번째 단계는 기존 메커니즘을 사용하지만 오류 내용을 대체하거나 보완하는 것입니다. 이를 위해ErrorAttributes 타입의 빈을 추가 할 수 있습니다.

오류 처리 동작을 변경하려면 ErrorWebExceptionHandler를 구현하고 해당 유형의 Bean 정의를 등록 할 수 있습니다. WebExceptionHandler는 꽤 낮은 수준이기 때문에 Spring Boot는 다음 예제와 같이 WebFlux 기능적 방식으로 오류를 처리 할 수있는 편리한 AbstractErrorWebExceptionHandler도 제공합니다.

public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

	// Define constructor here

	@Override
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {

		return RouterFunctions
				.route(aPredicate, aHandler)
				.andRoute(anotherPredicate, anotherHandler);
	}

}

보다 완벽한 그림을 보기 위해 DefaultErrorWebExceptionHandler를 직접 서브 클래스 화하고 특정 메소드를 대체 할 수 있습니다.

사용자 정의 에러 페이지

주어진 상태 코드에 대한 사용자 정의 HTML 오류 페이지를 표시하려면 /error폴더에 파일을 추가하십시오. 오류 페이지는 정적 HTML (정적 리소스 폴더 아래에 추가됨)이거나 템플릿으로 빌드 될 수 있습니다. 파일의 이름은 정확한 상태 코드 또는 시리즈 마스크 여야합니다.

예를 들어 404를 정적 HTML 파일에 매핑하려면 폴더 구조가 다음과 같습니다.

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

Mustache 템플릿을 사용하여 5xx오류를 모두 매핑하려면 폴더 구조가 다음과 같습니다.

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>

29.2.6 Web Filters

Spring WebFlux는 HTTP 요청 - 응답 교환을 필터링하기 위해 구현할 수있는 WebFilter인터페이스를 제공합니다. 응용 프로그램 컨텍스트에서 발견 된 WebFilterbean은 자동으로 각 교환을 필터링하는 데 사용됩니다.

Ex.

필터의 순서가 중요 할 경우 Ordered를 구현하거나 @Order로 주석을 달 수 있습니다. 스프링 부트 자동 구성은 웹 필터를 구성 할 수 있습니다. 그렇게하면 다음 표에 표시된 Order가 사용됩니다.

Web Filter

Order

MetricsWebFilter

Ordered.HIGHEST_PRECEDENCE + 1

WebFilterChainProxy (Spring Security)

-100

HttpTraceWebFilter

Ordered.LOWEST_PRECEDENCE - 10

Last updated