본문 바로가기
Study/spring cloud

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

by 유경호 2022. 4. 21.
반응형

개요

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

반응형