CS 정리
Spring WebFlux: 왜, 언제, 어떻게?
문쿼리
2025. 6. 29. 16:11
Spring WebFlux는 비동기(Async), 논블로킹(Non-blocking) 기반의 웹 프레임워크로, Spring 5부터 도입
동시성이 높은 환경에서 적은 리소스로 많은 요청을 처리
왜? MVC와 WebFlux
항목 | Spring MVC | Spring WebFlux |
처리 방식 | 동기, 블로킹 | 비동기, 논블로킹 |
스레드 모델 | 요청당 스레드 1개 | 이벤트 루프 기반 (Netty 등) |
데이터 흐름 | 객체 기반 | 리액티브 스트림 (Mono, Flux) |
적합한 상황 | CPU 중심, 트래픽 적음 | I/O 중심, 동시성 많음 |
언제? 도입 배경
- 외부 API 여러 개를 병렬로 호출할 때
- 실시간 데이터 처리 (SSE, WebSocket 등)
- 대용량 파일 처리나 스트리밍이 필요할 때
- 느린 외부 시스템과의 연동이 많은 서비스
어떻게? MVC → WebFlux 전환 전략
dto -> Mono<dto> or Flus<dto>
RestTemplate -> WebClient
JPA -> R2DBC
MockMvc → WebTestClient
1. 전환 범위 정하기
2. 반환 타입 변경
// MVC
@GetMapping("/user")
public User getUser() { ... }
// WebFlux
@GetMapping("/user")
public Mono<User> getUser() { ... }
3. RestTemplate → WebClient 교체
WebClient.create()
.get().uri("/api")
.retrieve()
.bodyToMono(String.class);
4. DB 접근 방식 고려 (JPA → R2DBC 등)
@Repository
public interface UserRepository extends ReactiveCrudRepository<User, Long> {
Mono<User> findByEmail(String email);
}
5. 테스트 도구도 변경
도입!
대시보드 구조 변경
기존 방식 (프론트 병렬 호출)
프론트에서 여러 api를 병렬 호출함,
요청 수가 많고, 응답 순서에 따라 렌더링 지연 발생
WebFlux 도입 후 (백엔드 병렬 조립)
백엔드에서 여러 api를 병렬 호출하여 통합 응답
@GetMapping("/dashboard")
public Mono<DashboardDto> getDashboard() {
Mono<User> user = webClient.get().uri("/user-info").retrieve().bodyToMono(User.class);
Mono<List<Order>> orders = webClient.get().uri("/orders").retrieve().bodyToFlux(Order.class).collectList();
Mono<List<Product>> products = webClient.get().uri("/products").retrieve().bodyToFlux(Product.class).collectList();
return Mono.zip(user, orders, products)
.map(tuple -> new DashboardDto(tuple.getT1(), tuple.getT2(), tuple.getT3()));
}
변경 후 장점
- 네트워크 요청 수 감소
- 응답 속도 증가 (가장 느린 API만 기다리면 됨)
- 구조 통제 및 화면 일관성 증가