Spring Web Reactive | 1. Spring WebFlux | 1.9. View Technologies

Web MVC

Spring WebFlux에서 뷰 기술의 사용은 플러그 가능하다. Thymeleaf, FreeMarker 또는 기타 표시 기술을 사용할지 여부는 주로 구성 변경의 문제이다. 이 장에서는 Spring WebFlux와 통합된 뷰 기술에 대해 설명한다. 이미 View Resolution에 대해 잘 알고 있다는 것을 전제로 하고 있다.

1.9.1. Thymeleaf

Web MVC

Thymeleaf은 더블 클릭으로 브라우저에서 미리 볼 수 있는 자연스러운(natural) HTML 템플릿을 강조하는 최신 서버 사이드 Java 템플릿 엔진이다. 이것은 UI 템플릿(디자이너 등)에서 별도의 작업이 필요 없이 매우 도움이 된다. 실행중인 서버. Thymeleaf는 광범위한 기능 세트를 제공하고 적극적으로 개발 및 유지 보수되어 있다. 완전한 소개 내용은 Thymeleaf 프로젝트의 홈페이지를 참조해라.

Thymeleaf와 Spring 통합 WebFlux는 Thymeleaf 프로젝트에 의해 관리된다. 구성은 SpringResourceTemplateResolver, SpringWebFluxTemplateEngine, ThymeleafReactiveViewResolver등의 일부 Bean 선언이 포함되어 있다. 자세한 내용은 Thymeleaf+Spring와 WebFlux 통합 발표을 참조해라.

1.9.2. FreeMarker

Web MVC

Apache FreeMarker는 HTML에서 메일 등의 모든 종류의 텍스트 출력을 생성하기 위한 템플릿 엔진이다. Spring Framework는 Spring WebFlux와 FreeMarker 템플릿을 사용하는 기본 통합 기능이 있다.

뷰 설정(View Configuration)

Web MVC

다음의 예제는 FreeMarker를 뷰 기술로 설정하는 방법을 보여준다.

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.freeMarker();
    }

    // Configure FreeMarker...

    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("classpath:/templates/freemarker");
        return configurer;
    }
}

Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

    override fun configureViewResolvers(registry: ViewResolverRegistry) {
        registry.freeMarker()
    }

    // Configure FreeMarker...

    @Bean
    fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
        setTemplateLoaderPath("classpath:/templates/freemarker")
    }
}

템플릿은 이전 예제에 표시된 FreeMarkerConfigurer로 지정된 디렉터리에 저장해야 한다. 위의 구성에서 컨트롤러가 뷰 이름 welcome을 반환하는 경우, 리졸버는 classpath:/templates/freemarker/welcome.ftl 템플릿을 찾는다.

FreeMarker 설정

Web MVC

FreeMarkerConfigurer Bean에서 적절한 Bean 프로퍼티를 설정함으로써 FreeMarker의 “설정"과 “SharedVariables"를 FreeMarker Configuration 객체(Spring에 의해 관리됨)에 직접 전달할 수 있다. freemarkerSettings 속성은 java.util.Properties 객체가 필요하고, freemarkerVariables 속성을 java.util.Map해야 한다. 다음 예제는 FreeMarkerConfigurer 사용 방법을 보여준다.

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    // ...

    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        Map<String, Object> variables = new HashMap<>();
        variables.put("xml_escape", new XmlEscape());

        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("classpath:/templates");
        configurer.setFreemarkerVariables(variables);
        return configurer;
    }
}

Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

    // ...

    @Bean
    fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
        setTemplateLoaderPath("classpath:/templates")
        setFreemarkerVariables(mapOf("xml_escape" to XmlEscape()))
    }
}

Configuration 객체에 적용되는 설정 및 변수에 대한 자세한 내용은 FreeMarker 문서를 참조해라.

폼 처리(Form Handling)

Web MVC

Spring은 특히 <spring:bind/> 요소가 포함된 JSP에서 사용하는 태그 라이브러리를 제공한다. 이 요소는 양식은 주로 양식 뒷면 객체의 값을 표시하여 Web 또는 비즈니스 계층의 Validator에서 검증 실패의 결과를 볼 수 있다. Spring은 FreeMarker와 같은 기능을 지원하고 있지만, 폼 입력 요소 자체를 생성하기 위한 추가의 편리한 매크로가 있다.

