1.3. DispatcherHandler

편집일시: 2021-04-13 10:46 조회수: 354 댓글수: 0
[Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet) Spring WebFlux은 Spring MVC와 마찬가지로 프런트 컨트롤러 패턴을 중심으로 설계되어 있으며, 중앙의 `WebHandler`인 `DispatcherHandler`가 요청 처리의 공유 알고리즘을 제공하고, 실제 작업은 구성 가능한 위임(delegate) 컨포넌트에 의해 실행된다 . 이 모델은 유연하고 다양한 워크 플로우를 지원한다. `DispatcherHandler`는 Spring 설정에서 필요한 위임 컨포넌트를 검색한다. 그러고, Spring Bean 자체되도록 설계되어 실행되는 컨텍스트에 액세스하기 위해 `ApplicationContextAware`를 구현한다. `DispatcherHandler`이 `webHandler`이라는 Bean 이름으로 선언되는 경우 [`WebHandler` API](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-web-handler-api)에 따라 요청 처리 체인을 모와서 [`WebHttpHandlerBuilder`](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/web/server/adapter/WebHttpHandlerBuilder.html)에 의해 검색된다. WebFlux 응용 프로그램의 Spring 설정은 일반적으로 다음이 포함된다. - `DispatcherHandler`, Bean 이름은 `webHandler` - `WebFilter` 그리고 `WebExceptionHandler` Bean - [`DispatcherHandler` 특수 Bean](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-special-bean-types) - 기타 다음의 예제에서 알 수 있듯이, 처리는 체인을 구축하기 위해 `WebHttpHandlerBuilder`에 주어진다. Java ``` ApplicationContext context = ... HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build(); ``` Kotlin ``` val context: ApplicationContext = ... val handler = WebHttpHandlerBuilder.applicationContext(context).build() ``` 결과 `HttpHandler`는 [서버 어댑터](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-httphandler)에서 함께 사용할 준비가 되어 있다. ## 1.3.1. 특별한 Bean 유형(Special Bean Types) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet-special-bean-types) `DispatcherHandler`는 요청을 처리하고 적절한 응답을 렌더링하는데 특별한 Bean에 위임한다. "특별한 Bean"이란, WebFlux 프레임워크의 요소를 구현하는 Spring 관리 `Object` 인스턴스를 의미한다. 기본적으로 내장(built-in)되어 있지만, 속성을 정의하거나 확장하거나 교체 할 수 있다. 다음 표는 `DispatcherHandler` 의해 검지된 특별한 Bean을 보여준다. 낮은 레벨에서 감지된 그밖에 Bean도 일부 있다는 점에 유의해라(Web 핸들러 API의[ 특별한 Bean 유형](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-web-handler-api-special-beans) 참조). | Bean 유형 |설명 | |--|--| | `HandlerMapping` | 요청을 핸들러에 매핑한다. 매핑은 몇 가지 조건을 기반으로 하며, 그 자세한 내용은 `HandlerMapping` 구현에 따라 달라진다. 주석이 선언된 컨트롤러, 간단한 URL 패턴 매핑 등. 주요 `HandlerMapping` 구현은 `@RequestMapping` 어노테이션이 선언된 메서드의 `RequestMappingHandlerMapping`, 함수 엔드 포인트 루트의 `RouterFunctionMapping` 및 URI 경로 패턴과 `WebHandler` 인스턴스의 명시적인 등록 `SimpleUrlHandlerMapping`이다. | | `HandlerAdapter` | 핸들러가 실제로 호출되는 방법에 관계없이, `DispatcherHandler`가 요청에 매핑 된 핸들러를 호출하는데 도움이 된다. 예: 어노테이션이 선언된 컨트롤러를 호출하려면 어노테이션에 대한 리졸버가 있어야 하는데, `HandlerAdapter`의 주요 목적은 그러 구체적인 부분까지는 `DispatcherHandler`에서 관여할 필요 없이 처리를 분리하는 것이다. | | `HandlerResultHandler` | 핸들러 호출의 결과를 처리하고 응답을 확인한다. [결과 핸들링](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-resulthandling)를 참조해라. | ## 1.3.2. WebFlux 구성 [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet-config) 응용 프로그램은 요청을 처리하는 데 필요한 인프라 Bean([Web 핸들러 API](httphttps://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-web-handler-api-special-beans) 및 [`DispatcherHandler`](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-special-bean-types/)에 목록화되어 있다)를 선언 할 수 있다. 그러나 대부분의 경우 [WebFlux 구성](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-config)이 최적의 출밤점이다. 필요한 Bean을 선언하고 그것을 정의하기 위한 높은 레벨의 구성 콜백 API를 제공한다. > Spring Boot는 WebFlux 구성에 따라 Spring WebFlux를 구성하고, 더욱 편리한 옵션을 제공한다. ## 1.3.3. 처리 [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet-sequence) `DispatcherHandler`는 요청을 다음과 같이 처리한다. - 각 `HandlerMapping` 일치하는 핸드러를 찾을 수 있도록 도와주고, 처음 메칭된 핸드러가 사용된다. - 핸들러가 찾으면 적절한 `HandlerAdapter`를 통해 실행되며, 실행에서 반환 값을 `HandlerResult`로 전달한다. - `HandlerResult`는 적절한 `HandlerResultHandler`에 전달된 응답을 직접 만들거나, 뷰를 사용하여 렌더링 처리를 완료한다. ## 1.3.4. 결과 처리(Result Handling) `HandlerAdapter`를 통해 핸들러의 호출의 반환 값은 추가 컨텍스트와 함께 HandlerResult로 싸여 그 지원을 요구하는 첫번째 `HandlerResultHandler`에 전달된다. 다음 표는 사용 가능한 `HandlerResultHandler` 구현을 보여준다. 이들은 모두 [WebFlux 구성](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-config)에 선언되어 있다. | 결과 핸들러 유형 | 반환 값 | 기본 순서 | |--|--|--| | `ResponseEntityResultHandler` | `ResponseEntity`, 일반적으로 `@Controller` 인스턴스에서 사용. | 0 | | `ServerResponseResultHandler` | `ServerResponse` 일반적으로 함수 엔드 포인트에서 사용. | 0 | | `ResponseBodyResultHandler` | `@ResponseBody` 메소드 또는 `@RestController` 클래스에서 반환 값을 처리한다. | 100 | | `ViewResolutionResultHandler` | `CharSequence`, [`View`](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/web/reactive/result/view/View.html), [Model](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/ui/Model.html), `Map`, [Rendering](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/web/reactive/result/view/Rendering.html)이나 다른 `Object`는 모델 속성으로 처리된다. [뷰 리졸버](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-viewresolution)를 참조해라. | `Integer.MAX_VALUE` | ## 1.3.5. 예외(Exceptions) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-exceptionhandlers) `HandlerAdapter`에서 반환된 `HandlerResult`는 핸들러 고유의 메커니즘을 기반으로 에러 핸들링 함수를 제공한다. 이 에러 핸들링 함수는 다음의 경우에 호출된다: - 핸들러 (예를 들어, `@Controller`) 호출 실패 - `HandlerResultHandler`를 통한 핸들러 반환 처리실패 에러 함수는 핸들러에서 반환되는 리액티브 유형의 데이터 항목을 생성하기 전에 에러 신호가 발생하면, 응답(예를 들어, 에러 상태:status)를 변경할 수 있다. 그래서 `@Controller` 클래스의 `@ExceptionHandler` 메서드가 지원된다. 반면 Spring MVC에서의 동일한 지원은 `HandlerExceptionResolver`을 기반으로 한다. 이는 그리 중요하지 않다. 다만, WebFlux는 `@ControllerAdvice`을 사용하여 핸들러가 선택되기 전에 발생하는 예외를 처리 할 수 없음에 주의해라. "어노테이션이 선언된 컨트롤러"섹션의 예외 관리 또는 WebHandler API 섹션의 예외를 참조해라. ## 1.3.6. 뷰 리솔루션(View Resolution) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-viewresolver) 뷰 리솔루션(View Resolution)를 사용하면 특정 뷰 기술에 얽매이지 않고, HTML 템플릿과 모델을 사용하여 브라우저에 렌더링 할 수 있다. Spring WebFlux는 `ViewResolver` 인스턴스를 사용하여 문자열(논리적 뷰 이름을 나타내는)를 `View` 인스턴스에 매핑하는 전용 `HandlerResultHandler`를 통해 뷰 리솔루션이 지원되고 있다. 다음은 `View`를 사용하여 응답을 렌더링한다. ### 핸들링(Handling) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-handling) `ViewResolutionResultHandler`에 전달되는 `HandlerResult`는 핸들러로부터의 반환 값과 요청 처리 중에 추가 된 속성을 포함하는 모델이 포함되어 있다. 반환 값은 다음 중 하나로 처리된다. - `String`, `CharSequence` : 구성된 `ViewResolver` 구현의 목록을 통해 `View`에서 만들어지는 논리적 뷰 이름. - `void` : 요청 경로에 따라 앞뒤에 슬래시를 제외한 디폴트 뷰 이름을 선택하고, `View`에서 해결한다. 뷰 이름이 지정되지 않은 경우(모델 속성이 반환된 경우 등) 또는 비동기 반환 값 (예를 들어, 빈어 있는 `Mono`가 완료된 경우)에서도 동일하게 처리한다. - [Rendering](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/web/reactive/result/view/Rendering.html) : 뷰 리솔루션 시나리오 API. IDE 자동 완성의 옵션을 찾아보자. - `Model`, `Map` : 요청의 모델에 추가된 추가 모델 속성. - 그 외 : 다른 반환 값([`BeanUtils#isSimpleProperty`](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-)에 의해 결정되는 단순한 유형 제외)는 모델에 추가되는 모델 속성으로 처리된다. 핸들러 메소드 `@ModelAttribute` 어노테이션이 존재하지 않는 속성 이름은 [Conventions](https://docs.spring.io/spring-framework/docs/5.3.5/javadoc-api/org/springframework/core/Conventions.html)을 사용하여 클래스 이름으로부터 얻어진다. 모델은 비동기 리액티브 타입을 포함 할 수 있다(예를 들어, Reactor 또는 RxJava에서). `AbstractView`는 이러한 모델 특성을 렌더링 전에 구체적인 값으로 값으로 리졸빙하고 그 모델을 업데이트한다. 단일 값의 리액티브 타입은 단일 값 또는 값 없음(비어있는 경우)로 확인된 여러 값의 리액티브 유형(예를 들어, `Flux<T>`)는 수집 된 `List<T>`에 리졸빙된다. 뷰 리졸버 조치를 구성하려면 `ViewResolutionResultHandler` Bean을 Spring 설정에 추가 하면 된다. WebFlux 구성은 뷰 리졸버 우퍼 전용 구성 API를 제공한다. Spring WebFlux와 통합 된 뷰 기술에 대한 자세한 내용은 [뷰 기술](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-view)을 참조해라. ### 리디렉션(Redirecting) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-redirecting-redirect-prefix) 뷰 이름의 특별한 `redirect:` 접두사(prefix)를 붙이면 리디렉션 할 수 있다. `UrlBasedViewResolver` (및 서브 클래스)는이를 리디렉션이 필요한 명령으로 인식한다. 뷰 이름의 나머지는 리디렉션 URL이다. 최종 효과는 컨트롤러가 `RedirectView` 또는 `Rendering.redirectTo("abc").build()`를 반환한 경우와 동일하지만 컨트롤러 자체가 논리적 뷰 이름의 관점에서 작동 할 수 있게 되어 있다. `redirect:/some/resource`와 같은 뷰 이름은 현재 응용 프로그램에 관련이 있지만, `redirect:https://example.com/arbitrary/path` 와 같이 하면 절대 경로 URL로 리디렉션된다. ### 콘텐츠 협상(Content Negotiation) [Web MVC](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-multiple-representations) `ViewResolutionResultHandler` 콘텐츠 협상을 지원하고 있다. 요청 미디어 유형과 선택한 각` View`에서 지원되는 미디어 유형을 비교한다. 요청한 미디어 타입을 지원하는 최초의 `View`가 사용된다. JSON 또는 XML 등의 미디어 타입을 지원하기 위해, Spring WebFlux는 `HttpMessageWriterView`을 제공한다. 이는 [ `HttpMessageWriter`](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-codecs)을 통해 렌더링하는 특별한 `View`이다. 일반적으로 이들은 [WebFlux 설정](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-config-view-resolvers)을 통해 기본 뷰로 설정한다. 요청한 미디어 타입에 일치하는 경우 기본 뷰가 항상 선택되어 사용된다.