WebClient의 .body(...)와 .bodyValue

WebClient의 .body(...)와 .bodyValue(...)의 차이는 "비동기 객체인지 아닌지", 즉 Reactive 타입인지 아닌지에 따라 나뉜다.


bodyValue(value: T)

즉시 사용할 수 있는 일반 객체일 때 사용

내부적으로 Mono.just(value)로 감싼 것과 같음

비동기 처리를 하지 않고, 즉시 요청에 넣음

val person = Person("Kim", 30)
webClient.post()
    .uri("/person")
    .bodyValue(person) // 바로 쓸 수 있는 객체
    .retrieve()
    .awaitBody<Unit>()

body(publisher: Publisher<T>)

Mono<T>, Flow<T>, Deferred<T> 등 비동기 데이터 소스를 처리할 때 사용

데이터가 나중에 준비되면, 그걸 사용해 본문을 구성함

.body(...)는 데이터를 Publisher 또는 Coroutine 타입으로 받는다

val deferredPerson: Deferred<Person> = async {
    getPersonFromDB() // 비동기 DB 조회
}

webClient.post()
    .uri("/person")
    .body(deferredPerson) // 나중에 준비될 값
    .retrieve()
    .awaitBody<Unit>()

 

  • val person = Person(...) → .bodyValue(person)
  • val person: Deferred<Person> → .body(person)
  • val personMono: Mono<Person> → .body(personMono)
  • val personFlow: Flow<Person> → .body(personFlow)

Flow, Mono, Deferred 간 차이

모두 비동기 데이터를 다루는 방식이지만, 각각의 목적과 특성이 다르다.


Deferred<T> – 단일 값 비동기 작업

  • async { ... }로 생성
  • 비동기적으로 계산된 하나의 값을 나중에 받을 수 있음
  • Kotlin Coroutine에서 제공
  • await()를 통해 값을 꺼냄
val deferred: Deferred<String> = async {
    delay(1000)
    "Hello"
}
val result = deferred.await()

 


Flow<T> – 여러 값의 비동기 스트림

  • flow { emit(...) }로 생성
  • 여러 값을 순차적으로 emit (흐름)
  • Kotlin Coroutine에서 제공
  • collect { ... } 또는 first(), toList() 등으로 사용
val flow: Flow<Int> = flow {
    emit(1)
    emit(2)
    emit(3)
}
flow.collect { println(it) }

 


Mono<T> – 단일 값의 Reactive 타입

  • Project Reactor에서 제공 (Spring WebFlux 기반)
  • Mono.just(value) 또는 Mono.fromCallable { ... }
  • subscribe { ... }, awaitSingle() (Kotlin에서는)
val mono: Mono<String> = Mono.just("Hello")
mono.subscribe { println(it) }

 


  Deferred Flow Mono
프레임워크 Kotlin Coroutines Kotlin Coroutines Reactor (Spring)
데이터 수 단일 값 여러 값 단일 값
취소/중단 지원 지원 지원 (reactive 방식)
사용 예 비동기 계산 결과 스트리밍 데이터 WebClient 비동기 요청 결과
  시간이 걸리는 작업을 백그라운드에서 처리하고, 나중에 단일 결과를 사용하고 싶을 때 여러 데이터를 지연 처리, 스트리밍, 또는 이벤트처럼 다룰 때 Spring WebFlux 등 리액티브 환경에서 단일 비동기 값을 처리할 때
WebClient 사용 .body(deferred) .body(flow) .body(mono)

 

예를 들어 WebClient에 쓸 때

// Deferred 사용
val dataDeferred: Deferred<Data> = ...
webClient.post().body(dataDeferred) ...

// Flow 사용
val dataFlow: Flow<Data> = ...
webClient.post().body(dataFlow) ...

// Mono 사용 (Java 기반 Reactive)
val dataMono: Mono<Data> = ...
webClient.post().body(dataMono) ...

필요하다면 Mono ↔ Deferred 변환, Flow ↔ Flux 변환도 가능하다.
Kotlin에서는 주로 Deferred와 Flow, Java 기반에서는 Mono, Flux를 사용한다.

 

 

'【 개발 이야기 】' 카테고리의 다른 글

[git] rebase 이해하기  (0) 2025.06.02
볼만한 개발 블로그..  (0) 2025.05.30
[spring] web client 공식 문서 번역  (1) 2025.05.08
[kotlin] inline 함수란 뭘까...  (1) 2025.04.29
[보안] Base64 인코딩과 iv  (0) 2025.04.25