거북이 developer

Spring Webflux - Server Configuration 본문

Spring Framework

Spring Webflux - Server Configuration

흥부가귀막혀 2022. 3. 14. 13:06

Server Configuration

@EnableWebFlux

  • @EnableWebFlux 어노테이션을 정의할 경우 DelegatingWebFluxConfiguration 이 동작하는데 해당 Configuration 이 수행하는 기능은 다음과 같다.
    • WebFlux Application 운영을 위한 default spring configuration 을 정의해준다.
    • WebFluxConfigurer 를 정의한 configuration 이 있는지 탐지 및 customizing 된 내용 적용.
@Configuration
@EnableWebFlux
public class WebConfig {

    // ...
}
  • 만약 @EnableWebFlux 를 사용하지 않고 직접 핸들링 하고 싶다면, DelegatingWebFluxConfiguration 을 직접 정의하는 방법도 있다.
@Configuration
public class WebConfig extends DelegatingWebFluxConfiguration {

    // ...
}

WebFluxConfigurer

  • WebFlux Server side 에 대해 사용자가 정의할 수 있는 옵션을 제공한다.
  • WebFluxConfigurer 가 동작하기 위해서는 @EnableWebFlux 가 어딘가 선언되어 있어야 한다.
  • WebFluxConfigurer 에서 지원하는 옵션은 다음과 같다.
    • addFormatters(FormatterRegistry registry) : Conversion, formatting 관련 옵션
    • Validator getValidator() : 전역 Validator 정의
    • configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) : 요청 media type 에 대한 resolver 정의. default 는 accept header 를 체크하지만 필요에 따라 parameter base 의 resolver 정의도 가능하다.
    • configureHttpMessageCodecs(ServerCodecConfigurer configurer) : request, response read/write 에 관련된 codec 설정 정의. 요청 파라미터 body 사이즈를 256kb 이상 늘리고 싶다면 WebClient 에서 언급되었던 MaxInMemorySize 설정과 동일하게 설정해준다.
    • configureViewResolvers(ViewResolverRegistry registry) : view resolver 를 정의. 상세 설정 방법은 spring doc 참고.
    • addResourceHandlers(ResourceHandlerRegistry registry) : static resource 에 대한 handler 정의. 각 케이스별 상세 설정은 spring doc 참고.
    • configurePathMatch(PathMatchConfigurer configurer) : path matching 에 대한 사용자 옵션을 정의. 옵션에 대한 자세한 사항은 PathMatchConfigurer 참고
    • addCorsMappings(CorsRegistry registry) : Cors 에 대한 전역 설정 정의.
    • getWebSocketService() : WebSocket Handling 을 위한 WebSocketService 를 정의.

CORS

  • WebFluxConfigurer 의 addCorsMappings 을 설정하거나 CorsFilter 를 bean 으로 정의하면 전역 CORS 지원이 가능하다.

WebFluxConfigurer 설정

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("https://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);

        // Add more mappings...
    }
}

CorsFilter 설정

@Bean
CorsWebFilter corsFilter() {

    CorsConfiguration config = new CorsConfiguration();

    // Possibly...
    // config.applyPermitDefaultValues()

    config.setAllowCredentials(true);
    config.addAllowedOrigin("https://domain1.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);

    return new CorsWebFilter(source);
}

CORS 에 대한 custom 한 동작이 필요하다면 CorsConfiguration 를 구현하면 된다. 예를들어 domain 의 allow origin check 를 ant pattern 이나 정규표현식 방식으로 check 하고 싶다면 CorsConfiguration 의 checkOrigin 을 구현하면 된다.

Netty TcpServer

  • NettyServerCustomizer 를 구현하여 Netty TcpServer 에 대한 옵션 정의가 가능하다.
  • TcpServer 에 설정가능한 옵션은 다음과 같다.(옵션 종류는 ChannelOption 에 필드로 정의되어있다.)
    • SO_BACKLOG
    • SO_KEEPALIVE
    • SO_REUSEADDR
    • SO_LINGER
    • SO_RCVBUF
    • SO_SNDBUF
    • SO_TIMEOUT
    • TCP_NODELAY
  • TcpServer 에 대한 metric 을 활성화 하고 싶다면, TcpServer.metrics(boolean) 함수를 호출하면 된다.
public class EventLoopNettyCustomizer implements NettyServerCustomizer {

    @Override
    public HttpServer apply(HttpServer httpServer) {
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        EventLoopGroup childGroup = new NioEventLoopGroup();
        return httpServer.tcpConfiguration(tcpServer -> { // 필요한 설정 변경 수행 });
    }
}

⚠️ Reactor Netty 의 selector, worker thread 수도 NettyServerCustomizer 를 통해 설정할 수 있는것 같지만, 실제로 해보면 적용이 안된다.
그 이유는 selector, worker thread 는 http server 를 생성할 때 정의해야 하는데 실제 http server 를 생성하는 NettyReactiveWebServerFactory 에서 http server 를 생성한 뒤에 customizer 를 호출하도록 되어있기 때문에 여기서 설정을 해봤자 변경되지 않는다.
selector, worker thread 를 변경하기 위해선 NettyReactiveWebServerFactory 를 통해 ReactorResourceFactory 를 정의해 loopResources 를 셋팅해주거나 ReactorNetty 에 정의된 환경변수를 application 실행시 정의해주어야 한다.

  • NettyServerCustomizer 구현체를 Bean 으로 등록하거나 NettyReactiveWebServerFactory 을 Bean 으로 등록하고 이때 NettyServerCustomizer 를 등록하면 된다.
@Configuration
@EnableWebFlux
public class WebConfig {

    @Bean
    public EventLoopNettyCustomizer eventLoopNettyCustomizer() {
        return new EventLoopNettyCustomizer();
    }
}
@Configuration
@EnableWebFlux
public class WebConfig {

    @Bean
    public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
        NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory();
        webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer());
        return webServerFactory;
    }
}
  • SSL, Http2 와 관련된 설정을 하고자 한다면, WebServerFactoryCustomizer 를 직접 정의하면 된다.
@Component
public class NettyWebServerFactorySslCustomizer 
  implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    @Override
    public void customize(NettyReactiveWebServerFactory serverFactory) {
        Ssl ssl = new Ssl();
        ssl.setEnabled(true);
        ssl.setKeyStore("classpath:sample.jks");
        ssl.setKeyAlias("alias");
        ssl.setKeyPassword("password");
        ssl.setKeyStorePassword("secret");
        Http2 http2 = new Http2();
        http2.setEnabled(false);
        serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null));
        serverFactory.setPort(8443);
    }
}

'Spring Framework' 카테고리의 다른 글

Spring Webflux - Monitoring Metrics  (0) 2022.03.14
Spring Webflux - Exception Handle  (0) 2022.03.14
Spring Webflux - WebClient  (0) 2022.03.14
Spring Webflux - Filter  (0) 2022.03.14
Spring Webflux - HandlerFunction  (0) 2022.03.14
Comments