CHAP17 - Modern-Java-in-Action/Online-Study GitHub Wiki

์ฃผ์ œ: ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

RP = Reactive Programming

์ด ์žฅ์˜ ๋‚ด์šฉ

  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ •์˜ํ•˜๊ณ  ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋งค๋‹ˆํŒจ์Šคํ† ๋ฅผ ํ™•์ธํ•จ
    • ๊ณผ๊ฑฐ์˜ ์ž˜๋ชป๋œ ํ–‰์ ์„ ์†”์งํžˆ ๋ฐ˜์„ฑํ•˜๋ฉฐ ์ƒˆ๋กœ์šด ๋ฏธ๋ž˜๋ฅผ ์œ„ํ•œ ๊ตฌ์ฒด์  ์•ฝ์†์„ ๊ณต๊ฐœ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ฑ…์ž„์„ฑ์„ ๋‹ด์•„ ๋ฌธ์„œ๋กœ์„œ ์„ ์–ธํ•˜๋Š” ๊ฒƒ
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ˆ˜์ค€, ์‹œ์Šคํ…œ ์ˆ˜์ค€์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ, ์ž๋ฐ” 9ํ”Œ๋กœ API๋ฅผ์‚ฌ์šฉํ•œ์˜ˆ์ œ์ฝ”๋“œ
  • ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ RxJava ์†Œ๊ฐœ
  • ์—ฌ๋Ÿฌ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์„ ๋ณ€ํ™˜ํ•˜๊ณ  ํ•ฉ์น˜๋Š” RxJava ๋™์ž‘ ์‚ดํŽด๋ณด๊ธฐ
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์˜ ๋™์ž‘์„ ์‹œ๊ฐ์ ์œผ๋กœ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋งˆ๋ธ” ๋‹ค์ด์–ด๊ทธ๋žจ

์™œ ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ธ”๋ผ๋ธ”๋ผ ๊ฐ€ ํ•„์š”ํ•˜๊ฒŒ ๋˜์—ˆ์„๊นŒ?

์˜ค๋Š˜๋‚  ์ƒํ™ฉ์ด ๋ณ€ํ–ˆ๋‹ค.

  • ๋น…๋ฐ์ดํ„ฐ
  • ๋งŽ์€ ๋ชจ๋ฐ”์ผ ๋””๋ฐ”์ด์Šค์™€ ์ˆ˜์ฒœ๊ฐœ ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ”„๋กœ์„ธ์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ ํ™˜๊ฒฝ
  • 1๋…„ ๋‚ด๋‚ด ๊ฐ€๋Šฅํ•œ ๊ณ ๊ฐ์˜ ์„œ๋น„์Šค ์š”๊ตฌ

4๊ฐ€์ง€ ๋งค๋‹ˆํŽ˜์Šคํ†  ํ€ด์ฆˆ

๋งคํ•‘ํ•˜์‹œ์˜ค. ( Elastic Responsive Resilient Message-driven )

  • ์‹œ์Šคํ…œ์€ ์ ์‹œ์— ์‘๋‹ตํ•ด์•ผ ํ•œ๋‹ค.
  • ์‹œ์Šคํ…œ์€ ๋А์Šจํ•œ ๊ฒฐํ•ฉ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์— ๋น„๋™๊ธฐ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • ์‹œ์Šคํ…œ์€ ๋†’์€ ๋ถ€ํ•˜์—์„œ๋„ ์‘๋‹ต์„ฑ์„ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์‹œ์Šคํ…œ์€ ์‘๋‹ต์„ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค.

๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ vs ๋ฆฌ์•กํ‹ฐ๋ธŒ ์‹œ์Šคํ…œ

์ž˜ ์ดํ•ด์•ˆ๋จ

๋งํฌ

  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์‹œ์Šคํ…œ
    • ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์˜ ํ•œ ์ข…๋ฅ˜
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์กฐ๋ฆฝํ•˜๊ณ  ์ƒํ˜ธ์†Œํ†ต์„ ์กฐ์ ˆ
    • ์œ„์˜ ๋งค๋‹ˆํŽ˜์Šคํ† ๋ฅผ ๋”ฐ๋ผ, ์ž‘์—… ๋ถ€ํ•˜๊ฐ€ ์žˆ์œผ๋ฉด ์œ ๋™์ ์œผ๋กœ scale-up ํ•˜๋Š” ์„ฑ์งˆ์„ ๊ฐ€์ง
    • ์ฃผ์š” ์†์„ฑ: ๋ฉ”์‹œ์ง€ ์ฃผ๋„
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
    • ๋น„๊ต์  ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ๋งŒ ์œ ์ง€๋˜๋Š” ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์— ๊ธฐ๋ฐ˜ํ•œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ๋ณดํ†ต ์ด๋ฒคํŠธ ์ฃผ๋„๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.
  • ์š”์•ฝ
    • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ชจ์—ฌ ์‹œ์Šคํ…œ์ด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

