티스토리 뷰
Spring WebFlux는 비동기 논블로킹(Asynchronous Non-Blocking) 방식으로 동작하는 스프링 웹 프레임워크입니다.
기존 Spring MVC와 달리 Reactive Streams 기반의 Reactor 라이브러리를 사용하여 높은 동시성을 처리할 수 있는 API를 만들 수 있습니다.
✅ Spring Boot의 공식 비동기 웹 프레임워크
✅ Reactor 기반의 논블로킹 I/O 처리
✅ 적은 리소스로 높은 동시성 처리 가능
✅ 마이크로서비스 및 서버리스 환경에 최적화
1️⃣ Spring WebFlux vs Spring MVC 비교
특징 Spring MVC (Blocking) Spring WebFlux (Non-Blocking)
동작 방식 | 동기(Blocking) 방식 | 비동기(Non-Blocking) 방식 |
스레드 모델 | 요청마다 새로운 스레드 할당 | 이벤트 루프 기반 (Netty) |
사용 라이브러리 | Servlet API, Tomcat | Reactor, Netty, Undertow |
장점 | 직관적인 코드, 개발 용이 | 높은 동시성 처리, 적은 리소스 |
단점 | 많은 스레드 사용, 리소스 낭비 | 러닝 커브 있음, Debugging 어려움 |
적합한 환경 | 전통적인 웹 애플리케이션 | 실시간 데이터 처리, 마이크로서비스 |
2️⃣ Spring WebFlux 설정
🛠 프로젝트 의존성 추가 (pom.xml)
<dependencies>
<!-- Spring WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- Lombok (선택 사항) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
3️⃣ 기본적인 WebFlux API 구현
🔹 기본 REST API (논블로킹)
@RestController
@RequestMapping("/api")
public class WebFluxController {
@GetMapping("/hello")
public Mono<String> hello() {
return Mono.just("Hello, WebFlux!");
}
@GetMapping("/numbers")
public Flux<Integer> getNumbers() {
return Flux.range(1, 10).delayElements(Duration.ofMillis(500));
}
}
✅ Mono<T> → 단일 값 반환 (ex. HTTP 1건 요청 처리)
✅ Flux<T> → 여러 개의 값 스트리밍 (ex. 실시간 데이터 처리)
🔹 비동기 서비스 & Repository
🛠 데이터 모델
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String id;
private String name;
}
🛠 비동기 Repository (ReactiveCrudRepository 사용)
@Repository
public interface UserRepository extends ReactiveCrudRepository<User, String> {
Flux<User> findByName(String name);
}
🛠 비동기 Service
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public Mono<User> getUserById(String id) {
return userRepository.findById(id);
}
public Flux<User> getUsersByName(String name) {
return userRepository.findByName(name);
}
}
🛠 컨트롤러에서 비동기 데이터 처리
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable String id) {
return userService.getUserById(id);
}
@GetMapping("/name/{name}")
public Flux<User> getUsersByName(@PathVariable String name) {
return userService.getUsersByName(name);
}
}
4️⃣ Streaming 데이터 처리 (Server-Sent Events)
WebFlux는 서버에서 클라이언트로 데이터를 스트리밍하는 SSE(Server-Sent Events) 를 지원합니다.
🔹 SSE 예제 (서버에서 실시간 데이터 푸시)
@RestController
@RequestMapping("/stream")
public class StreamController {
@GetMapping(value = "/time", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamTime() {
return Flux.interval(Duration.ofSeconds(1))
.map(tick -> "Current Time: " + Instant.now());
}
}
✅ MediaType.TEXT_EVENT_STREAM_VALUE → 클라이언트가 실시간 데이터를 받을 수 있도록 SSE 스트림 설정
✅ Flux.interval(Duration.ofSeconds(1)) → 1초마다 새로운 데이터 생성
💡 📌 클라이언트에서 수신하는 방법 (JavaScript)
const eventSource = new EventSource('/stream/time');
eventSource.onmessage = (event) => {
console.log("Received: ", event.data);
};
5️⃣ WebClient: 비동기 HTTP 호출
Spring WebFlux에서는 RestTemplate 대신 WebClient를 사용하여 비동기 HTTP 요청을 처리할 수 있습니다.
🔹 WebClient 설정
@Bean
public WebClient webClient() {
return WebClient.builder().baseUrl("http://localhost:8080").build();
}
🔹 비동기 API 호출 예제
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient webClient) {
this.webClient = webClient;
}
public Mono<String> getDataFromExternalApi() {
return webClient.get()
.uri("/api/hello")
.retrieve()
.bodyToMono(String.class);
}
}
6️⃣ 성능 최적화 및 운영
🔹 Netty 사용 (Tomcat 대신)
Spring WebFlux는 기본적으로 Netty를 사용하여 높은 성능을 제공합니다.
Netty를 명시적으로 설정하려면 application.properties에서 다음과 같이 설정합니다.
server.port=8080
spring.main.web-application-type=reactive
✅ 기본적으로 Netty 사용 (Tomcat 제거 가능)
✅ Undertow로 변경 가능 (spring-boot-starter-undertow 추가)
🔹 WebFlux와 R2DBC (비동기 데이터베이스)
JPA 대신 R2DBC (Reactive Relational Database Connectivity) 를 사용하면 비동기 방식으로 데이터베이스를 처리할 수 있습니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
</dependency>
✅ JPA 대신 R2DBC 사용하여 논블로킹 데이터 처리
✅ MySQL, PostgreSQL 등 다양한 DB 지원
🔥 결론: Spring WebFlux가 적합한 경우
✅ 비동기 논블로킹 API가 필요한 경우
✅ 대량의 요청을 동시에 처리해야 할 때
✅ 실시간 데이터 스트리밍 (SSE, WebSocket)이 필요한 경우
✅ 마이크로서비스 및 클라우드 네이티브 환경에서 사용
Spring WebFlux는 높은 동시성과 확장성을 제공하여 쿠버네티스, 서버리스, 마이크로서비스 환경에서 강력한 API를 구축할 수 있습니다! 🚀
'Programming' 카테고리의 다른 글
스프링부트 서비스 리소스 절감 최적화 전략 (0) | 2025.03.20 |
---|---|
GraalVM을 사용한 네이티브 이미지 정적 링크 빌드란? (0) | 2025.03.20 |
자바 WebClient VS FeignClient 비교 (0) | 2025.03.20 |
Kotlin + Spring Boot REST API 예시 (0) | 2025.03.18 |
비동기(Asynchronous) vs. 동기(Synchronous), 블로킹(Blocking) vs. 논블로킹(Non-blocking) (0) | 2025.03.18 |