fromCallable

map 계열 함수

Mono

0개 또는 1개의 결과를 비동기로 처리하는 리액티브 타입. 단건을 조회하거나 저장하는데 사용한다.

// 값 있는 Mono
Mono<String> mono = Mono.just("hello");

// 빈 Mono (0개)
Mono<String> empty = Mono.empty();

// 에러 Mono
Mono<String> error = Mono.error(new RuntimeException("에러"));

// 지연 실행
Mono<String> defer = Mono.defer(() -> Mono.just("lazy"));

주요 메서드는 다음과 같다.

// 값 변환
Mono.just("hello")
    .map(s -> s.toUpperCase());          // HELLO

// 비동기 변환 (Mono 반환하는 함수)
Mono.just(1)
    .flatMap(id -> findUserById(id));    // Mono<User>

// 값 없을 때 기본값
Mono.empty()
    .defaultIfEmpty("기본값");

// 에러 처리
Mono.error(new RuntimeException())
    .onErrorReturn("fallback");

// 값 소비 (사이드 이펙트)
Mono.just("hello")
    .doOnNext(s -> log.info(s));

하나의 Mono 객체는 는 구독하지 않으면 그 전까지는 실행되지 않는다. 레이지하게 반응함.

mono.subscribe(
    value -> System.out.println("값: " + value),   // onNext
    error -> System.out.println("에러: " + error),  // onError
    () -> System.out.println("완료")               // onComplete
);

하지만 WebFlux 컨트롤러에서 사용하면 직접 구독하지 않고 반환만 해도 프레임워크가 알아서 처리한다.

@RestController
public class UserController {

    @GetMapping("/user/{id}")
    public Mono<User> getUser(@PathVariable Long id) {
        return userService.findById(id);  // 구독은 WebFlux가 처리
    }

    @PostMapping("/user")
    public Mono<ResponseEntity<User>> createUser(@RequestBody Mono<User> body) {
        return body
            .flatMap(userService::save)
            .map(user -> ResponseEntity.ok(user));
    }
}

Flux

0~N개의 데이터를 비동기적으로 처리하는 리액티브 타입. 쉽게 말하면 스트림임

WebFlux에서 HTTP 응답은 항상 Mono 이지만, 그 내부 Body는 Flux 일 수 있다.

다음과 같이 생성한다.

// 고정된 값
Flux.just("a", "b", "c")

// 컬렉션으로부터
Flux.fromIterable(listOf(1, 2, 3))

// 범위
Flux.range(1, 5)  // 1, 2, 3, 4, 5

// 빈 Flux
Flux.empty()

// 에러
Flux.error(RuntimeException("에러"))

// 무한 스트림
Flux.interval(Duration.ofSeconds(1))  // 1초마다 값 발행