Study/spring cloud

Spring Cloud Gateway가 netty 기반 reactive web application으로 구동되는 이유

유경호 2022. 4. 21. 12:31
반응형

개요

Spring Cloud Gateway 애플리케이션을 구동하게 되면 기존의 임베디드 톰켓 기반의 Spring Boot Web 애플리케이션과는 다르게 Netty 기반의 비동기 통신을 지원하는 형태의 웹 애플리케이션으로 실행됩니다.

 

이 문서에서는 왜 이러한 현상이 발생하는지 알아봅니다.

WebApplicationType

먼저 SpringBoot에서는 웹 애플리케이션 구동시 org.springframework.boot.WebApplicationType을 정하게 됩니다.

WebApplicationType에는 세가지 타입이 존재합니다.

  • WebApplicationType.SERVLET
    → 애플리케이션을 서블릿 기반의 웹 애플리케이션으로 실행하며 임베디드 서블릿 웹서버(기본적으로 tomcat 기반)로 실행한다.
  • WebApplicationType.REACTIVE
    → 애플리케이션을 리엑티브 웹 애플리케이션으로 실행하며 임베디드 리엑티브 웹 서버(기본적으로 netty 기반)로 실행한다
  • WebApplicationType.NONE
    → 애플리케이션을 웹 애플리케이션, 임베디드 웹 서버로써 실행하지 않는다.

 

이제 어떠한 기준으로 WebApplicationType 을 가져가는지가 중요한데요. 간단하게 말하면 아래와 같은 기준을 가집니다.

  • WebApplicationType.SERVLET → spring-boot-starter-web 의존성을 가지면 해당 타입
  • WebApplicationType.REACTIVE → spring-boot-starter-webflux의존성을 가지면 해당 타입
  • WebApplicationType.NONE → 둘 다 의존성이 존재하지 않는다면 NONE 타입

 

둘 다 의존성이 존재한다면 SERVLET 타입으로 동작합니다. 이유는 아래 코드를 보면 알 수 있는데요.

...
package org.springframework.boot;

...

public enum WebApplicationType {

    ...
    private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";

    private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";

    ...

    static WebApplicationType deduceFromApplicationContext(Class<?> applicationContextClass) {
        if (isAssignable(SERVLET_APPLICATION_CONTEXT_CLASS, applicationContextClass)) {
            return WebApplicationType.SERVLET;
        }
        if (isAssignable(REACTIVE_APPLICATION_CONTEXT_CLASS, applicationContextClass)) {
            return WebApplicationType.REACTIVE;
        }
        return WebApplicationType.NONE;
    }

    ...

}

WebApplicationType을 결정할 때 spring-boot-starter-web 의존성 내에 존재하는 애플리케이션 컨텍스트 클래스를 먼저 스캔하기 때문입니다.

 

둘 다 존재하더라도 임의로 WebApplicationType을 REACTIVE로 명시한다면 REACTIVE로 실행할 수 있습니다.

Adding both spring-boot-starter-web and spring-boot-starter-webflux modules in your application results in Spring Boot auto-configuring Spring MVC, not WebFlux. This behavior has been chosen because many Spring developers add spring-boot-starter-webflux to their Spring MVC application to use the reactive WebClient. You can still enforce your choice by setting the chosen application type to SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE).

참조: https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.reactive.webflux

Spring Cloud Gateway의 의존성

WebApplicationType 는 알겠고 그럼 왜 Spring Cloud Gateway는 WebApplicationType.REACTIVE로써 웹 애플리케이션이 구동이 될까요?

 

이는 spring-cloud-gateway-server 의존성 내부를 들여다보면 알 수 있습니다. 아래는 spring-cloud-gateway-server-3.0.3.pom 파일의 일부를 발췌한 내용입니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-gateway</artifactId>
    <version>3.0.3</version>
    <relativePath>..</relativePath>
  </parent>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-gateway-server</artifactId>
  <version>3.0.3</version>
  <name>Spring Cloud Gateway Server</name>
  <description>Spring Cloud Gateway Server</description>
  <url>https://spring.io/spring-cloud/spring-cloud-gateway/spring-cloud-gateway-server</url>
  <organization>
    <name>Pivotal Software, Inc.</name>
    <url>https://www.spring.io</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>https://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
  </licenses>
    ...
  <dependencies>
        ...
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
      <version>2.4.6</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
</project>

<dependencies> 태그 내에 spring-boot-starter-webflux 의존성이 확인되시나요? 그렇습니다. Spring WebFlux의 의존성이 존재하기 때문에 REACTIVE로써 구동이 되는 것입니다.

결론

Spring Cloud Gateway가 REACTIVE 타입의 웹 애플리케이션으로써 구동되는 것은 비동기 웹 프로그래밍을 지원하기 위함으로 보여집니다. MSA(Microservices Architecture)에서 비동기 통신을 활용하는 것이 왜 좋은가에 대해서는 아래 안내해드리는 글을 참고하시면 알 수 있습니다.

참고: Spring WebFlux와 Armeria를 이용하여 Microservice에 필요한 Reactive + RPC 동시에 잡기


Reference

반응형