์•ž์œผ๋กœ ๋ฐฐ์šธ ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•„์š”ํ•œ ์ด์œ ์™€ ์ผ๋ฐ˜์  ์‚ฌ์‹ค๋“ค

  • ์Šค๋ ˆ๋“œ๋Š” ๋น„์‹ธ๊ณ  ๊ท€ํ•œ ์ž์›์ด๋‹ค. (ํ• ๋‹นํ•˜๊ณ  ํ•ด์ œํ•˜๋Š” ๊ฒƒ๋„ ๋น„์‹ธ๋‹ค)
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ ˆ์ด์Šค ์ปจ๋””์…˜, ๋ฐ๋“œ๋ฝ ๊ฐ™์€ ๊ฐ™์€ ์ €์ˆ˜์ค€์˜ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฌธ์ œ๋ฅผ ์ง์ ‘ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง€๋ฉด์„œ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ๊ตฌํ˜„์— ๋” ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์Šค๋ ˆ๋“œ ํ’€์„ ์ชผ๊ฐค๋•Œ๋Š” ๋ธ”๋Ÿญ ๋™์ž‘์„ ๋„ฃ์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
    • RxJava, Akka ๊ฐ™์€ ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ณ„๋„๋กœ ์ง€์ •๋œ ์Šค๋ ˆ๋“œ ํ’€์—์„œ ๋ธ”๋ก ๋™์ž‘์„ ์‹คํ–‰์‹œ์ผœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

![image-20220219195249486](D:\0 Google Drive\03 ์Šคํ„ฐ๋”” ๋ชจ์ž„\๋ชจ๋˜์ž๋ฐ”\10์ฃผ์ฐจ\17์žฅ.assets\image-20220219195249486.png)

๋ฆฌ์•กํ‹ฐ๋ธŒ ์‹œ์Šคํ…œ์€ ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•œ ๊ฐœ์˜ ์ผ๊ด€์ ์ธ, ํšŒ๋ณตํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค„ ๋ฟ ์•„๋‹ˆ๋ผ ์ด๋“ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํŒจํ•ด๋„ ์ „์ฒด ์‹œ์Šคํ…œ์€ ๊ณ„์† ์šด์˜๋  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜๋‹ค.

๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ๊ณผ Flow API

  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ ์ด๋ž€?
    • ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
    • ๋ฌดํ•œ์˜ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ๊ทธ๋ฆฌ๊ณ  ๋ธ”๋กํ•˜์ง€ ์•Š๋Š” ์—ญ์••๋ ฅ์„ ์ „์ œํ•ด ์ฒ˜๋ฆฌํ•˜๋Š” ํ‘œ์ค€ ๊ธฐ์ˆ 
  • ์—ญ์••๋ ฅ์ด๋ž€?
    • ๋ฐœํ–‰-๊ตฌ๋… ํ”„๋กœํ† ์ฝœ์—์„œ ๊ตฌ๋…์ž๊ฐ€ ๋А๋ฆฐ ์†๋„๋กœ ์ด๋ฒคํŠธ๋ฅผ ์†Œ๋น„ํ•˜๋ฉด์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•˜๋Š” ์žฅ์น˜
    • ์‚ฌ์šฉํ•จ์œผ๋กœ์จ
      • ์ด๋ฒคํŠธ๋ฅผ ์žƒ์–ด๋ฒ„๋ฆฌ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ
      • ์ด๋ฒคํŠธ ์ˆ˜์‹ ์„ ๋Šฆ์ถ”๋Š” ๊ฒƒ, ๊ฐ€๋Šฅํ•œ ์ˆ˜์‹ ๋Ÿ‰ ์•Œ๋ฆผ๊ธฐ๋Šฅ, ๋‚จ์€์ผ ์ฒ˜๋ฆฌ ์˜ˆ์ธก ์‹œ๊ฐ„ ์•Œ๋ฆผ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์œผ๋กœ ์—…์ŠคํŠธ๋ฆผ ๊ตฌ๋…์ž์—๊ฒŒ ์•Œ๋ฆด์ˆ˜ ์žˆ๋‹ค.
      • ๋น„๋™๊ธฐ API๋ฅผ ์ด์šฉํ•˜๋ฉด ํ•˜๋“œ์›จ์–ด ์‚ฌ์šฉ๋ฅ ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋А๋ฆฐ ๋‹ค์šด์ŠคํŠธ๋ฆผ ์ปดํฌ๋„ŒํŠธ์— ๋„ˆ๋ฌด ํฐ ๋ถ€ํ•˜๋ฅผ ์ค„ ๊ฐ€๋Šฅ์„ฑ๋„ ์ƒ๊ธด๋‹ค. ์—ญ์••๋ ฅ์€ ์ด ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•œ๋‹ค.
  • ํšŒ์‚ฌ๋ณ„ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ ์ž์ฒด ๊ตฌํ˜„ ์‚ฌ๋ก€
    • ๋ผ์ดํŠธ๋ฐด๋“œ - Akka Stream
    • ๋„ทํ”Œ๋ฆญ์Šค - RxJava
    • ๋ฆฌ์•กํ„ฐ - Pivotal
    • ๋ ˆ๋“œํ–‡ - Vert.x
  • Flow API๋ž€?
    • ์ž๋ฐ”์—์„œ ์œ„ 4๊ฐœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ตœ์†Œ ๊ธฐ๋Šฅ ์ง‘ํ•ฉ์œผ๋กœ๋งŒ ์žฌ์ •์˜ํ•œ ํ‘œ์ค€ API = Flow API

