본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Document

[SpringBoot] 공식 문서 요약(4) - Spring WebFlux

by 김코더 김주역 2021. 11. 15.
반응형

SpringBoot Document Review 4

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/

 

 

 

Spring WebFlux

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-webflux

 

https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux

※ WebFlux에 대한 예제 코드들이 많이 있음

 

1) Spring WebFlux 소개

- Spring WebFlux는 Spring Framework 5.0에서 도입된 반응형 웹 프레임워크로, Project Reactor의 웹의 스트리밍 처리를 담당한다. Spring MVC와 달리 Servlet API를 필요로 하지 않으며, 완전한 비동기화 및 non-blocking 방식이다.

※ non-blocking 방식 : 메소드를 호출했을 때, 그 메소드가 끝나는 것과 상관없이 다른 행동을 취할 수 있음

 Reactor : non-blocking back pressure을 이용한 비동기 데이터 처리의 표준인 Reactive Streams의 구현체

※ back pressure : Publisher에서 발행하고 Subscriber에서 구독할 때, Publisher에서 데이터를 Subscriber로 Push 하는 방식이 아니라, Pull 방식으로 Subscriber가 Publisher로 처리할 수 있는 양의 크기만큼 데이터를 요청 함으로써 Subscriber의 장애를 방지하는 방식이다.

- 서비스간 호출이 많은 아키텍처에 적합하다. View나 JSON으로 데이터를 넘겨줄 때, 대용량의 데이터를 전송할수록 속도 차이는 더 확연히 나타난다.

- spring-boot-starter-webflux 모듈을 사용해야 한다. 만약 spring-boot-starter-web도 같이 존재한다면, web이 더 우선순위가 높다. webflux를 우선으로 이용하게 하려면 SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)로 세팅하면 된다.

- 함수 기반 혹은 어노테이션 기반으로 사용할 수 있다.

어노테이션 기반 : 라우팅 설정 부분과 요청 핸들링 부분을 붙여 놓는 구조 (Spring MVC와 유사) - https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-controller

함수 기반 : 라우팅 설정 부분과 요청 핸들링 부분을 따로 분리해 놓는 구조 - https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-fn

- Reactor 객체이자 Publisher 구현체로 Flux와 Mono가 있는데, Mono는 0~1개의 데이터를 전달하고, Flux는 0~N개의 데이터를 전달한다는 차이점이 있다.

Flux.fromIterable() 메소드는 List를 Flux로 변환해준다.

 

 

2) Spring WebFlux Auto-configuration

- HttpMessageReader, HttpMessageWriter 인스턴스를 위한 Codecs를 설정한다.

- WebJars를 포함하여 static resources에 대한 제공을 지원한다.

- WebFlux에 추가적인 기능을 주고 싶다면 WebFluxConfigurer 인터페이스를 상속받은 @Configuration 클래스를 생성하면 된다. 단, @EnableWebFlux는 작성하지 않는다.

※ @EnableWebFlux를 포함하면 Spring Boot가 제공하는 기본 설정이 적용되지 않기 때문에 모두 직접 설정해야 함

 

 

3) Http Codecs with HttpMessageReaders and HttpMessage Writers

- Spring WebFlux는 HTTP 요청들과 응답들을 변환하기 위해 각각 HttpMessageReader, HttpMessageWriter 인터페이스를 사용하며, classpath에 있는 사용 가능한 라이브러리들을 찾아 만들어진 적절한 기본값들이 CodeConfigurer에 등록된다.

- CodeCustomizer 클래스를 @Bean으로 사용하여 코덱을 추가하거나 코덱을 커스터마이징 할 수 있다.

 

 

4) Static Content

(1) static path

- Spring Boot에서는 기본적으로 정적 파일을 /resources/static, /resources/public, /resources/resources, /resources/META-INF/resources에서 찾는다. 그리고 요청 URL에서는 저 경로를 명시하지 않고 root로 요청하면 된다.

참고로 이러한 처리는 ResourceWebHandler가 수행해주는데, 정적 파일을 찾는 경로를 수정하고 싶다면  WebFluxConfigurer 인터페이스를 상속한 @Configuraion 클래스를 생성하고 addResourceHandlers 메소드를 오버라이딩해서 수행하면 된다.

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry
      .addResourceHandler("/resources/**")
      .addResourceLocations("/resources/","classpath:/other-resources/");
}

