Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 프로그래머스
- 우선순위큐
- 네트워크
- boj
- 백준
- 그리디
- dynamic programming
- 해시맵
- 백트래킹
- JPA
- Spring
- Backtracking
- 깊이우선탐색
- DP
- 브루트포스
- 동적계획법
- 스프링
- 부분수열의합
- 너비우선탐색
- Network
- BFS
- greedy
- DFS
- DynamicProgramming
- ReactiveProgramming
- 알고리즘
- 구현
- Algorithm
- 이분탐색
- programmers
Archives
- Today
- Total
옌의 로그
[Reactive Programming] 마블 다이어그램(Marble Diagram) 본문
본 포스팅은 스프링으로 시작하는 리액티브 프로그래밍 책을 참고하여 작성하였습니다. ( _ _)
마블 다이어그램(Marble Diagram) 이란?
마블 다이어그램은 비동기적인 데이터 흐름을 시간의 흐름에 따라 시각적으로 표시한 다이어그램을 의미한다.
- 그림에서 두 개의 타임라인이 존재하는데, 첫 번째가 Publisher가 데이터를 emit 하는 타임라인이다
- 두 번째는 Operator 함수에서 가공 처리되어 출력으로 내보내진 데이터의 타임라인이다
- Marble로 표시된 데이터는 Publisher가 emit하는 데이터를 의미한다. 타임라인은 왼쪽에서 오른쪽으로 시간이 흐르는 것을 의미하기 때문에 가장 왼쪽에 있는 1번 구슬이 시간상으로 가장 먼저 emit된 데이터이다
- 중간 박스는 Publisher로부터 전달받은 데이터를 처리하는 Operator 함수이다.
- Reactor는 굉장히 많은 수의 Operator를 지원하며, 각각의 Operator마다 해당 Operator를 잘 설명하는 마블 다이어그램을 가진다.
- 가장 오른쪽의 수직 바가 데이터의 emit이 정상적으로 끝났음을 의미한다. (onComplete Signal)
- X표시는 에러가 발생해 데이터 처리가 종료되었음을 의미한다. (onError Signal)
마블 다이어그램으로 Publisher 이해하기
위 그림은 Reactor의 Publisher 타입 중 하나인 Mono를 마블 다이어그램으로 표현한 것이다.
- Mono는 단 하나의 데이터를 emit하는 Publisher이기 때문에 그림에서도 하나의 데이터 (3)만 표현한다
- 정확히는 0개 또는 1개의 데이터를 emit하는 Publisher이다
public class Example6_1 {
public static void main(String[] args) {
Mono.just("Hello Reactor")
.subscribe(System.out::println);
}
}
- just()는 한 개 이상의 데이터를 emit 하기 위한 대표적인 Operator로서 2개 이상의 데이터를 파라미터로 전달할 경우, 내부적으로 fromArray()를 이용해 데이터를 emit 한다
public class Example6_2 {
public static void main(String[] args) {
Mono
.empty()
.subscribe(
none -> System.out.println("# emitted onNext signal"),
error -> {},
() -> System.out.println("# emitted onComplete signal")
);
}
}
- 데이터를 한 건도 emit하지 않는 경우, empty()를 사용해 onComplete Signal을 전송한다
- 실행해보면 # emitted onComplete signal이 출력되는데, 이를 통해 emit할 데이터가 없는 경우 바로 onComplete Signal을 전송한다는 걸 알 수 있다
더보기
subscrite()의 람다 표현식 파라미터
- 첫 번째 람다 표현식은 Publisher가 onNext Signal을 전송하면 실행
즉, Subscriber가 Publisher로부터 데이터를 전달받기 위해 사용 - 두 번째 람다 표현식은 Publisher가 onError Signal을 전송하면 실행
- 세 번째 람다 표현식은 Publisher가 onComplete Signal을 전송하면 실행
위 그림은 Reactor의 Publisher 타입 중 하나인 Flux를 마블 다이어그램으로 표현한 것이다
- Mono와 차이점은 Flux는 emit되는 데이터가 여러 개라는 점이다.
- Flux는 0개 또는 1개 이상의 데이터를 emit할 수 있기 때문에 Mono의 데이터 emit 범위를 포함한다.
public class Example6_4 {
public static void main(String[] args) {
Flux.just(6, 9, 13)
.map(num -> num % 2)
.subscribe(System.out::println);
}
}
- just()에서 emit하는 세 개의 숫자들을 전달받은 후에 map()에서 2로 나눈 나머지를 Subscriber에 전달
public class Example6_5 {
public static void main(String[] args) {
Flux.fromArray(new Integer[]{3, 6, 7, 9})
.filter(num -> num > 6)
.map(num -> num * 2)
.subscribe(System.out::println);
}
}
- 데이터 소스로 제공되는 배열 데이터를 처리하기 위해 fromArray()를 사용한다
- 전달받은 배열의 원소를 하나씩 차례대로 emit하면 filter()에서 6보다 큰 수만 필터링 한 후, 다시 map()으로 전달한다
public class Example6_6 {
public static void main(String[] args) {
Flux<String> flux =
Mono.justOrEmpty("Steve")
.concatWith(Mono.justOrEmpty("Jobs"));
flux.subscribe(System.out::println);
}
}
- 두 개의 Mono를 연결해 Flux로 변환
- just()의 경우 파라미터의 값으로 null을 허용하지 않지만 justOrEmpty()는 null을 허용한다
- justOrEmpty()의 파라미터로 null이 전달되면 내부적으로 empty()를 호출하도록 구현되어 있다
- concatWith()는 concatWith()를 호출하는 Publisher와 concatWith()의 파라미터로 전달되는 Publisher가 각각 emit하는 데이터들을 하나로 연결해서 새로운 Publisher의 데이터 소스로 만들어준다
- String의 concat처럼 하나로 이어 붙이는게 아니라, emit할 데이터들을 일렬로 줄 세워서 하나의 소스로 만든 후 차례차례 emit한다고 보면 된다

