1. Flux의 개념
- 기존의 동기식 프로그램은 한 개의 작업이 끝나고 다른 작업을 실행하는 Blocking 방식의 프로그래밍
- 그런데, 한 번에 여러개의 작업을 계속 처리하는 것을 Non-blocking 방식의 프로그래밍.
- Flux는 데이터 스트림을 통해 작업을 비동기적으로 처리하고, 데이터가 준비되면 그 즉시 처리할 수 있도록 해준다. => 반응성이 뛰어나고 많은 양의 데이터를 처리하는 것에 효율적임.
1-2. Flux와 Mono의 차이
- Flux는 0개 이상의 값을 가질 수 있고, Mono는 0개 또는 1개의 값을 가진다.
- Reactive Stream은 Publisher가 Subscriber에게 데이터를 제공하는 개념이며, Flux와 Mono는 이러한 Publisher의 구현.
2. List와 뭐가 다를까 ?
- 동기적 상황에서는 List를 쓰고, 비동기적 상황에서는 Flux or Mono를 사용한다.
- 데이터를 조금씩 처리할 수 있어서 메모리 사용량을 줄일 수 있다.
List는 1부터 100까지의 수를 한 번에 저장해놓고 필요한 순간에 가져와서 사용하지만 Mono와 Flux는 필요한 순간에 값을 생성해서
메모리를 줄일 수 있다고 한다.
- 비동기적 또는 리액티브한 프로그래밍에서 더 유연하고 확장가능한 해결책을 제시해준다고 한다.
3. 기본적인 Flux 사용법
// 1. 그냥 생성
Flux<String> flux1 = Flux.just("Apple", "Banana", "Orange");
// 2. Iterable 객체를 기반으로 Flux 생성
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange");
Flux<String> flux2 = Flux.fromIterable(fruits);
// 3. 빈 Flux 생성
Flux<String> flux3 = Flux.empty();
// 4. 주어진 범위 내의 값을 생성
Flux<Integer> flux4 = Flux.range(1, 5);
// 5. 주어진 Supplier or BiFunction을 사요ㅕㅇ해서 값을 생성하는 Flux를 생성
Flux<String> flux5 = Flux.generate(
() -> 0, // 상태(초기값)를 생성하는 역할인 Supplier
(state, sink) -> {
sink.next("Value_" + state);
if(state == 5 ) sink.complete();
return state +1;
}
);
// 6. 주어진 FluxSink를 사용하여 값을 생성하는 Flux를 생성. 주의! 직접 사용하기 보다는 'FluxSink'를 사용하여 커스텀 발행 로직을 구현할 때 사용.
Flux<String> flux6 = Flux.create(sink -> {
sink.next("Apple");
sink.next("Banana");
sink.complete();
});
/* FluxSink
next()
error()
complete()
*/
// 인덱스를 뽑기.
flux1.elementAt(1)
.subscribe(System.out::println);
// 순차적으로 뽑기.
// 첫 번째, 데이터 핸들링 함수: Flux or Mono에서 발생한 데이터를 처리
// 두 번쨰, 에러 핸들링 함수: Flux or Mono에서 에러가 발생했을 때 처리할 작업
// 세 번째, 완료 핸들링 함수 : Flux or Mono에서 데이터 발행이 완료되었을 떄 실행할 작업
flux6.subscribe(
data -> System.out.println(data),
error -> System.err.println("Error occurred: " + error),
() -> System.out.println("Completed!")
);
4. 단점
- 비동기적이고 이벤트 기반의 프로그래밍을 지원하기 떄문에 코드가 복잡해질 수 있다.
- 당연히 비동기적이기 때문에 순서보장이 어렵다
- 따라서 이벤트 루프나 쓰레드 풀이 필요할 수 있기때문에 오버헤드가 발생할 수 있다.
- 스트림을 처리하는 동안 리소스 누수가 발생할 수 있다. (예를 들어 create에서 complete()을 안 해준다..)
=> 이런 단점을 커버하기 위해 적절한 코드 사용이 필요한데 기존의 동기식 프로그래밍과 많이 다르기때문에 학습곡선이 높다!