Flow ํด๋ž˜์Šค ์†Œ๊ฐœ

Flow ํด๋ž˜์Šค๊ฐ€ ํฌํ•จํ•˜๋Š” 4๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค

// Publisher: ์ด๋ฒคํŠธ ๋ฐœํ–‰ ์ˆ˜ํ–‰
@FunctionalInterface
public interface Publisher<T> {
    void subscribe(Subscriber<? super T> s);
}

// Subscriber: ์ž์‹ ์„ Publisher ์—๊ฒŒ ๋“ฑ๋ก ์š”์ฒญํ•ด ์ด๋ฒคํŠธ ์†Œ๋น„
// ํ˜ธ์ถœ ์ˆœ์„œ : onSubscribe -> onNext (์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœ ๊ฐ€๋Šฅ) -> onError ๋˜๋Š” onComplete 
public interface Subscriber<T> {
    void onSubscribe(Subscription s);
    void onNext(T t);
    void onError(Throwable t);
    void onComplete();
}

// Subscription: Publisher์™€ Subscriber ์‚ฌ์ด์˜ ์ œ์–ด ํ๋ฆ„, ์—ญ์••๋ ฅ์„ ๊ด€๋ฆฌํ•œ๋‹ค.
public interface Subscription {
    void request(long n);
    void cancel();
}

// Processor: ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€๊ณต, ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. 
// ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ณ€ํ˜•์‹œ์ผœ ๋‹ค์Œ ๊ตฌ๋…์ž ํ•œํ…Œ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ. (์ค‘๊ฐ„์ž ์—ญํ• ์ด๋ฉฐ, ๊ตฌ๋…์ž์™€ ๋ฐœํ–‰์ž ๋‘ ์—ญํ•  ์ˆ˜ํ–‰)
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { }
  • ์–ธ์ œ Subscriber์˜ onSubscribe()์™€ onNext()๊ฐ€ ์‚ฌ์šฉ๋ ๊นŒ?
    • onSubscribe(): Subscriber๊ฐ€ Publisher์— ์ž์‹ ์„ ๋“ฑ๋กํ•  ๋•Œ Publisher๋Š” ์ฒ˜์Œ์œผ๋กœ onSubscribe ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด Subscription ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
    • onNext(): Publisher๊ฐ€ ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋œ๋‹ค.
  • Subscription์˜ request()์™€ cancel() ๋ฉ”์„œ๋“œ์˜ ์—ญํ• ์€?
    • request(): Publisher์—๊ฒŒ ์ฃผ์–ด์ง„ ๊ฐœ์ˆ˜์˜ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Œ์„ ์•Œ๋ฆฌ๋Š”๋ฐ ์‚ฌ์šฉ
    • cancel(): ๊ตฌ๋… ์ทจ์†Œ ์š”์ฒญ
  • ์ž‘๋™ ์š”์•ฝ

์ƒ˜ํ”Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค์–ด๋ณด๊ธฐ

์˜จ๋„ ์ •๋ณด ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ฐ›์•„๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด ๋ณด์ž

๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ๋ช… ์ฃผ๊ธฐ ํ™•์ธํ•˜๊ธฐ

![image-20220219203502517](D:\0 Google Drive\03 ์Šคํ„ฐ๋”” ๋ชจ์ž„\๋ชจ๋˜์ž๋ฐ”\10์ฃผ์ฐจ\17์žฅ.assets\image-20220219203502517.png)

  • ์—ฌ๊ธฐ ์ฝ”๋“œ์—์„ 
    • Publisher: ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ๋กœ ๋ฐ”๋กœ ์ƒ์„ฑ
    • Subscriber: TempSubscriber
    • Subscription: TempSubscription
    • ๊ธฐํƒ€
      • TempInfo: ์˜จ๋„ ์ •๋ณด ๋‹ด๋Š” ๊ฐ์ฒด

ํŠน์ • ๋„์‹œ ์˜จ๋„ ์ •๋ณด ๊ตฌ๋… ํ•˜๊ธฐ

import java.util.concurrent.Flow.*;
public class Main {
    public static void main( String[] args ) {
        // Subscriber๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ Subscriber์˜ onSubscribe ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
        getTemperatures( "New York" ).subscribe( new TempSubscriber() );
    }
    private static Publisher<TempInfo> getTemperatures( String town ) {
        // ์•„๋ž˜ ์ฝ”๋“œ ์ต์ˆ™ํ•˜์ง€๊ฐ€ ์•Š๋„ค์š”...
        return subscriber -> subscriber.onSubscribe(
            new TempSubscription( subscriber, town ) );
    }
}

