본문 바로가기
  • 오늘도 한걸음. 수고많았어요.^^
  • 조금씩 꾸준히 오래 가자.ㅎ
IT기술/spring

[Webflux] 이해하기, webflux는 무엇인가?

by 미노드 2025. 12. 23.

WebFlux로 “외부 HTTP 호출 → 응답 수신”을 할 때
스레드를 잡아두지 않고(Non-blocking), 데이터가 도착하는 이벤트에 반응해서 다음 단계로 흘려보내는 파이프라인으로 동작한다.
이 구조로 대기 기간이 없는 Nonblocking 방식의 통신을 지원한다.

Webflux 구성요소를 정리해보면 다음과 같다.

호출 주체: WebClient

반환 타입: Mono / Flux (응답을 담는 그릇)

외부 응답을 “값”으로 받는 게 아니라 “스트림”으로 받는다.
Mono: 응답 0~1개 (보통 단건 응답)
Flux: 응답 여러 개 (SSE/스트리밍/페이지 분할 등)

요청 구성에 필요한 것 준비

(1) URL / QueryParam
.uri("https://...") 또는 .uri(uriBuilder -> uriBuilder.path("/x").queryParam("a", 1).build())
(2) Method
.get() / .post() / .put() / .delete()
(3) Headers (인증/추적/콘텐츠 협상)
Authorization(Bearer/API-Key), Content-Type / Accept, Trace/Correlation-Id (로그 추적용)
(4) Body (POST/PUT)
JSON: .bodyValue(reqDto), Form: .body(BodyInserters.fromFormData(...)), 파일 멀티파트: MultipartBodyBuilder

응답 수신에 필요한 것들

(1) 상태코드 처리: retrieve() + onStatus(...)
(2) 바디 파싱: bodyToMono(...) / bodyToFlux(...)
(3) 타임아웃/리트라이/서킷브레이커 같은 “복원력”

Thread/Blocking 규칙: “절대 막지 말기”

WebFlux 에서 가장 중요한 단 하나:
.block(), .join(), JDBC 같은 블로킹 호출을 같은 체인에서 섞으면 WebFlux의 장점이 깨짐
왜냐면 WebFlux는 이벤트 루프 기반이라, 블로킹이 들어오면 이벤트 루프 스레드를 점유해버려서 전체 처리량이 떨어진다.

가능하면 R2DBC(DB), reactive driver를 쓰는 게 정석

“내 서비스”에서 컨트롤러까지 이어지는 형태

외부 호출 결과를 WebFlux 컨트롤러가 그대로 리턴할 때의 이상적인 흐름:

Controller는 Mono를 반환

Service는 WebClient로 외부 호출하고 Mono로 반환

중간에 매핑/검증/에러처리/로깅을 map/flatMap/onErrorMap/doOnNext 등으로 체이닝

즉, “받은 다음 처리”가 아니라 “받으면 처리하도록 선언”하는 스타일.

필수인 부가 요소

외부 호출은 “호출 성공” 뒤에 필요할 수 있는 요소

로깅/트레이싱: request-id, response time, status 기록

메트릭: 성공/실패/latency

에러 모델링: 외부 에러를 내부 에러코드로 매핑 (예: PG 오류 → 우리 도메인 에러)

논블로킹(Non-blocking)이란?
“기다림 자체가 없다”

스레드가 I/O 대기 때문에 멈추지 않음

“데이터 준비됨” 이벤트가 올 때만 처리

보통 이벤트 루프(Event Loop) 구조

WebFlux에서의 논블로킹
WebFlux는:

요청 N개 = 소수 이벤트 루프 스레드

외부 API 대기 중에도 스레드는 놀지 않음

비동기: 언제 올지 모르는 결과를 Mono/Flux로 표현

논블로킹: 그 결과를 기다리느라 스레드를 묶지 않음

WebFlux: 비동기와 논블로킹을 동시에 강제하는 모델

기존 MVC에서는

요청 1개 = 스레드 1개

외부 API 1초 지연 → 스레드 1초 점유 (대기, blocking)

비동기로 할 수 있지만, 대기가 필요할 수 있어 논블로킹은 아니다.