- 만약, 정적 파일에 대한 요청 URL와 찾는 경로를 바꾸고 싶다면 설정 파일에 다음과 같이 작성한다.

(예시)

spring.webflux.static-path-pattern=/img/** 
spring.resources.static-locations=classpath:/image/

※ 위의 예시에서 static-path-pattern은 요청 경로이고, static-locations은 실제 정적 파일의 저장 경로이다. 위와 같은 경우에는 정적 파일은 /resources/image/에 저장하고 URL 요청은 /img/파일명으로 하면 된다.

- Spring Webflux는 Servlet API에 절대 의존하지 않기 때문에, Webjars을 이용할 때 src/main/webapp 디렉토리는 이용하지 않는 것을 권장한다.

 

 

5) Template Engines

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-webflux

- 템플릿 엔진의 경우에는 /resources에 templates 디렉토리를 생성해서 해당 파일을 추가하면 된다.

- 일반 템플릿 엔진에서는 View가 모두 완성되어야 클라이언트에게 응답을 보낼 수 있지만, Thymeleaf는 이러한 blocking을 최소화 한다. Thymeleaf에서는 컨트롤러에서 모아진 데이터를 chunk(덩어리) 단위로 View에 전달해서 바로바로 렌더링 시킬 수도 있다.

spring.thymeleaf.reactive.max-chunk-size=8192 #Chunk의 최대 크기
spring.thymeleaf.reactive.chunked-mode-view-names=thymeleaf/*chunked* #Chunked 모드를 적용할 View의 이름

또, Flux를 ReactiveDataDriverContextVariable객체에 묶어서 버퍼 단위로 전달할 수도 있다.

 

 

6) Error Handling

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-webflux-error-handling

- Spring Boot는 모든 에러들을 바람직한 방법으로 처리하기 위해 WebExceptionHandler을 제공한다.

- 기본적으로 Machine 클라이언트에게는 에러 내용이 포함된 JSON로 응답하고, Browser 클라이언트에게는 HTML 형태의 whitelabel 에러 View로 응답한다.

- 에러 내용 커스터마이징 : ErrorAttributes에 대한 Bean을 추가하는 방법

- Error Handling 동작을 커스터마이징하기 위해 ErrorWebExceptionHandler 인터페이스를 구현하여 Bean으로 등록하는 방법도 있지만, Spring Boot에서는 WebFlux의 기능적인 방법으로 Error Handling을 할 수 있는 AbstractErrorWebExceptionHandler 클래스를 지원한다.

- status code에 대한 에러 페이지 생성 : html 페이지의 경우에는 정적 파일을 찾는 경로에 /error 디렉토리를 생성하고, 그 안에 [에러코드].html 파일을 저장하면 된다. template의 경우에는 /resources/templates/error 디렉토리에 [에러코드].[확장자] 파일을 저장하면 된다.

※ 예) resources/public/error/404.html
※ 예) resources/templates/error/5xx.ftl -> 시리즈 마스크를 적용하여 500번대의 에러를 모두 포함

 

 

7) JSON Data

- Header에 "accept:application/stream+json"을 설정함으로써 Flux 데이터를 chunk 단위로 쪼개어 전송할 수 있다.

 

 

8) Web Filters

- Spring WebFlux는 HTTP 요청-응답간의 교환들을 필터링하기 위해 구현될 수 있는 WebFilter 인터페이스를 제공한다.

- 필터는 HTTP 요청을 처리하기 전에 호출된다.

- WebFilter로부터 오버라이딩되는 filter 메소드의 인자는 ServerWebExchange, WebFilterChain 객체이며, ServerWebExchange 클래스에 응답과 요청에 대한 정보를 가져오는 메소드들이 있다.

- WebFilter bean이 application context에 있다면 각 교환을 필터링할 때 자동으로 사용된다.
- 필터들의 순서가 중요한 경우 Order를 구현하거나 @Order 어노테이션을 적용할 수 있다. Spring Boot에 의해 설정되는 Web Filter들의 우선도는 다음과 같이 적용된다.

※ Order값이 낮을 수록 우선도가 높다.

 

 

반응형

댓글