์˜จ๋„ ์ •๋ณด๋ฅผ ๋ฐ›์•„๋ณผ ์˜ˆ์ •์ธ ๊ตฌ๋…์ž

import java.util.concurrent.Flow.*;
public class TempSubscriber implements Subscriber<TempInfo> {
    private Subscription subscription;
    @Override
    public void onSubscribe( Subscription subscription ) {
        this.subscription = subscription; // ๊ตฌ๋… ์ €์žฅ
        subscription.request( 1 ); // 1๋ฒˆ์งธ ์š”์ฒญ
    }
    @Override
    public void onNext( TempInfo tempInfo ) {
        // Subscription์ด ์ „๋‹ฌํ•œ ์˜จ๋„๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ƒˆ ๋ ˆํฌํŠธ๋ฅผ ๋‹ค์‹œ ์š”์ฒญ
        System.out.println( tempInfo );
        subscription.request( 1 );
    }
    @Override
    public void onError( Throwable t ) {
        System.err.println(t.getMessage());
    }
    @Override
    public void onComplete() {
        System.out.println("Done!");
    }
}

์˜จ๋„ ์ •๋ณด๋ฅผ ๋ฐ›์•„๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ตฌ๋…๊ถŒ

import java.util.concurrent.Flow.*;
public class TempSubscription implements Subscription {
    private final Subscriber<? super TempInfo> subscriber;
    private final String town;
    public TempSubscription( Subscriber<? super TempInfo> subscriber,
                            String town ) {
        this.subscriber = subscriber;
        this.town = town;
    }
    @Override
    public void request( long n ) {
        // ์š”์ฒญํ•œ ์ด๋ฒคํŠธ ์ˆ˜ ๋งŒํผ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค 
        for (long i = 0L; i < n; i++) {
            try {
                subscriber.onNext( TempInfo.fetch( town ) );
            } catch (Exception e) {
                subscriber.onError( e );
                break;
            }
        }
    }
    @Override
    public void cancel() {
        subscriber.onComplete();
    }
}

์˜จ๋„ ์ •๋ณด ๊ฐ์ฒด

import java.util.Random;
public class TempInfo {
    public static final Random random = new Random();
    private final String town;
    private final int temp;
    public TempInfo(String town, int temp) {
        this.town = town;
        this.temp = temp;
    }
    // ํŠน์ • ํƒ€์šด์˜ ์˜จ๋„๋ฅผ ๋ฆฌํ„ด
    public static TempInfo fetch(String town) {
        if (random.nextInt(10) == 0)
            throw new RuntimeException("Error!");
        return new TempInfo(town, random.nextInt(100));
    }
    @Override
    public String toString() {
        return town + " : " + temp;
    }
    public int getTemp() {
        return temp;
    }
    public String getTown() {
        return town;
    }
}

๊ฒฐ๊ณผ - ๋‰ด์š•์˜ ์˜จ๋„๋ฅผ ๋„ค ๋ฒˆ ์„ฑ๊ณต์ ์œผ๋กœ ์ „๋‹ฌํ–ˆ์ง€๋งŒ ๋‹ค์„ฏ ๋ฒˆ์งธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ

New York :: 44
New York :: 68
New York :: 95
New York :: 30
Error!

์ง€๊ธˆ๊นŒ์ง€ ๊ฐœ๋ฐœํ•œ ์ฝ”๋“œ์— ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ํ€ด์ฆˆ๋ฅผ ๋ณด๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

ํ€ด์ฆˆ

์ง€๊ธˆ๊นŒ์ง€ ๊ฐœ๋ฐœํ•œ ์ฝ”๋“œ์— ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋ฌธ์ œ๋Š” Tempinfo ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์—๋Ÿฌ๋ฅผ ์ž„์˜๋กœ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์ฝ”๋“œ ๋•Œ๋ฌธ์— ๊ฐ์ถฐ์ง„ ์ƒํƒœ๋‹ค. ์ž„์˜๋กœ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์ฝ”๋“œ๋ฅผ ์—†์•ค ๋‹ค์Œ main์„ ์˜ค๋ž˜ ์‹คํ–‰ํ•˜๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ?

.
.
.
.
.
.
.
.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • Executor๋ฅผ TempSubscription์œผ๋กœ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ TempSubscriber๋กœ ์„ธ ์š”์†Œ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
  • ์ด๊ฒƒ ์ดํ•ด ์ž˜ ์•ˆ๋œ๋‹ค.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TempSubscription implements Subscription {
    private static final ExecutorService executor =
        Executors.newSingleThreadExecutor();
    @Override
    public void request( long n ) {
        // ๋‹ค๋ฅธ์Šค๋ ˆ๋“œ์—์„œ ๋‹ค์Œ์š”์†Œ๋ฅผ ๊ตฌ๋…์ž์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.
        executor.submit( () -> {
            for (long i = 0L; i < n; i++) {
                try {
                    subscriber.onNext( TempInfo.fetch( town ) );
                } catch (Exception e) {
                    subscriber.onError( e );
                    break;
                }
            }
        });
    }
}