public class Example6_7 {
public static void main(String[] args) {
Flux.concat(
Flux.just("Mercury", "Venus", "Earth"),
Flux.just("Mars", "Jupiter", "Saturn"),
Flux.just("Uranus", "Neptune", "Pluto"))
.collectList()
.subscribe(planets -> System.out.println(planets));
}
}
- concatWith()의 경우 두 개의 데이터 소스만 연결할 수 있지만, concat()은 여러 개의 데이터 소스를 원하는 만큼 연결할 수 있다
- collectList()는 Upstream Publisher에서 emit하는 데이터를 모아서 List의 원소로 포함시킨 새로운 데이터 소스로 만들어준다
- 간단한 문제 ㅎㅎ
- Q. concat()에서 리턴하는 Publisher는 Mono일까 Flux일까?
- A. Flux이다. concat()을 이용해 3개의 Flux가 가지고 있는 아홉 개의 데이터를 연결하기 때문에 concat()의 리턴 값은 Flux일 수밖에 없음!
- Q. collectList()에서 리턴하는 Publisher는 Mono일까 Flux일까?
- A. Mono이다. collectList()는 여러 개의 데이터를 하나의 List에 원소로 포함시킨다. List에 포함된 원소는 여러 개이지만 List 자체는 하나이기 때문에 한 개의 데이터만 emit할 수 있는 Mono를 리턴한 것.
- Q. 최종적으로 출력되는 데이터의 형태는 무엇일까?
- A. [Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto]
정답이 List이기 때문에 각각의 데이터를 반복적으로 출력하는 것이 아니라, List 객체를 그대로 출력한다.
- A. [Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto]
- Q. concat()에서 리턴하는 Publisher는 Mono일까 Flux일까?
마무리하며,,,
마블 다이어그램을 가장한 Flux, Mono에 대한 포스팅이었다. (ㅋㅋ)
비동기 데이터 흐름을 파악하는게 쉽지 않기 때문에 마블 다이어그램이 참 유용한 것 같다!
'스터디 > 기타' 카테고리의 다른 글
단축 URL 생성기 (민감정보 노출 방지를 곁들인,,) (1) | 2025.09.27 |
---|---|
[Reactive Programming] Blocking I/O와 Non-Blockin I/O (1) | 2025.09.25 |
[Reactive Programming] 리액티브 프로그래밍 & 리액티브 스트림즈 (1) | 2025.08.29 |
ENUM과 DB 매핑 전략 (feat. Enum Converter,, 코드 테이블,,) (1) | 2025.08.28 |
(충격) 지금까지 배치 서버를 써본 줄 알았는데… 아니었음 (3) | 2025.08.26 |
Comments