바인딩 매크로(The Bind Macros)

Web MVC

매크로의 표준 세트는 FreeMarker의 spring-webflux.jar 파일에서 유지되기 때문에, 적절하게 구성된 응용 프로그램에서 항상 사용할 수 있다.

Spring 템플릿 라이브러리에 정의되어 있는 매크로의 일부는 내부(비공개)로 간주되지만 매크로 정의는 그러한 범위는 존재하지 않고, 호출되는 코드와 사용자 템플릿에 모든 매크로가 표시된다. 다음 섹션에서는 템플릿에서 직접 호출할 필요가 있는 매크로에만 초점을 맞추고 있다. 매크로 코드를 직접 표시하는 경우, 파일 spring.ftl이라고 하는 org.springframework.web.reactive.result.view.freemarker 패키지에 포함되어 있다.

바인딩 지원에 대한 자세한 내용은 Spring MVC의 간단한 바인딩을 참조해라.

폼 매크로(Form Macros)

FreeMarker 템플릿에 대한 Spring의 폼 매크로 지원에 대한 자세한 내용은 Spring MVC 문서의 다음 섹션을 참조해라.

1.9.3. 스크립트보기

Web MVC

Spring Framework에는 JSR-223 Java 스크립트 엔진에서 실행할 수 있는 템플릿 라이브러리에 Spring WebFlux을 사용하기 위한 기본 제공 통합이 포함되어 있다. 다음 표는 다양한 스크립트 엔진에서 테스트 템플릿 라이브러리를 보여준다.

스크립트 라이브러리 스크립트 엔진
Handlebars Nashorn
Mustache Nashorn
React Nashorn
EJS Nashorn
ERB JRuby
String templates Jython
Kotlin 스크립트 템플릿 Kotlin

다른 스크립트 엔진을 통합하기 위한 기본적인 규칙은 ScriptEngineInvocable 인터페이스를 구현할 필요가 있다는 것이다.

요구 사항

Web MVC

클래스 경로에 스크립트 엔진이 필요한다. 자세한 내용은 스크립트 엔진에 따라 달라진다.

  • Nashorn JavaScript 엔진은 Java 8+가 포함되어 있다. 사용 가능한 최신 업데이트 자료를 사용하는 것이 좋다.
  • JRuby는 Ruby 지원의 종속성으로 추가해야 한다.
  • Jython는 Python 지원의 종속성으로 추가해야 한다.
  • Kotlin 스크립트를 지원하려면 org.jetbrains.kotlin:kotlin-script-util 종속성과 org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory 행을 포함하는 META-INF/services/javax.script.ScriptEngineFactory 파일을 추가해야 한다. 자세한 내용은 예제을 참조해라.

스크립트 템플릿 라이브러리가 필요한다. Javascript에서 이렇게 하나의 방법은 WebJars을 사용하는 것이다.

스크립트 템플릿(Script Templates)

Web MVC

ScriptTemplateConfigurer Bean을 선언하고 사용하는 스크립트 엔진을 로드하는 스크립트 파일 템플릿을 렌더링하기 위해 호출하는 함수 등을 지정할 수 있다. 다음 예제에서는 Mustache 템플릿과 Nashorn JavaScript 엔진을 사용하고 있다.

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.scriptTemplate();
    }

    @Bean
    public ScriptTemplateConfigurer configurer() {
        ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
        configurer.setEngineName("nashorn");
        configurer.setScripts("mustache.js");
        configurer.setRenderObject("Mustache");
        configurer.setRenderFunction("render");
        return configurer;
    }
}

Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

    override fun configureViewResolvers(registry: ViewResolverRegistry) {
        registry.scriptTemplate()
    }

    @Bean
    fun configurer() = ScriptTemplateConfigurer().apply {
        engineName = "nashorn"
        setScripts("mustache.js")
        renderObject = "Mustache"
        renderFunction = "render"
    }
}

render 함수는 다음 매개 변수로 호출된다.

  • String template: 템플릿의 내용
  • Map model: 뷰 모델
  • RenderingContext renderingContext: 응용 프로그램 컨텍스트 로케일 템플릿 로더, URL에 대한 액세스를 제공하는 RenderingContext(5.0 이상)