Processor ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ํ•˜๊ธฐ

Processor ์ธํ„ฐํŽ˜์ด์Šค์˜ ์‚ฌ์šฉ๋ฒ•๋„ ํ™•์ธํ•˜์ž

  • ๋ชฉ์ : Publisher๋ฅผ ๊ตฌ๋…ํ•œ ๋‹ค์Œ ์ˆ˜์‹ ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•ด ๋‹ค์‹œ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ
  • Subscriber ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” ๋‹จ์ˆœํžˆ ์ˆ˜์‹ ํ•œ ๋ชจ๋“  ์‹ ํ˜ธ๋ฅผ ์—…์ŠคํŠธ๋ฆผ Subscriber๋กœ ์ „๋‹ฌํ•˜๋ฉฐ Publisher์˜ subscribe ๋ฉ”์„œ๋“œ๋Š” ์—…์ŠคํŠธ๋ฆผ Subscriber๋ฅผ Processor๋กœ ๋“ฑ๋กํ•˜๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

Main: Publisher๋ฅผ ๋งŒ๋“ค๊ณ  TempSubscriberB ๊ตฌ๋…์‹œํ‚ด

import java.util.concurrent.Flow.*;
public class Main {
    public static void main( String[] args ) {
        getCelsiusTemperatures( "New York" )
            .subscribe( new TempSubscriber() );
    }
    public static Publisher<TempInfo> getCelsiusTemperatures(String town) {
        return subscriber -> {
            TempProcessor processor = new TempProcessor();
            processor.subscribe( subscriber );
            processor.onSubscribe( new TempSubscription(processor, town) );
        };
    }
}

import java.util.concurrent.Flow.*;
// ํ™”์”จ๋ฅผ ์„ญ์”จ๋กœ ๋ณ€ํ™˜
public class TempProcessor implements Processor<TempInfo, TempInfo> {
    private Subscriber<? super TempInfo> subscriber;
    @Override
    public void subscribe( Subscriber<? super TempInfo> subscriber ) {
        this.subscriber = subscriber;
    }
    
    // ๋กœ์ง์„ ํฌํ•จํ•˜๋Š” ์œ ์ผํ•œ ๋ฉ”์„œ๋“œ
    @Override
    public void onNext( TempInfo temp ) {
        // ์„ญ์”จ๋กœ ๋ณ€ํ™˜ํ•œ ๋‹ค์Œ TempInfo ๋ฅผ ๋‹ค์‹œ ์ „์†ก
        subscriber.onNext( new TempInfo( temp.getTown(),
                                        (temp.getTemp() - 32) * 5 / 9) ); 
    }
    
    @Override
    public void onSubscribe( Subscription subscription ) {
        // ์—…์ŠคํŠธ๋ฆผ ๊ตฌ๋…์ž์— ์ „๋‹ฌ 
        subscriber.onSubscribe( subscription );
    }
    @Override
    public void onError( Throwable throwable ) {
        // ์—…์ŠคํŠธ๋ฆผ ๊ตฌ๋…์ž์— ์ „๋‹ฌ 
        subscriber.onError( throwable );
    }
    @Override
    public void onComplete() {
        // ์—…์ŠคํŠธ๋ฆผ ๊ตฌ๋…์ž์— ์ „๋‹ฌ 
        subscriber.onComplete();
    }
}

์‹คํ–‰ ์ฝ”๋“œ

New York : 10
New York : -12
New York : 23
Error!

์™œ Flow API ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๊ฐ€?

  • Flow API๊ฐ€ ๊ตฌํ˜„์„ ์žฌ๊ณตํ•˜์ง€ ์•Š์•„, ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.
  • ๋‹ค๋ฅธ ์‚ฌ๋ก€๋ฅผ ๋ณด๋ฉด, ์ž๋ฐ”๋Š” List์˜ ๊ตฌํ˜„์ธ ArrayList๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ์™œ ๊ตฌํ˜„ ์ œ๊ณต์„ ์•ˆํ• ๊นŒ?
    • ์ด์œ : API๋ฅผ ๋งŒ๋“ค ๋‹น์‹œ Akka, RxJava ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์˜ ์ž๋ฐ” ์ฝ”๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค
    • ์ฆ‰, ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์˜ ๊ณตํ†ต ๋ถ€๋ถ„๋งŒ ๋ด…์•„๋‚ด ํ‘œ์ค€ํ™” ์ž‘์—…์„ ํ•œ ๊ฒƒ์ด๋‹ค.

