Loading...
Spring Framework Reference Documentation 7.0.2의 WebFlux Config의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
WebFlux Java configuration은 annotated controller나 functional endpoint로 요청을 처리하는 데 필요한 컴포넌트들을 선언하고, 구성을 커스터마이징할 수 있는 API를 제공합니다. 이는 Java configuration에 의해 생성되는 하위 빈들을 이해할 필요는 없다는 것을 의미합니다.
그러나 이를 이해하기 원한다면, WebFluxConfigurationSupport에서 확인하거나 Special Bean Types에서 그것들이 무엇인지 더 읽어볼 수 있습니다.
configuration API에서 제공되지 않는 더 고급 커스터마이징의 경우, Advanced Configuration Mode를 통해 configuration에 대한 완전한 제어권을 얻을 수 있습니다.
다음 예제에서 보듯이, Java config에서 @EnableWebFlux 어노테이션을 사용할 수 있습니다:
1@Configuration 2@EnableWebFlux 3public class WebConfig { 4}
1@Configuration 2@EnableWebFlux 3class WebConfig
Spring Boot를 사용할 때는 Spring Boot WebFlux customization을 유지하기 위해<br>
@EnableWebFlux없이WebFluxConfigurer타입의@Configuration클래스를 사용하고 싶을 수 있습니다.<br>자세한 내용은<br>WebFlux config API section과<br>전용 Spring Boot documentation을 참조하십시오.
앞의 예제는 여러 Spring WebFlux infrastructure bean을 등록하고, classpath에 사용 가능한 의존성들(예: JSON, XML 등)에 맞게 조정합니다.
Java configuration에서 다음 예제와 같이 WebFluxConfigurer 인터페이스를 구현할 수 있습니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 // Implement configuration methods... 5}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 // Implement configuration methods... 5}
기본적으로 다양한 숫자 및 날짜 타입에 대한 포매터가 설치되며, 필드와 파라미터에 대한
@NumberFormat, @DurationFormat, @DateTimeFormat을 통한 커스터마이징을 지원합니다.
Java config에서 커스텀 포매터와 컨버터를 등록하려면 다음을 사용하십시오:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void addFormatters(FormatterRegistry registry) { 6 // ... 7 } 8 9}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun addFormatters(registry: FormatterRegistry) { 5 // ... 6 } 7}
기본적으로 Spring WebFlux는 날짜 값을 파싱 및 포매팅할 때 요청 Locale을 고려합니다. 이는 날짜가 "input" form 필드를 가진 문자열로 표현되는 form에서 동작합니다.
그러나 "date"와 "time" form 필드의 경우, 브라우저는 HTML 명세에 정의된 고정 포맷을 사용합니다. 이러한 경우 날짜와 시간 포매팅은 다음과 같이 커스터마이징할 수 있습니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void addFormatters(FormatterRegistry registry) { 6 DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); 7 registrar.setUseIsoFormat(true); 8 registrar.registerFormatters(registry); 9 } 10}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun addFormatters(registry: FormatterRegistry) { 5 val registrar = DateTimeFormatterRegistrar() 6 registrar.setUseIsoFormat(true) 7 registrar.registerFormatters(registry) 8 } 9}
언제
FormatterRegistrar구현을 사용해야 하는지에 대한 더 많은 정보는<br>FormatterRegistrarSPI<br>와FormattingConversionServiceFactoryBean을 참조하십시오.
기본적으로, classpath에 Bean Validation이 존재하면
(예: Hibernate Validator), LocalValidatorFactoryBean이 전역
validator로 등록되어 @Controller 메서드 argument에서
@Valid와 @Validated와 함께 사용됩니다.
다음 예제와 같이, Java configuration에서 전역 Validator 인스턴스를 커스터마이징할 수 있습니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public Validator getValidator() { 6 // ... 7 } 8 9}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun getValidator(): Validator { 5 // ... 6 } 7 8}
다음 예제와 같이, Validator 구현을 로컬하게 등록할 수도 있습니다:
1@Controller 2public class MyController { 3 4 @InitBinder 5 protected void initBinder(WebDataBinder binder) { 6 binder.addValidators(new FooValidator()); 7 } 8 9}
1@Controller 2class MyController { 3 4 @InitBinder 5 protected fun initBinder(binder: WebDataBinder) { 6 binder.addValidators(FooValidator()) 7 } 8}
다른 곳에서
LocalValidatorFactoryBean을 주입받아야 하는 경우, 빈을 생성하고<br>MVC config에 선언된 것과 충돌을 피하기 위해@Primary로 표시하십시오.
요청으로부터 @Controller 인스턴스에 대해 Spring WebFlux가 요청된 미디어 타입을
결정하는 방식을 구성할 수 있습니다. 기본적으로 Accept 헤더만 확인하지만,
query 파라미터 기반 전략도 활성화할 수 있습니다.
다음 예제는 요청된 콘텐츠 타입 resolution을 커스터마이징하는 방법을 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { 6 // ... 7 } 8}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) { 5 // ... 6 } 7}
다음 예제는 요청과 응답 body가 읽히고 쓰이는 방식을 커스터마이징하는 방법을 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { 6 configurer.defaultCodecs().maxInMemorySize(512 * 1024); 7 } 8}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) { 5 configurer.defaultCodecs().maxInMemorySize(512 * 1024) 6 } 7}
ServerCodecConfigurer는 기본 리더와 라이터의 집합을 제공합니다. 이를 사용해 더 많은
리더와 라이터를 추가하거나, 기본 것을 커스터마이징하거나, 기본 것을 완전히 교체할 수 있습니다.
Jackson의 경우, Jackson의 기본 프로퍼티를 구성하기 위해 JsonMapper.Builder와 같은
Jackson 포맷 전용 빌더를 사용하는 것을 고려하십시오.
다음 예제는 뷰 resolution을 구성하는 방법을 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureViewResolvers(ViewResolverRegistry registry) { 6 // ... 7 } 8}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureViewResolvers(registry: ViewResolverRegistry) { 5 // ... 6 } 7}
ViewResolverRegistry에는 Spring Framework가 통합하는 뷰 기술을 위한 shortcut이 있습니다.
다음 예제는 FreeMarker를 사용하며(이는 기반 FreeMarker 뷰 기술을 구성하는 것도 필요합니다):
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureViewResolvers(ViewResolverRegistry registry) { 6 registry.freeMarker(); 7 } 8 9 // Configure Freemarker... 10 11 @Bean 12 public FreeMarkerConfigurer freeMarkerConfigurer() { 13 FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); 14 configurer.setTemplateLoaderPath("classpath:/templates"); 15 return configurer; 16 } 17}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureViewResolvers(registry: ViewResolverRegistry) { 5 registry.freeMarker() 6 } 7 8 // Configure Freemarker... 9 10 @Bean 11 fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply { 12 setTemplateLoaderPath("classpath:/templates") 13 } 14}
다음 예제와 같이, 어떤 ViewResolver 구현도 연결할 수 있습니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureViewResolvers(ViewResolverRegistry registry) { 6 ViewResolver resolver = /* ... */ ; 7 registry.viewResolver(resolver); 8 } 9}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureViewResolvers(registry: ViewResolverRegistry) { 5 val resolver: ViewResolver = /* ... */ 6 registry.viewResolver(resolver) 7 } 8}
Content Negotiation을 지원하고
HTML 이외의 다른 포맷을 뷰 resolution을 통해 렌더링하려면,
spring-web의 사용 가능한 Codecs 중 어느 것이든
받아들이는 HttpMessageWriterView 구현을 기반으로 하나 이상의 기본 뷰를 구성할 수 있습니다.
다음 예제는 그 방법을 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureViewResolvers(ViewResolverRegistry registry) { 6 registry.freeMarker(); 7 8 JacksonJsonEncoder encoder = new JacksonJsonEncoder(); 9 registry.defaultViews(new HttpMessageWriterView(encoder)); 10 } 11 12 // ... 13}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureViewResolvers(registry: ViewResolverRegistry) { 5 registry.freeMarker() 6 7 val encoder = JacksonJsonEncoder() 8 registry.defaultViews(HttpMessageWriterView(encoder)) 9 } 10 11 // ... 12}
Spring WebFlux와 통합된 뷰 기술에 대한 더 많은 내용은 View Technologies를 참조하십시오.
이 옵션은 정적 리소스를
Resource 기반 location 목록에서 제공하는 편리한 방법을 제공합니다.
다음 예제에서, /resources로 시작하는 요청이 주어지면, 상대 경로는
classpath의 /static에 상대적인 정적 리소스를 찾고 제공하는 데 사용됩니다.
리소스는 브라우저 캐시를 최대한 사용하고 브라우저가 수행하는 HTTP 요청을 줄이기 위해
1년 후 만료로 제공됩니다.
Last-Modified 헤더도 평가되며, 존재하는 경우
304 상태 코드가 반환됩니다. 다음 listing은 예제를 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void addResourceHandlers(ResourceHandlerRegistry registry) { 6 registry.addResourceHandler("/resources/**") 7 .addResourceLocations("/public", "classpath:/static/") 8 .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)); 9 } 10 11}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun addResourceHandlers(registry: ResourceHandlerRegistry) { 5 registry.addResourceHandler("/resources/**") 6 .addResourceLocations("/public", "classpath:/static/") 7 .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)) 8 } 9}
static resource에 대한 HTTP caching support도 참조하십시오.
리소스 핸들러는 또한
ResourceResolver 구현과
ResourceTransformer 구현의 체인을 지원하며,
이를 사용해 최적화된 리소스를 다루는 툴체인을 만들 수 있습니다.
VersionResourceResolver를 사용해 content에서 계산된 MD5 해시, 고정 애플리케이션 버전,
또는 기타 정보를 기반으로 버전이 있는 리소스 URL을 사용할 수 있습니다.
ContentVersionStrategy(MD5 해시)는 몇 가지 주목할 만한 예외(JavaScript 리소스를
모듈 로더와 함께 사용하는 경우 등)를 제외하면 좋은 선택입니다.
다음 예제는 Java configuration에서 VersionResourceResolver를 사용하는 방법을 보여줍니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void addResourceHandlers(ResourceHandlerRegistry registry) { 6 registry.addResourceHandler("/resources/**") 7 .addResourceLocations("/public/") 8 .resourceChain(true) 9 .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**")); 10 } 11 12}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun addResourceHandlers(registry: ResourceHandlerRegistry) { 5 registry.addResourceHandler("/resources/**") 6 .addResourceLocations("/public/") 7 .resourceChain(true) 8 .addResolver(VersionResourceResolver().addContentVersionStrategy("/**")) 9 } 10 11}
ResourceUrlProvider를 사용해 URL을 리라이트하고, 전체 resolver 및 transformer 체인을 적용할 수 있습니다
(예: 버전 삽입). WebFlux configuration은 ResourceUrlProvider를 제공하므로 다른 곳에 주입할 수 있습니다.
Spring MVC와 달리, 현재 WebFlux에서는 resolver와 transformer의 논블로킹 체인을 사용할 수 있는
뷰 기술이 없기 때문에 정적 리소스 URL을 투명하게 리라이트하는 방법이 없습니다.
로컬 리소스만 제공하는 경우, 우회 방법은 ResourceUrlProvider를 직접 사용하고(예: 커스텀 element를 통해)
블로킹하는 것입니다.
EncodedResourceResolver(예: Gzip, Brotli 인코딩)와
VersionedResourceResolver를 둘 다 사용할 때는, 항상 인코딩되지 않은 파일을 기반으로
content 기반 버전이 안정적으로 계산되도록 그 순서로 등록해야 합니다.
WebJars의 경우,
/webjars/jquery/1.2.0/jquery.min.js와 같은 버전이 있는 URL이 이를 사용하는 데 권장되며 가장 효율적인 방법입니다.
관련 리소스 location은 Spring Boot에서 기본으로 구성되며(또는 ResourceHandlerRegistry를 통해 수동으로
구성할 수 있으며), org.webjars:webjars-locator-lite 의존성을 추가할 필요가 없습니다.
/webjars/jquery/jquery.min.js와 같은 버전이 없는 URL은
classpath에 org.webjars:webjars-locator-lite 라이브러리가 존재하면 자동으로 등록되는
WebJarsResourceResolver를 통해 지원됩니다. resolver는 jar의 버전을 포함하도록 URL을 리라이트할 수 있으며,
또한 버전 없이 들어오는 URL과도 매칭할 수 있습니다.
예를 들어,
/webjars/jquery/jquery.min.js에서 /webjars/jquery/1.2.0/jquery.min.js로 매칭할 수 있습니다.
ResourceHandlerRegistry기반 Java configuration은 예를 들어 last-modified 동작 및 최적화된 리소스 resolution과 같이<br>세밀한 제어를 위한 추가 옵션을 제공합니다.
경로 매칭과 관련된 옵션을 커스터마이징할 수 있습니다. 개별 옵션에 대한 자세한 내용은
PathMatchConfigurer javadoc을 참조하십시오.
다음 예제는 PathMatchConfigurer를 사용하는 방법을 보여줍니다:
1import org.springframework.context.annotation.Configuration; 2import org.springframework.web.bind.annotation.RestController; 3import org.springframework.web.method.HandlerTypePredicate; 4import org.springframework.web.reactive.config.PathMatchConfigurer; 5import org.springframework.web.reactive.config.WebFluxConfigurer; 6 7@Configuration 8public class WebConfig implements WebFluxConfigurer { 9 10 @Override 11 public void configurePathMatching(PathMatchConfigurer configurer) { 12 configurer.addPathPrefix( 13 "/api", HandlerTypePredicate.forAnnotation(RestController.class)); 14 } 15}
1import org.springframework.context.annotation.Configuration 2import org.springframework.web.bind.annotation.RestController 3import org.springframework.web.method.HandlerTypePredicate 4import org.springframework.web.reactive.config.PathMatchConfigurer 5import org.springframework.web.reactive.config.WebFluxConfigurer 6 7@Configuration 8class WebConfig : WebFluxConfigurer { 9 10 override fun configurePathMatching(configurer: PathMatchConfigurer) { 11 configurer.addPathPrefix( 12 "/api", HandlerTypePredicate.forAnnotation(RestController::class.java)) 13 } 14}
Spring WebFlux는 디코딩된 path segment 값에 접근하기 위해 semicolon 내용이 제거된<br>(즉, path 또는 matrix variable) 요청 path의 파싱된 표현인
RequestPath에 의존합니다.<br>이는 Spring MVC와 달리, path 매칭 목적을 위해 요청 path를 디코딩할지 여부와<br>semicolon 내용을 제거할지 여부를 지정할 필요가 없다는 것을 의미합니다.<br>또한 Spring WebFlux는 Spring MVC와 달리 suffix 패턴 매칭을 지원하지 않으며,<br>Spring MVC에서도 이에 대한 의존을 줄이는 것을<br>recommend하고 있습니다. |
API 버저닝을 활성화하려면, WebFluxConfigurer의 ApiVersionConfigurer 콜백을 사용하십시오:
1@Configuration 2public class WebConfiguration implements WebFluxConfigurer { 3 4 @Override 5 public void configureApiVersioning(ApiVersionConfigurer configurer) { 6 configurer.useRequestHeader("API-Version"); 7 } 8}
1@Configuration 2class WebConfiguration : WebFluxConfigurer { 3 4 override fun configureApiVersioning(configurer: ApiVersionConfigurer) { 5 configurer.useRequestHeader("API-Version") 6 } 7}
아래에 나열된 built-in 옵션 중 하나를 통해 버전을 resolve하거나,
대안으로 커스텀 ApiVersionResolver를 사용할 수 있습니다:
path segment에서 resolve하려면, 버전을 포함할 것으로 예상되는 path segment의 인덱스를 지정해야 합니다. path segment는 URI 변수로 선언되어야 합니다(예: "/{version}", "/api/{version}" 등). 실제 이름은 중요하지 않습니다.
버전은 일반적으로 path의 시작 부분에 있으므로, Path Matching 옵션을 통해 모든 handler에 대한 공통 path prefix로 외부에서 구성하는 것을 고려하십시오.
기본적으로 버전은 SemanticVersionParser로 파싱되지만,
커스텀 ApiVersionParser를 구성할 수도 있습니다.
지원되는 버전은 편의를 위해 request mapping에 선언된 버전에서 투명하게 감지되지만,
WebFlux config의 플래그를 통해 이를 끄고, config에서 명시적으로 구성된 버전만 지원되는 것으로
간주할 수 있습니다. 지원되지 않는 버전을 가진 요청은
InvalidApiVersionException으로 거부되며 400 응답이 발생합니다.
클라이언트에게 deprecated된 버전에 대한 정보를 보내기 위해 ApiVersionDeprecationHandler를 설정할 수 있습니다.
내장 standard handler는 RFC 9745와
RFC 8594를 기반으로 "Deprecation", "Sunset",
"Link" 헤더를 설정할 수 있습니다.
API 버저닝이 구성되면, 요청 버전에 따라 controller method에 요청을 매핑하기 시작할 수 있습니다.
WebFlux Java config는 WebFlux에서 블로킹 실행을 커스터마이징할 수 있게 해줍니다.
다음과 같이 VirtualThreadTaskExecutor와 같은
VirtualThreadTaskExecutor를 제공하여
블로킹 controller 메서드를 별도의 스레드에서 호출되도록 할 수 있습니다:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public void configureBlockingExecution(BlockingExecutionConfigurer configurer) { 6 AsyncTaskExecutor executor = /* ... */; 7 configurer.setExecutor(executor); 8 } 9}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun configureBlockingExecution(configurer: BlockingExecutionConfigurer) { 5 val executor: AsyncTaskExecutor = /* ... */ 6 configurer.setExecutor(executor) 7 } 8}
기본적으로, 반환 타입이 구성된 ReactiveAdapterRegistry에 의해 인식되지 않는
controller 메서드는 블로킹으로 간주되지만, BlockingExecutionConfigurer를 통해
커스텀 controller 메서드 predicate를 설정할 수 있습니다.
WebFlux Java config는 WebSocket handler 호출을 지원하는 WebSocketHandlerAdapter 빈을 선언합니다.
이는 WebSocket 핸드셰이크 요청을 처리하기 위해 남은 작업은
SimpleUrlHandlerMapping을 통해 WebSocketHandler를 URL에 매핑하는 것뿐이라는 것을 의미합니다.
일부 경우에는 WebSocket 서버 프로퍼티를 구성할 수 있게 해주는
제공된 WebSocketService 서비스로 WebSocketHandlerAdapter 빈을 생성해야 할 수도 있습니다.
예를 들어:
1@Configuration 2public class WebConfig implements WebFluxConfigurer { 3 4 @Override 5 public WebSocketService getWebSocketService() { 6 TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy(); 7 strategy.setMaxSessionIdleTimeout(0L); 8 return new HandshakeWebSocketService(strategy); 9 } 10}
1@Configuration 2class WebConfig : WebFluxConfigurer { 3 4 override fun getWebSocketService(): WebSocketService { 5 val strategy = TomcatRequestUpgradeStrategy().apply { 6 setMaxSessionIdleTimeout(0L) 7 } 8 return HandshakeWebSocketService(strategy) 9 } 10}
@EnableWebFlux는 다음을 수행하는 DelegatingWebFluxConfiguration을 import합니다:
WebFluxConfigurer 구현을 감지하고 위임합니다.advanced mode의 경우, @EnableWebFlux를 제거하고 WebFluxConfigurer를 구현하는 대신
직접 DelegatingWebFluxConfiguration을 상속할 수 있으며, 다음 예제와 같습니다:
1@Configuration 2public class WebConfig extends DelegatingWebFluxConfiguration { 3 4 // ... 5}
1@Configuration 2class WebConfig : DelegatingWebFluxConfiguration() { 3 4 // ... 5}
WebConfig에 기존 메서드를 유지할 수 있지만, 이제 base 클래스의 빈 선언을 override할 수도 있고,
classpath에 다른 수의 WebMvcConfigurer 구현을 둘 수 있습니다.
View Technologies
HTTP/2