오늘은 Spring Boot Batch 프로젝트에 Webclient 의존성을 추가하면서 발생한 이슈를 기록하고자 합니다.
이벤트 관련 Spring Boot Batch 비즈니스 로직을 작성하며 기술적 부채였던 RestTemplate을 더이상 사용하지 않고 점진적으로 Webclient로 교체해나가기 의존성을 추가하기로 결정하였습니다.
implementation 'org.springframework.boot:spring-boot-starter-webflux'
Webclient를 사용하기 위해서는 Webflux의존성을 추가하였는데 웬걸? Spring Boot Batch는 일괄작업만 하고 종료되기에 특별히 Web 요청을 받을 필요가 Spring Boot 기본적으로 추가되어 있는 임베디드 톰캣의존성을 제거하였는데 웬걸?
갑자기 Netty started on port 8080이 활성화 되었다는 로그가 출력되었습니다! 나는 webflux의존성만 추가하였는데 왜? 톰캣 웹서버도아니고 네티 웹서버가 갑자기 왜 실행되었을까? webflux 의존성 트리를 확인해보니
\--- org.springframework.boot:spring-boot-starter-webflux -> 3.4.0
+--- org.springframework.boot:spring-boot-starter:3.4.0 (*)
+--- org.springframework.boot:spring-boot-starter-json:3.4.0
| +--- org.springframework.boot:spring-boot-starter:3.4.0 (*)
| +--- org.springframework:spring-web:6.2.0
| | +--- org.springframework:spring-beans:6.2.0 (*)
| | +--- org.springframework:spring-core:6.2.0 (*)
| | \--- io.micrometer:micrometer-observation:1.14.0 -> 1.14.1 (*)
| +--- com.fasterxml.jackson.core:jackson-databind:2.18.1
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.18.1
| | | \--- com.fasterxml.jackson:jackson-bom:2.18.1
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.18.1 (c)
| | | +--- com.fasterxml.jackson.core:jackson-core:2.18.1 (c)
| | | +--- com.fasterxml.jackson.core:jackson-databind:2.18.1 (c)
| | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.1 (c)
| | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.1 (c)
| | | \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.1 (c)
| | +--- com.fasterxml.jackson.core:jackson-core:2.18.1
| | | \--- com.fasterxml.jackson:jackson-bom:2.18.1 (*)
| | \--- com.fasterxml.jackson:jackson-bom:2.18.1 (*)
| +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.1
| | +--- com.fasterxml.jackson.core:jackson-core:2.18.1 (*)
| | +--- com.fasterxml.jackson.core:jackson-databind:2.18.1 (*)
| | \--- com.fasterxml.jackson:jackson-bom:2.18.1 (*)
| +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.1
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.18.1 (*)
| | +--- com.fasterxml.jackson.core:jackson-core:2.18.1 (*)
| | +--- com.fasterxml.jackson.core:jackson-databind:2.18.1 (*)
| | \--- com.fasterxml.jackson:jackson-bom:2.18.1 (*)
| \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.1
| +--- com.fasterxml.jackson.core:jackson-core:2.18.1 (*)
| +--- com.fasterxml.jackson.core:jackson-databind:2.18.1 (*)
| \--- com.fasterxml.jackson:jackson-bom:2.18.1 (*)
+--- org.springframework.boot:spring-boot-starter-reactor-netty:3.4.0
| \--- io.projectreactor.netty:reactor-netty-http:1.2.0
| +--- io.netty:netty-codec-http:4.1.114.Final -> 4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-buffer:4.1.115.Final
| | | \--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-transport:4.1.115.Final
| | | +--- io.netty:netty-common:4.1.115.Final
| | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | \--- io.netty:netty-resolver:4.1.115.Final
| | | \--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-codec:4.1.115.Final
| | | +--- io.netty:netty-common:4.1.115.Final
| | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | \--- io.netty:netty-transport:4.1.115.Final (*)
| | \--- io.netty:netty-handler:4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-resolver:4.1.115.Final (*)
| | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | +--- io.netty:netty-transport:4.1.115.Final (*)
| | +--- io.netty:netty-transport-native-unix-common:4.1.115.Final
| | | +--- io.netty:netty-common:4.1.115.Final
| | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | \--- io.netty:netty-transport:4.1.115.Final (*)
| | \--- io.netty:netty-codec:4.1.115.Final (*)
| +--- io.netty:netty-codec-http2:4.1.114.Final -> 4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | +--- io.netty:netty-transport:4.1.115.Final (*)
| | +--- io.netty:netty-codec:4.1.115.Final (*)
| | +--- io.netty:netty-handler:4.1.115.Final (*)
| | \--- io.netty:netty-codec-http:4.1.115.Final (*)
| +--- io.netty:netty-resolver-dns:4.1.114.Final -> 4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | +--- io.netty:netty-resolver:4.1.115.Final (*)
| | +--- io.netty:netty-transport:4.1.115.Final (*)
| | +--- io.netty:netty-codec:4.1.115.Final (*)
| | +--- io.netty:netty-codec-dns:4.1.115.Final
| | | +--- io.netty:netty-common:4.1.115.Final
| | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | +--- io.netty:netty-transport:4.1.115.Final (*)
| | | \--- io.netty:netty-codec:4.1.115.Final (*)
| | \--- io.netty:netty-handler:4.1.115.Final (*)
| +--- io.netty:netty-resolver-dns-native-macos:4.1.114.Final -> 4.1.115.Final
| | \--- io.netty:netty-resolver-dns-classes-macos:4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-resolver-dns:4.1.115.Final (*)
| | \--- io.netty:netty-transport-native-unix-common:4.1.115.Final (*)
| +--- io.netty:netty-transport-native-epoll:4.1.114.Final -> 4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | +--- io.netty:netty-transport:4.1.115.Final (*)
| | +--- io.netty:netty-transport-native-unix-common:4.1.115.Final (*)
| | \--- io.netty:netty-transport-classes-epoll:4.1.115.Final
| | +--- io.netty:netty-common:4.1.115.Final
| | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | +--- io.netty:netty-transport:4.1.115.Final (*)
| | \--- io.netty:netty-transport-native-unix-common:4.1.115.Final (*)
| +--- io.projectreactor.netty:reactor-netty-core:1.2.0
| | +--- io.netty:netty-handler:4.1.114.Final -> 4.1.115.Final (*)
| | +--- io.netty:netty-handler-proxy:4.1.114.Final -> 4.1.115.Final
| | | +--- io.netty:netty-common:4.1.115.Final
| | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | +--- io.netty:netty-transport:4.1.115.Final (*)
| | | +--- io.netty:netty-codec:4.1.115.Final (*)
| | | +--- io.netty:netty-codec-socks:4.1.115.Final
| | | | +--- io.netty:netty-common:4.1.115.Final
| | | | +--- io.netty:netty-buffer:4.1.115.Final (*)
| | | | +--- io.netty:netty-transport:4.1.115.Final (*)
| | | | \--- io.netty:netty-codec:4.1.115.Final (*)
| | | \--- io.netty:netty-codec-http:4.1.115.Final (*)
| | +--- io.netty:netty-resolver-dns:4.1.114.Final -> 4.1.115.Final (*)
| | +--- io.netty:netty-resolver-dns-native-macos:4.1.114.Final -> 4.1.115.Final (*)
| | +--- io.netty:netty-transport-native-epoll:4.1.114.Final -> 4.1.115.Final (*)
| | \--- io.projectreactor:reactor-core:3.7.0
| | \--- org.reactivestreams:reactive-streams:1.0.4
| \--- io.projectreactor:reactor-core:3.7.0 (*)
+--- org.springframework:spring-web:6.2.0 (*)
\--- org.springframework:spring-webflux:6.2.0
+--- org.springframework:spring-beans:6.2.0 (*)
+--- org.springframework:spring-core:6.2.0 (*)
+--- org.springframework:spring-web:6.2.0 (*)
\--- io.projectreactor:reactor-core:3.7.0 (*)
org.springframework.boot:spring-boot-starter-reactor-netty:3.4.0 비동기 처리에 특화된 네티 웹 서버의존성이 포함되어있었습니다! 따라서 스프링 부트는 톰캣 웹 서버는 의존성은 없어서 톰캣 웹서버를 실행하지 않았지만 네티 웹서버 의존성 존재여부를 파악한 스프링 부트는 AutoConfiguration을 통해 자동으로 네티 웹 서버를 동작시키게 된 부분입니다.
@Configuration
@ConditionalOnClass(ReactorNetty.class)
public class NettyWebServerConfiguration {
// ReactorNetty 서버를 활성화하는 설정
}
스프링 부트 로직과는 다르지만 간단한 코드로 설명해 보자면 네티 웹 서버 의존성이 추가되고 스프링 부트를 실행하면 @ConditionalOnClass 즉 해당 클래스가 존재한다면 스프링 부트는 자동구성정보를 통해 네티 웹 서버를 구동하게 되는겁니다!
spring:
main:
web-application-type: none
하지만 Spring Boot Batch 프로젝트에 Webflux의존성을 추가한 의도는 Webclient를 사용하기 위함이였으므로 Spring Boot가 웹 서버 의존성이 있다고 하더라도 웹 서버를 실행시키지 않도록 application.yml 웹서버를 실행시키지 않도록 설장하였습니다.
위 설정을 마치고 Spring Boot Batch를 실행하면 WebFlux의존성을 추가하였음에도 네티 웹 서버는 실행되지 않았습니다.
혹시나 웹 서버를 필요치 않는 Spring Boot 프로젝트에서 Webclient의존성을 추가할때 이점의 주의하여 사용하고 사용하시면
좋을것 같습니다.
'Spring > experience' 카테고리의 다른 글
Java 부동소수점 계산시 정확한 계산을 위해 왜 BigDesimal을 사용해야하는가? (1) | 2025.02.10 |
---|---|
SpringFramework NullPointException 방지법 (0) | 2025.01.13 |
Spring Framework ResponseEntity 사용에 대한 고찰 (0) | 2024.11.17 |
현업에서 자주 사용한 Java Stream Api (3) | 2024.11.10 |
그럼에도 불구하고 Lombok을 도입해야하는 이유? (0) | 2024.10.27 |