티스토리 뷰

Spring

[Spring] WebMVC와 WebFlux 의존성이 모두 존재하는 경우의 동작 방식

망나니개발자 2022. 6. 20. 10:00
반응형

이번에는 Spring WebMVC와 WebFlux의 의존성이 모두 존재하는 경우에 어떻게 동작하는지 살펴보도록 하겠습니다.

 

 

 

 

1. WebMVC와 WebFlux 의존성이 모두 존재하는 경우의 동작 방식


[ WebMVC와 WebFlux ]

스프링에는 WebMVC와 WebFlux, 2가지의 웹 프레임워크가 있다.

  • WebMVC: 전통적인 멀티 쓰레드 기반의 웹 프레임워크
  • WebFlux:  리액티브 스택 기반의 웹 프레임워크

 

2가지 웹 프레임워크는 다음과 같은 의존성을 추가함으로써 사용 가능하다. 2가지 의존성을 모두 추가하는 것도 가능한데, 이러한 경우에는 어떻게 동작하게 되는지 살펴보도록 하자.

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'

 

 

 

 

 

[ WebMVC와 WebFlux 의존성이 모두 존재하는 경우 ]

스프링은 애플리케이션 타입을 설정하는데, 3가지를 Enum으로 관리한다. 스프링은 DI 프레임워크인 만큼 웹이 아닌 프로젝트에서도 사용이 가능한데, 이때 NONE 타입이 사용된다.

  • NONE: 웹 애플리케이션이 아닌 경우
  • SERVLET: 서블릿 웹 애플리케이션인 경우
  • REACTIVE: 리액티브 웹 애플리케이션인 경우

 

 

애플리케이션이 실행될 때 클래스 패스를 기반으로 애플리케이션 타입을 선택하는데, 해당 로직은 다음과 같다. 리액티브 타입으로 선택되려면 클래스패스에 웹 플럭스 의존성은 존재하고, 서블릿 의존성은 존재하지 않는 경우에만 가능함을 확인할 수 있다. 즉, 2가지 의존성이 모두 존재한다면 서블릿 기반으로 스프링이 실행되는 것이다.

static WebApplicationType deduceFromClasspath() {
    if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) 
        && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
        && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
            return WebApplicationType.REACTIVE;
    }
    for (String className : SERVLET_INDICATOR_CLASSES) {
        if (!ClassUtils.isPresent(className, null)) {
            return WebApplicationType.NONE;
        }
    }
    return WebApplicationType.SERVLET;
}

 

 

 

 

 

[ WebMVC와 WebFlux 자동 설정을 모두 활성화하는 경우 ]

애플리케이션 타입이 정해지면 자동 설정이 진행되는데, 각각 서블릿 기반과 리액티브 기반의 자동 설정을 활성화하는 클래스는 각각 WebMvcAutoConfiguration와 WebFluxAutoConfiguration이다.

@AutoConfiguration(after = { ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
		ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class,
		WebSessionIdResolverAutoConfiguration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebFluxAutoConfiguration {

    ... 생략

}

 

 

WebFluxAutoConfiguration이 활성화되는 조건을 살펴보면 다음과 같다.

  1. 애플리케이션이 리액티브 타입인 경우
  2. 클래스패스에 웹플럭스가 존재하는 경우
  3. WebFluxConfigurationSupport 타입의 빈이 없는 경우

 

일반적으로 2가지 의존성이 모두 존재하면 애플리케이션 타입이 SERVLET이 되므로 WebFlux 관련 자동 설정은 활성화되지 않는다. 하지만 @EnableWebFlux 어노테이션을 사용하면 WebFluxAutoConfiguration을 강제로 활성화 시킬 수 있다. 이러한 경우에는 2가지 웹 프레임워크 설정이 자동으로 활성화되므로 문제가 발생할 수 있는데, 그래서 WebFluxConfigurationSupport에 applicationCotext을 세팅할 때 WebMVC 자동 설정이 되었다면 assert를 통해 이를 방지하고 있다.

public class WebFluxConfigurationSupport implements ApplicationContextAware {

    ... 생략

    @Override
    public void setApplicationContext(@Nullable ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        if (applicationContext != null) {
            Assert.state(!applicationContext.containsBean("mvcContentNegotiationManager"),
                "The Java/XML config for Spring MVC and Spring WebFlux cannot both be enabled, " +
                "e.g. via @EnableWebMvc and @EnableWebFlux, in the same application.");
        }
    }
    
    ... 생략 
    
}

 

 

 

 

즉, 위에서 살펴본 내용들을 정리하면 WebMVC와 WebFlux 의존성이 모두 존재하면 애플리케이션 타입이 SERVLET으로 설정되고, WebMVC 기반으로 스프링이 실행된다는 것이다. 그리고 @EnableWebFlux 어노테이션으로 WebFlux 설정을 강제 활성화해도, 애플리케이션 실행 시점에 에러를 던져 이러한 상황을 방지하고 있다.

 

 

 

 

 

위의 내용들은 개인적으로 공부를 하면서 작성을 한 내용이라 충분히 틀리거나 잘못된 내용들이 있을 수 있습니다. 혹시 수정 또는 추가할 내용들을 발견하셨다면 댓글 남겨주세요! 반영해서 수정하도록 하겠습니다:)

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함