RxJava ์‚ฌ์šฉํ•˜๊ธฐ

  • RxJava: ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•œ ์ข…๋ฅ˜

  • RxJava ๋Š” Flow.Publisher ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋‘ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณต

    • io.reactivex.Flowable
      • Pull ๊ธฐ๋ฐ˜ ์—ญ์••๋ ฅ ๊ธฐ๋Šฅ ํฌํ•จ
      • ์ด๋ฏธ Flow API๋ฅผ ํ†ตํ•ด ์—ญ์••๋ ฅ์„ ํ™•์ธํ–ˆ์œผ๋‹ˆ ์•„๋ž˜์„  ์ƒ๋žต
    • io.reactivex.Observable
      • ์—ญ์••๋ ฅ ์ง€์› X
      • ๋‹จ์ˆœํ•œ ๋งˆ์šฐ์Šค ์›€์ง์ž„ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฒคํŠธ์— ์ ํ•ฉ
        • ์ด์œ : ๋งˆ์šฐ์Šค ์›€์ง์ž„์„ ๋А๋ฆฌ๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ๋ฉˆ์ถœ ์ˆ˜ ์—†๋“ฏ์ด ์—ญ์••๋ ฅ์„ ์ ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ
  • Flow API ์™€ ๋น„๊ต

    • Publisher ์—ญํ• : Observable

      • ์˜ต์ €๋ฒ„๋ธ”์€ ์—ญ์••๋ ฅ ์ง€์›์„ ์•ˆํ•˜๋ฏ€๋กœ, request() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š” ์—†๋‹ค.
      • Subscription ํด๋ž˜์Šค ์ด์šฉ์ด ํ•„์š” ์—†๋‹ค๋Š”๊ฑฐ ๊ฐ™์Œ.
    • Subscriber ์—ญํ• : Observer

      • ์˜ต์ €๋ฒ„๋Š” ์ถ”๊ฐ€๋กœ Disposable ์ธ์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค.

      • Observer ์ธํ„ฐํŽ˜์ด์Šค

        public interface Observer<T> {
            void onSubscribe(Disposable d);
            void onNext(T t);
            void onError(Throwable t);
            void onComplete();
        }
  • ์ข‹์€ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์œ„ํ•œ TIP

    • ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋…ธ์ถœํ•˜์ง€ ๋ง์ž.
      • ์ฆ‰, Observable์˜ ์ถ”๊ฐ€ ๊ตฌ์กฐ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ๋งŒ Observable ์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด Publisher์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
      • ๋น„์Šทํ•œ ์‚ฌ๋ก€
        • ์ „๋‹ฌํ•˜๋Š” ๊ฐ’์ด ArrayList ์ž„์„ ์•Œ์ง€๋งŒ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์„ List๋กœ ์„ค์ •ํ•จ์œผ๋กœ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์„ ๋ฐ–์œผ๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.
        • ์ด๋Ÿผ์œผ๋กœ์จ, LinkedList๋กœ ์ ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
        • ๋‹คํ˜•์„ฑ
  • ๋งˆ๋ธ” ๋‹ค์ด์–ด๊ทธ๋žจ

    • ๋ชจํ˜•๋“ค์„ ์ˆ˜ํ‰์„ ์— ํ‘œ์‹œํ•ด์„œ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์˜ ํ๋ฆ„์„ ๋ณด์—ฌ์ค€๋‹ค.

![image-20220220002256504](D:\0 Google Drive\03 ์Šคํ„ฐ๋”” ๋ชจ์ž„\๋ชจ๋˜์ž๋ฐ”\10์ฃผ์ฐจ\17์žฅ.assets\image-20220220002256504.png)

์ง€๊ธˆ๋ถ€ํ„ฐ๋Š” RxJava์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์˜ ๊ตฌํ˜„์„ ์ด์šฉํ•ด์„œ ์˜จ๋„ ๋ณด๊ณ  ์‹œ์Šคํ…œ์„ ์ •์˜ํ•ด๋ณด์ž.

Observable ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ

Observable, Flowable ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  • just(): ํ•œ ๊ฐœ ์ด์ƒ์˜ ์š”์†Œ๋ฅผ ์ด์šฉํ•ด ์ด๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” Observable๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
  • interval(): ํŠน์ • ์†๋„๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” ์ƒํ™ฉ์— ์œ ์šฉํ•˜๋‹ค.

just() ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ

// Observable์˜ ๊ตฌ๋…์ž๋Š” onNext("first"), onNext("second"), onComplete()์˜ ์ˆœ์„œ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š”๋‹ค.
Observable<String> strings = Observable.just( "first", "second" );
Disposable disposable = strings.subscribe(System.out::println); // ๊ตฌ๋…ํ•˜๊ธฐ 
disposable.dispose(); // ๊ตฌ๋… ์ทจ์†Œ 
System.out.println(disposable.isDisposed());

interval() ์‚ฌ์šฉ ์˜ˆ

  • ์ด ์ฝ”๋“œ๋Š” ํ”„๋ฆฐํŒ…์ด ์•ˆ๋˜๊ณ  ์ข…๋ฃŒ๋˜๋ฒ„๋ฆฐ๋‹ค.
    • ์ด์œ : ๋งค ์ดˆ๋งˆ๋‹ค ์ •๋ณด๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” Observable์ด RxJava์˜ ์—ฐ์‚ฐ ์Šค๋ ˆ๋“œ ํ’€ ์ฆ‰ ๋ฐ๋ชฌ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธํ”„๋ฆฐํŒ…์ด ์•ˆ๋œ๋‹ค.
    • ํ•ด๊ฒฐ: blockingSubscribe() ์‚ฌ์šฉํ•˜๊ธฐ