Mustache.render()은 서명과 기본적으로 호환성이 있기 때문에 직접 호출 할 수 있다.

템플릿 기술로 사용자가 필요한 경우 사용자 정의 렌더링 기능을 구현하는 스크립트를 제공 할 수 있다. 예 : Handlerbars (영문) 사용하기 전에 템플릿을 컴파일해야 서버 사이드 스크립트 엔진에서 사용할 수없는 브라우저 기능을 에뮬레이트하기 위해 polyfill가 필요한다. 다음 예제에서는 사용자 지정 렌더링 함수를 설정하는 방법을 보여준다.

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.scriptTemplate();
    }

    @Bean
    public ScriptTemplateConfigurer configurer() {
        ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
        configurer.setEngineName("nashorn");
        configurer.setScripts("polyfill.js", "handlebars.js", "render.js");
        configurer.setRenderFunction("render");
        configurer.setSharedEngine(false);
        return configurer;
    }
}

Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

    override fun configureViewResolvers(registry: ViewResolverRegistry) {
        registry.scriptTemplate()
    }

    @Bean
    fun configurer() = ScriptTemplateConfigurer().apply {
        engineName = "nashorn"
        setScripts("polyfill.js", "handlebars.js", "render.js")
        renderFunction = "render"
        isSharedEngine = false
    }
}

Nashorn에서 실행되는 Handlebars과 React 등 동시 실행을 위해 설계되지 않은 템플릿 라이브러리에서 비 스레드 안전 스크립트 엔진을 사용하는 경우는 sharedEngine 속성을 false 설정해야 한다. 이 경우 이 버그 때문에 Java SE 8 update 60이 필요하지만, 일반적으로 최신의 Java SE 패치 릴리스를 사용하는 것이 좋습니다.

polyfill.js 다음 조각이 같이 Handlebars가 제대로 실행하는데 필요한 window 개체만 정의한다.

var window = {};

이 기본 render.js 구현은 템플릿을 사용하기 전에 컴파일한다. 또한 실전 대응의 구현에서는 캐시 된 템플릿 또는 미리 컴파일 된 템플릿을 저장하고 재사용해야 한다. 이것은 필요한 사용자 (예를 들어, 템플릿 엔진의 구성 관리)뿐만 아니라 스크립트 측에서도 실행할 수 있다. 다음 예제는 템플릿의 컴파일 방법을 보여준다.

function render(template, model) {
    var compiledTemplate = Handlebars.compile(template);
    return compiledTemplate(model);
}

다른 구성 예는 Spring Framework 단위 테스트, Java, resources을 참조해라.

1.9.4. JSON과 XML

Web MVC

내용 협상(Content Negotiation )의 목적은 클라이언트에서 요청된 콘텐츠 형식에 따라 HTML 템플리트를 사용하여 모델의 렌더링과 다른 형식 (JSON 또는 XML 등)로 렌더링을 전환 할 수 있는 편리한다. 이렇게 하는 것을 지원하기 위해 Spring WebFlux은 HttpMessageWriterView을 제공한다. 이것을 사용하여 Jackson2JsonEncoder, Jackson2SmileEncoder, Jaxb2XmlEncoder 등을 spring-web에서 사용 가능한 코덱 중 하나를 플러그인 할 수 있다.

다른 뷰 기술과 달리 HttpMessageWriterViewViewResolver를 필요로 하지 않고, 대신 기본 뷰로 설정 된다. 다른 HttpMessageWriter 인스턴스 또는 Encoder 인스턴스를 감싸고 이러한 기본 뷰를 하나 이상 구성 할 수 있다. 요청된 콘텐츠 형식에 일치하는 항목이 실행될 때 사용된다.

대부분의 경우 모델에 여러 속성이 포함된다. 어느 것을 직렬화하는 방법을 결정하기 위해 렌더링에 사용하는 모델 속성의 이름으로 HttpMessageWriterView을 구성 할 수 있다. 모델에 포함된 속성이 하나의 경우 그 특성이 사용된다.




최종 수정 : 2021-04-12