Loading...
Spring Framework Reference Documentation 7.0.2의 View Technologies의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
See equivalent in the Servlet stack
Spring WebFlux에서 view의 렌더링은 플러그형입니다. Thymeleaf, FreeMarker 또는 다른 view technology를 사용할지 여부는 주로 설정 변경의 문제입니다. 이 장에서는 Spring WebFlux와 통합된 view technologies를 다룹니다.
view 렌더링에 대한 더 많은 컨텍스트는 View Resolution을 참조하십시오.
Spring WebFlux 애플리케이션의 views는 애플리케이션의 내부 신뢰 경계<br>내에 존재합니다. Views는 애플리케이션 컨텍스트의 beans에 접근할 수 있으므로,<br>template이 외부 소스에 의해 수정 가능한 애플리케이션에서는 Spring WebFlux template support를<br>사용하지 않을 것을 권장합니다. 이는 보안에 영향을 줄 수 있기 때문입니다.
See equivalent in the Servlet stack
Thymeleaf는 자연스러운 HTML templates를 강조하는 modern server-side Java template engine으로, 브라우저에서 더블 클릭만으로 미리 볼 수 있습니다. 이는 (예를 들어 디자이너에 의한) UI templates에 대한 독립적인 작업에 매우 유용하며, 실행 중인 서버가 필요하지 않습니다.
Thymeleaf는 광범위한 기능 세트를 제공하며, 활발히 개발 및 유지 관리되고 있습니다. 보다 완전한 소개는 Thymeleaf project home page를 참조하십시오.
Spring WebFlux와의 Thymeleaf integration은 Thymeleaf project에 의해 관리됩니다.
설정은 SpringResourceTemplateResolver, SpringWebFluxTemplateEngine,
ThymeleafReactiveViewResolver와 같은 몇 가지 bean 선언을 포함합니다.
자세한 내용은 Thymeleaf+Spring과 WebFlux integration announcement를 참조하십시오.
See equivalent in the Servlet stack
Apache FreeMarker는 HTML에서 email 및 기타 모든 종류의 텍스트 출력을 생성하기 위한 template engine입니다. Spring Framework는 Spring WebFlux를 FreeMarker templates와 함께 사용하기 위한 내장 integration을 제공합니다.
See equivalent in the Servlet stack
다음 예제는 FreeMarker를 view technology로 설정하는 방법을 보여줍니다:
1@Configuration 2@EnableWebFlux 3public class WebConfig implements WebFluxConfigurer { 4 5 @Override 6 public void configureViewResolvers(ViewResolverRegistry registry) { 7 registry.freeMarker(); 8 } 9 10 // Configure FreeMarker... 11 12 @Bean 13 public FreeMarkerConfigurer freeMarkerConfigurer() { 14 FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); 15 configurer.setTemplateLoaderPath("classpath:/templates/freemarker"); 16 return configurer; 17 } 18}
1@Configuration 2@EnableWebFlux 3class WebConfig : WebFluxConfigurer { 4 5 override fun configureViewResolvers(registry: ViewResolverRegistry) { 6 registry.freeMarker() 7 } 8 9 // Configure FreeMarker... 10 11 @Bean 12 fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply { 13 setTemplateLoaderPath("classpath:/templates/freemarker") 14 } 15}
templates는 앞의 예제에 표시된 대로 FreeMarkerConfigurer에 의해 지정된 디렉터리에 저장해야 합니다.
앞의 설정이 주어졌을 때, controller가 view name welcome을 반환하면,
resolver는 classpath:/templates/freemarker/welcome.ftl template을 찾습니다.
See equivalent in the Servlet stack
FreeMarker 'Settings'와 'SharedVariables'를 FreeMarkerConfigurer bean의 적절한 bean
properties를 설정하여 Spring이 관리하는 FreeMarker Configuration 객체에 직접 전달할 수 있습니다.
freemarkerSettings property는 java.util.Properties 객체가 필요하고,
freemarkerVariables property는 java.util.Map이 필요합니다.
다음 예제는 FreeMarkerConfigurer를 사용하는 방법을 보여줍니다:
1@Configuration 2@EnableWebFlux 3public class WebConfig implements WebFluxConfigurer { 4 5 // ... 6 7 @Bean 8 public FreeMarkerConfigurer freeMarkerConfigurer() { 9 Map<String, Object> variables = new HashMap<>(); 10 variables.put("xml_escape", new XmlEscape()); 11 12 FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); 13 configurer.setTemplateLoaderPath("classpath:/templates"); 14 configurer.setFreemarkerVariables(variables); 15 return configurer; 16 } 17}
1@Configuration 2@EnableWebFlux 3class WebConfig : WebFluxConfigurer { 4 5 // ... 6 7 @Bean 8 fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply { 9 setTemplateLoaderPath("classpath:/templates") 10 setFreemarkerVariables(mapOf("xml_escape" to XmlEscape())) 11 } 12}
settings와 variables가 Configuration 객체에 적용되는 방식에 대한 자세한 내용은
FreeMarker documentation을 참조하십시오.
See equivalent in the Servlet stack
Spring은 JSP에서 사용할 수 있는 tag library를 제공하며, 그 중에는 <spring:bind/> element도 있습니다.
이 element는 주로 form-backing objects에서 values를 표시하고 web 또는 business tier의
Validator에서 발생한 실패한 validation 결과를 표시할 수 있게 해줍니다.
Spring은 FreeMarker에서 동일한 기능을 위한 support도 제공하며, form input elements 자체를 생성하기 위한 추가적인 편의 매크로도 제공합니다.
See equivalent in the Servlet stack
표준 macro set은 FreeMarker용 spring-webflux.jar file 내에 유지되므로,
적절히 설정된 애플리케이션에서는 항상 사용할 수 있습니다.
Spring templating libraries에 정의된 일부 macros는 internal (private)로 간주되지만, macro 정의에는 이러한 scoping이 없으므로 모든 macros는 호출 코드와 user templates에 모두 보입니다.
다음 섹션에서는 templates 내에서 직접 호출해야 하는 macros에만
집중합니다. macro code를 직접 보고 싶다면, file 이름은 spring.ftl이며
org.springframework.web.reactive.result.view.freemarker package에 있습니다.
binding support에 대한 추가적인 세부 사항은 Spring MVC의 Simple Binding을 참조하십시오.
FreeMarker templates에 대한 Spring의 form macro support에 대한 자세한 내용은 다음 Spring MVC documentation 섹션을 참조하십시오.
See equivalent in the Servlet stack
Spring Framework는 Spring WebFlux를 JSR-223 Java scripting engine 위에서 실행될 수 있는 어떤 templating library와도 함께 사용할 수 있는 내장 integration을 제공합니다. 다음 표는 서로 다른 script engines에서 test해 본 templating libraries를 보여줍니다:
| Scripting Library | Scripting Engine |
|---|---|
| Handlebars | Nashorn |
| Mustache | Nashorn |
| React | Nashorn |
| EJS | Nashorn |
| ERB | JRuby |
| String templates | Jython |
| Kotlin Script templating | Kotlin |
다른 script engine을 통합하기 위한 기본 규칙은 해당 engine이<br>
ScriptEngine과Invocable인터페이스를 구현해야 한다는 것입니다.
See equivalent in the Servlet stack
classpath에 script engine이 있어야 하며, 이에 대한 세부 사항은 script engine마다 다릅니다:
org.jetbrains.kotlin:kotlin-script-util 의존성과
META-INF/services/javax.script.ScriptEngineFactory file에
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory
line을 추가해야 합니다. 자세한 내용은
this example을 참조하십시오.script templating library가 필요합니다. JavaScript의 경우 이를 수행하는 한 가지 방법은 WebJars를 사용하는 것입니다.
See equivalent in the Servlet stack
사용할 script engine, load할 script files, templates를 렌더링하기 위해 호출할 function 등을 지정하기 위해
ScriptTemplateConfigurer bean을 선언할 수 있습니다.
다음 예제는 Mustache templates와 Nashorn JavaScript engine을 사용합니다:
1@Configuration 2@EnableWebFlux 3public class WebConfig implements WebFluxConfigurer { 4 5 @Override 6 public void configureViewResolvers(ViewResolverRegistry registry) { 7 registry.scriptTemplate(); 8 } 9 10 @Bean 11 public ScriptTemplateConfigurer configurer() { 12 ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); 13 configurer.setEngineName("nashorn"); 14 configurer.setScripts("mustache.js"); 15 configurer.setRenderObject("Mustache"); 16 configurer.setRenderFunction("render"); 17 return configurer; 18 } 19}
1@Configuration 2@EnableWebFlux 3class WebConfig : WebFluxConfigurer { 4 5 override fun configureViewResolvers(registry: ViewResolverRegistry) { 6 registry.scriptTemplate() 7 } 8 9 @Bean 10 fun configurer() = ScriptTemplateConfigurer().apply { 11 engineName = "nashorn" 12 setScripts("mustache.js") 13 renderObject = "Mustache" 14 renderFunction = "render" 15 } 16}
render function은 다음 parameters로 호출됩니다:
String template: template contentMap model: view modelRenderingContext renderingContext: 애플리케이션 컨텍스트, locale, template loader,
URL (5.0부터)에 접근을 제공하는
RenderingContextMustache.render()는 이 시그니처와 네이티브하게 호환되므로, 직접 호출할 수 있습니다.
templating technology가 일부 customization을 필요로 하는 경우, custom render function을 구현하는 script를 제공할 수 있습니다. 예를 들어, Handlerbars는 templates를 사용하기 전에 compile해야 하며, 서버 측 script engine에서 사용할 수 없는 일부 브라우저 기능을 에뮬레이트하기 위해 polyfill이 필요합니다.
다음 예제는 custom render function을 설정하는 방법을 보여줍니다:
1@Configuration 2@EnableWebFlux 3public class WebConfig implements WebFluxConfigurer { 4 5 @Override 6 public void configureViewResolvers(ViewResolverRegistry registry) { 7 registry.scriptTemplate(); 8 } 9 10 @Bean 11 public ScriptTemplateConfigurer configurer() { 12 ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); 13 configurer.setEngineName("nashorn"); 14 configurer.setScripts("polyfill.js", "handlebars.js", "render.js"); 15 configurer.setRenderFunction("render"); 16 configurer.setSharedEngine(false); 17 return configurer; 18 } 19}
1@Configuration 2@EnableWebFlux 3class WebConfig : WebFluxConfigurer { 4 5 override fun configureViewResolvers(registry: ViewResolverRegistry) { 6 registry.scriptTemplate() 7 } 8 9 @Bean 10 fun configurer() = ScriptTemplateConfigurer().apply { 11 engineName = "nashorn" 12 setScripts("polyfill.js", "handlebars.js", "render.js") 13 renderFunction = "render" 14 isSharedEngine = false 15 } 16}
sharedEngineproperty를false로 설정하는 것은 Handlebars나<br>Nashorn에서 실행되는 React와 같이 concurrency를 위해 설계되지 않은 templating libraries와<br>함께 non-thread-safe script engines를 사용할 때 필요합니다. 이 경우<br>이 bug로 인해 Java SE 8 update 60이 필요하지만,<br>일반적으로 최신 Java SE 패치 릴리스를 사용하는 것이 권장됩니다.
polyfill.js는 Handlebars가 제대로 실행하는 데 필요한 window 객체만 정의하며,
다음 snippet과 같습니다:
1var window = {};
이 기본 render.js 구현은 template을 사용하기 전에 compile합니다.
운영 환경에 적합한 구현은 캐시된 templates 또는 사전 컴파일된 templates를 저장하고 재사용해야 합니다.
이는 template engine 설정 관리와 같은 필요한 모든 customization과 함께
script 측에서 수행할 수 있습니다.
다음 예제는 template을 compile하는 방법을 보여줍니다:
1function render(template, model) { 2 var compiledTemplate = Handlebars.compile(template); 3 return compiledTemplate(model); 4}
더 많은 설정 예제는 Spring Framework 단위 테스트, Java와 resources를 확인하십시오.
See equivalent in the Servlet stack
HTMX와 Hotwire Turbo는 클라이언트가 JSON이 아닌 HTML로 서버 업데이트를 수신하는 HTML-over-the-wire 접근 방식을 강조합니다. 이를 통해 많은 JavaScript를 작성하지 않거나 전혀 작성하지 않고도 SPA(single page app)의 이점을 누릴 수 있습니다. 좋은 개요와 더 많은 정보를 위해 각자의 웹사이트를 방문하십시오.
Spring WebFlux에서 view 렌더링은 일반적으로 하나의 view와 하나의 model을 지정하는 것을 포함합니다. 그러나 HTML-over-the-wire에서는 브라우저가 페이지의 서로 다른 부분을 업데이트하는 데 사용할 수 있는 여러 HTML fragments를 보내는 것이 일반적인 capability입니다.
이를 위해 controller methods는
Collection<Fragment>를 반환할 수 있습니다. 예를 들면 다음과 같습니다:
1@GetMapping 2List<Fragment> handle() { 3 return List.of(Fragment.create("posts"), Fragment.create("comments")); 4}
1@GetMapping 2fun handle(): List<Fragment> { 3 return listOf(Fragment.create("posts"), Fragment.create("comments")) 4}
동일한 작업을 전용 type인 FragmentsRendering을 반환하여 수행할 수도 있습니다:
1@GetMapping 2FragmentsRendering handle() { 3 return FragmentsRendering.fragment("posts").fragment("comments").build(); 4}
1@GetMapping 2fun handle(): FragmentsRendering { 3 return FragmentsRendering.fragment("posts").fragment("comments").build() 4}
각 fragment는 독립적인 model을 가질 수 있으며, 해당 model은 요청에 대한 공유 model에서 attributes를 상속합니다.
HTMX와 Hotwire Turbo는 SSE(server-sent events)를 통한 스트리밍 업데이트를 지원합니다.
controller는 Flux<Fragment> 또는 ReactiveAdapterRegistry를 통해
Reactive Streams Publisher로 adaptable한 다른 reactive producer와 함께 FragmentsRendering을
생성할 수 있습니다.
FragmentsRendering wrapper 없이 Flux<Fragment>를 직접 반환하는 것도 가능합니다.
See equivalent in the Servlet stack
Content Negotiation 목적상, 클라이언트가 요청한 content type에 따라 model을 HTML template로 렌더링하거나 JSON 또는 XML과 같은 다른 format으로 렌더링할 수 있으면 유용합니다.
이를 지원하기 위해 Spring WebFlux는 HttpMessageWriterView를 제공하며,
이를 사용하여 spring-web의 사용 가능한
Codecs 중
JacksonJsonEncoder, JacksonSmileEncoder, Jaxb2XmlEncoder와 같은 어떤 것이든 플러그인할 수 있습니다.
다른 view technologies와 달리, HttpMessageWriterView는 ViewResolver를 필요로 하지 않으며,
대신 기본 view로서
configured됩니다.
서로 다른 HttpMessageWriter 인스턴스 또는 Encoder 인스턴스를 wrapping하는
하나 이상의 기본 views를 설정할 수 있습니다. 요청된 content type과 일치하는 것이
런타임에 사용됩니다.
대부분의 경우, model은 여러 attributes를 포함합니다. 어느 것을 직렬화할지 결정하기 위해,
렌더링에 사용할 model attribute의 이름으로 HttpMessageWriterView를 설정할 수 있습니다.
model에 attribute가 하나만 있는 경우, 해당 attribute가 사용됩니다.
HTTP Caching
WebFlux Config