Files
spring-boot-examples/docs/webflux/04_리액티브 데이터 스트림 이해.md
2025-04-08 19:56:24 +09:00

6.1 KiB

아래는 **"스프링부트 웹플럭스 시리즈"**의 **4장: 리액티브 데이터 스트림 이해"**에 대한 초안입니다. 3장에서의 실습을 바탕으로 MonoFlux를 중심으로 리액티브 스트림의 개념을 설명하고, 간단한 예제를 포함했습니다. 코드도 간략히 유지하며 초보자가 이해하기 쉽게 작성했습니다.


4. 리액티브 데이터 스트림 이해

3장에서 우리는 첫 번째 웹플럭스 애플리케이션을 만들며 Mono를 살짝 맛봤습니다. 이번 장에서는 웹플럭스의 핵심인 리액티브 데이터 스트림을 깊이 파고들어, MonoFlux가 무엇인지, 어떻게 동작하는지 알아보겠습니다. 실습도 곁들이며 개념을 확실히 잡아볼게요. 준비되셨죠?

Mono와 Flux의 개념

리액티브 프로그래밍의 세계에서 데이터는 "스트림" 형태로 흐릅니다. 이 스트림을 다루는 두 가지 주요 도구가 바로 MonoFlux입니다. 둘 다 스프링 웹플럭스가 사용하는 리액터(Reactor) 라이브러리에서 제공되며, 비동기 데이터 처리를 가능하게 합니다.

  • Mono: 0개 또는 1개의 항목을 발행하는 스트림입니다. 단일 값을 반환할 때 유용합니다. 예를 들어, 데이터베이스에서 한 명의 사용자 정보를 조회하거나, 외부 API에서 단일 응답을 받을 때 사용합니다.
  • Flux: 0개 이상의 항목을 발행하는 스트림입니다. 여러 개의 데이터를 순차적으로 처리하거나, 실시간으로 계속 들어오는 데이터를 다룰 때 적합합니다. 리스트나 스트리밍 데이터가 대표적인 예입니다.

쉽게 말해, Mono는 "하나 아니면 없음"이고, Flux는 "여러 개가 올 수도 있음"이라고 생각하면 됩니다. 이 둘은 리액티브 스트림의 기본 빌딩 블록으로, 데이터를 비동기적으로 생성하고 구독자가 이를 소비하는 구조를 만듭니다.

리액티브 스트림의 동작 원리

리액티브 스트림은 "발행-구독(Publish-Subscribe)" 모델을 따릅니다. 데이터가 준비되면 발행자(Publisher)가 이를 발행하고, 구독자(Subscriber)가 그 데이터를 받아 처리합니다. 이 과정에서 중요한 점은 비동기성과 **백프레셔(Backpressure)**입니다.

  • 비동기성: 데이터가 준비되는 즉시 처리하지 않고, 준비 완료 시점에 맞춰 반응합니다. 스레드가 블록되지 않으니 자원을 효율적으로 사용할 수 있죠.
  • 백프레셔: 구독자가 데이터 처리 속도를 조절할 수 있게 해줍니다. 예를 들어, 데이터가 너무 빨리 쏟아지면 "천천히 보내줘"라고 요청할 수 있는 셈입니다.

MonoFlux는 이런 원리를 구현한 도구로, 우리가 작성하는 코드는 이 흐름을 정의하는 역할을 합니다.

간단한 예제로 배우는 Mono와 Flux

이제 직접 코드를 보며 느낌을 익혀보겠습니다. 3장에서 만든 프로젝트에 새 컨트롤러를 추가하거나, 별도의 클래스에서 테스트해볼 수 있습니다. 여기서는 간단히 컨트롤러로 예제를 작성합니다.

src/main/java/com/example/demoStreamController를 만들고 아래 코드를 추가하세요:

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;

@RestController
public class StreamController {

    @GetMapping("/mono")
    public Mono<String> getMono() {
        return Mono.just("This is a Mono!")
                   .delayElement(Duration.ofSeconds(1));
    }

    @GetMapping("/flux")
    public Flux<String> getFlux() {
        return Flux.just("This", "is", "a", "Flux!")
                   .delayElements(Duration.ofSeconds(1));
    }
}
  • /mono 엔드포인트: Mono로 단일 문자열을 1초 지연 후 반환합니다. 접속하면 1초 뒤에 "This is a Mono!"가 표시됩니다.
  • /flux 엔드포인트: Flux로 여러 문자열을 1초 간격으로 순차적으로 발행합니다. 접속하면 "This", "is", "a", "Flux!"가 1초씩 간격을 두고 나타납니다(클라이언트에 따라 한꺼번에 보일 수도 있음).

애플리케이션을 실행하고 http://localhost:8080/monohttp://localhost:8080/flux를 브라우저나 Postman으로 테스트해보세요. Mono는 한 번에 끝나고, Flux는 여러 값을 순차적으로 보내는 걸 느낄 수 있습니다.

더 재미있는 예제로, 숫자 스트림을 만들어볼까요?

@GetMapping("/numbers")
public Flux<Integer> getNumbers() {
    return Flux.range(1, 5)
               .delayElements(Duration.ofSeconds(1));
}

/numbers에 접속하면 1부터 5까지 숫자가 1초 간격으로 출력됩니다. 이런 식으로 Flux는 연속적인 데이터를 다룰 때 강력합니다.

잠깐 정리

  • Mono: 단일 데이터(0 또는 1개)를 비동기적으로 처리.
  • Flux: 여러 데이터(0개 이상)를 스트림으로 처리.
  • 동작: 발행자가 데이터를 준비하면 구독자가 받아서 처리하며, 비동기와 백프레셔로 효율성을 높임.

이 예제들은 아주 기본적인 수준이지만, 리액티브 스트림의 흐름을 이해하는 데 큰 도움이 됩니다. 실제로는 데이터베이스나 외부 API와 연동할 때 더 빛을 발휘하죠.

마무리

MonoFlux는 웹플럭스의 심장과도 같습니다. 이 두 도구를 잘 다룰 수 있다면, 비동기 프로그래밍의 세계가 훨씬 친근하게 느껴질 겁니다. 다음 장에서는 웹플럭스의 라우팅 방식을 더 깊이 탐구하며, 함수형 접근법도 함께 살펴보겠습니다. 이번 장에서 스트림의 맛을 보셨으니, 다음 단계가 더 기대되시죠?


이 장은 개념 설명과 간단한 실습을 균형 있게 배치해 초보자가 부담 없이 따라 할 수 있도록 했습니다. 코드도 최소화했으며, 추가 예제나 설명이 필요하면 언제든 말씀해주세요!