// main ํ”„๋กœ๊ทธ๋žจ์€ ์‹คํ–‰ํ•˜์ž ๋งˆ์ž ๋”ฐ๋กœ ์‹คํ–‰ํ•  ์ฝ”๋“œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ฐ”๋กœ ์ข…๋ฃŒ๋˜๊ณ 
// ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋˜์—ˆ์œผ๋ฏ€๋กœ ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ๋„ ์ „์— ๋ฐ๋ชฌ ์Šค๋ ˆ๋“œ๋„ ์ข…๋ฃŒ๋˜๋ฉด์„œ
// ์ด๋Ÿฐ ํ˜„์ƒ์ด ์ผ์–ด๋‚œ๋‹คใ„ด
Observable<Long> onePerSec = Observable.interval(1, TimeUnit.SECONDS);
onePerSec.subscribe(i -> System.out.println(TempInfo.fetch( "New York" )));
// onePerSec.blockingSubscribe(i -> System.out.println(TempInfo.fetch( "New York" )));

์˜ˆ์ œ์˜ ๋‚œ์ด๋„๋ฅผ ๋†’์—ฌ๋ณด์ž.

์˜จ๋„๋ฅผ ์ง์ ‘ ์ถœ๋ ฅํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด ๋งค ์ดˆ๋งˆ๋‹ค ์˜จ๋„๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” Observable์„ ๋ฐ˜ํ™˜ํ•ด๋ณด์ž.

main ์ฝ”๋“œ

// getTemperature ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” Observable์—  TempObserver ๋ฅผ ๊ตฌ๋…์‹œํ‚จ๋‹ค.
public static void main(String[] args) {
    // ๋งค์ดˆ๋งˆ๋‹ค ๋‰ด์š• ์˜จ๋„ ๋ฐฉ์ถœํ•˜๋Š” Oberserverble ์ƒ์„ฑ
    Observable<TempInfo> observable = getTemperature( "New York" );
    // Observable์— ๊ฐ€์ž…ํ•ด์„œ ์˜จ๋„ ์ถœ๋ ฅ
    observable.blockingSubscribe( new TempObserver() );
}
  • ์ˆœ์„œ ์ •๋ฆฌ
    • Observer๋ฅผ ์†Œ๋น„ํ•˜๋Š” ํ•จ์ˆ˜๋กœ๋ถ€ํ„ฐ Observable ๋งŒ๋“ค๊ธฐ
    • ๋งค์ดˆ ๋งˆ๋‹ค ๋ฌดํ•œ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋Š” ์ผ๋ จ์˜ long ๊ฐ’์„ ๋ฐฉ์ถœํ•˜๋Š” Observerble
    • ์†Œ๋น„๋œ Observer๊ฐ€ ํ๊ธฐ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ (์ด์ „ ์—๋Ÿฌ)
    • ์˜จ๋„๋ฅผ ๋‹ค์„ฏ๋ฒˆ ๋ณด๊ณ  ํ–ˆ์œผ๋ฉด ์˜ต์ €๋ฒ„๋ฅผ ์™„๋ฃŒํ•˜๊ณ  ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ
    • ์•„๋‹ˆ๋ฉด ์˜จ๋„๋ฅผ ์˜ต์ €๋ฒ„๋กœ ๋ณด๊ณ 
public static Observable<TempInfo> getTemperature(String town) {
    return Observable.create(emitter ->
                             Observable.interval(1, TimeUnit.SECONDS)
                             .subscribe(i -> {
                                 if (!emitter.isDisposed()) {
                                     // ํŽธ์˜์ƒ ๋‹ค์„ฏ ๋ฒˆ๋งŒ
                                     if ( i >= 5 ) {
                                         emitter.onComplete();
                                     } else {
                                         try {
                                             emitter.onNext(TempInfo.fetch(town));
                                         } catch (Exception e) {
                                             emitter.onError(e);
                                         }
                                     }
                                 }}));
}

์ˆ˜์‹ ํ•œ ์˜จ๋„๋ฅผ ์ถœ๋ ฅํ•˜๋Š” Observer

  • ์—ญ์••๋ ฅ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋‹ˆ, request() ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„์š” ์—†์–ด ๋‹จ์ˆœํ•˜๋‹ค.
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public class TempObserver implements Observer<TempInfo> {
    @Override
    public void onComplete() {
        System.out.println( "Done!" );
    }
    @Override
    public void onError( Throwable throwable ) {
        System.out.println( "Got problem: " + throwable.getMessage() );
    }
    @Override
    public void onSubscribe( Disposable disposable ) {
    }
    @Override
    public void onNext( TempInfo tempInfo ) {
        System.out.println( tempInfo );
    }
} 

๊ฒฐ๊ณผ

New York : 69
New York : 26
New York : 85
New York : 94
New York : 29
Done!

RxJava ์˜ˆ์ œ๋ฅผ ์กฐ๊ธˆ ๋” ๋ฐœ์ „์‹œ์ผœ์„œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด์ž.

RxJava ๊ณ ๊ธ‰์ง€๊ฒŒ ํ™œ์šฉํ•ด๋ณด๊ธฐ

Observable์ด ๋ฐฉ์ถœํ•˜๋Š” ์š”์†Œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•ด๋ณด์ž.

RxJava์˜ ์žฅ์ : ์ŠคํŠธ๋ฆผ์„ ํ•ฉ์น˜๊ณ , ๋งŒ๋“ค๊ณ , ๊ฑฐ๋ฅด๋Š” ๋“ฑ์˜ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

map() ์‚ฌ๋ก€

// ์„ญ์”จ๋ฅผ ํ™”์”จ๋กœ
public static Observable<TempInfo> getCelsiusTemperature(String town) {
    return getTemperature( town )
        .map( temp -> new TempInfo( temp.getTown(),
                                   (temp.getTemp() - 32) * 5 / 9) );
}

filter() ์‚ฌ๋ก€

// ํ•„ํ„ฐ์— ๋งŒ์กฑํ•˜๋Š” Observable๋“ค๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค. 
// ์•„๋ž˜๋Š” ๋™์ƒ์— ๊ฑธ๋ฆด ์œ„ํ—˜์ด ์žˆ์„ ๋•Œ ์•Œ๋ ค์ฃผ๋Š” ๊ฒฝ๊ณ  ์‹œ์Šคํ…œ ์‚ฌ๋ก€ 
public static Observable<TempInfo> getNegativeTemperature(String town) {
    return getCelsiusTemperature( town )
        .filter( temp -> temp.getTemp() < 0 ); // ์˜จ๋„๊ฐ€ ์„ญ์”จ 0๋„ ์ดํ•˜์ผ ๋•Œ๋งŒ
}

์„ธ ๋„์‹œ์˜ ์˜จ๋„๋ฅผ ์ถœ๋ ฅํ•˜๋Š” Main ํด๋ž˜์Šค

  • getCelsiusTemperatures(): ์—ฌ๋Ÿฌ ๋„์‹œ์—์„œ ์˜จ๋„๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” Observable์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌ๋˜์—ˆ๋‹ค.
public class Main {
    public static void main(String[] args) {
        Observable<TempInfo> observable = getCelsiusTemperatures(
            "New York", "Chicago", "San Francisco" );
        observable.blockingSubscribe( new TempObserver() );
    }
}
  • merge ๋ฉ”์„œ๋“œ๋Š” Iterable์„ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋งˆ์น˜ ํ•œ ๊ฐœ์˜ Observable ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋„๋ก ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์นœ๋‹ค.
public static Observable<TempInfo> getCelsiusTemperatures(String... towns) {
    return Observable.merge(Arrays.stream(towns)
                            .map(TempObservable::getCelsiusTemperature)
                            .collect(toList()));
}

๊ฒฐ๊ณผ

New York : 21
Chicago : 6
San Francisco : -15
New York : -3
Chicago : 12
San Francisco : 5
Got problem: Error!

merge ๋งˆ๋ธ” ๋‹ค์ด์–ด๊ทธ๋žจ

![image-20220220002712153](D:\0 Google Drive\03 ์Šคํ„ฐ๋”” ๋ชจ์ž„\๋ชจ๋˜์ž๋ฐ”\10์ฃผ์ฐจ\17์žฅ.assets\image-20220220002712153.png)

์ •๋ฆฌ

  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์‚ฌ์ƒ์€ ์ด๋ฏธ ์˜ค๋ž˜์ „์— ๋‚˜์™”์ง€๋งŒ ์ตœ๊ทผ์—์„œ์•ผ ๊ฐ๊ด‘๋ฐ›๋Š” ์ค‘์ด๋‹ค.
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์†Œํ”„ํŠธ์›จ์–ด๋Š” 4 ๊ฐ€์ง€ ์†์„ฑ (๋ฐ˜์‘์„ฑ, ํšŒ๋ณต์„ฑ, ํƒ„๋ ฅ์„ฑ, ๋ฉ”์‹œ์ง€ ์ฃผ๋„) ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์‹œ์Šคํ…œ๊ณผ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐœ๋… ์ฐจ์ด๋ฅผ ์•Œ์ž.
  • ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์—์„œ ์—ญ์••๋ ฅ์€ ์ค‘์š”ํ•˜๋‹ค. (๊ตฌ๋…์ž-๋ฐœํ–‰์ž ์†๋„ ์ฐจ์ดํ•ด๊ฒฐ)
  • RxJava๋Š” ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋„๊ตฌ ์ค‘ ๋Œ€ํ‘œ์ ์ด๋‹ค. (๊ฐ•๋ ฅํ•œ ์—ฐ์‚ฐ์ž๋“ค - filter, map ๋“ฑ)
  • ํ‘œ์ค€ํ™”๋œ ์ž๋ฐ” Flow API ๊ฐ€ ์žˆ๋‹ค.
โš ๏ธ **GitHub.com Fallback** โš ๏ธ