๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

RxSwift

[์Šคํ„ฐ๋”” 1์ฃผ์ฐจ] RxSwift ๊ฐœ์š”

Reactive eXtension ์ด๋ž€?๐Ÿ˜

* An API for asynchronous programming with observable streams.
* ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming
* In computing, reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change.

  • ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ํ๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ๋ฐ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ์ปดํ“จํŒ…์—์„œ ๋ฐ˜์‘ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ๋“ค๊ณผ ๋ณ€ํ™”์˜ ํผ์ง๊ณผ ๊ด€๊ณ„๋˜์–ด ์žˆ๋Š” ์„ ์–ธ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„

http://reactivex.io/ 

 

์žฅ์ ?๐Ÿ‘

  1. ์ผ๊ด€์„ฑ ์žˆ๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ฝ”๋“œ
  2. ๊ฐ€๋…์„ฑ์ด ์ข‹์€ ๊น”๋”ํ•œ ์ฝ”๋“œ
  3. ์‰ฌ์šด ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ

 

๐Ÿฐ RxSwift ๋ž€?

  • ReactiveX๋ฅผ ๋„์ž…ํ•œ Swift ์ „์šฉ ๊ตฌํ˜„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

https://github.com/ReactiveX/RxSwift

* RxSwift : ReactiveX์—์„œ ์ •์˜ํ•œ Rx ํ‘œ์ค€์„ ์ œ๊ณตํ•จ. ์ข…์†์„ฑ์€ ์—†์Œ.

* RxCocoa : ๊ณต์œ  ์‹œํ€€์Šค, ํŠน์„ฑ ๋“ฑ๊ณผ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ iOS / macOS / watchOS ๋ฐ tvOS ์•ฑ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ Cocoa ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ. RxSwift์™€ RxRelay์— ์ข…์†๋จ.

* RxRelay : Subjects๋ฅผ ๋žฉํ•‘ํ•˜๋Š” PublishRelay, BehaviorRelay, ReplayRelay๋ฅผ ์ œ๊ณตํ•จ. RxSwift์— ์ข…์†๋จ.

* RxTest & RxBlocking : Rx ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ. RxSwift์— ์ข…์†๋จ.

 

 

๐Ÿ’ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ž€?

: ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์–ด, ๋จผ์ € ์š”์ฒญํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ.

 

๐Ÿ’ ๋ช…๋ นํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Impreative programming)

- ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋‹ฌ์„ฑํ•ด ๋‚˜๊ฐ€๋Š” ๊ณผ์ •์— ๊ด€์‹ฌ์„ ๋‘ .

- ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ƒํƒœ์™€ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ๊ตฌ๋ฌธ์˜ ๊ด€์ ์—์„œ ์—ฐ์‚ฐ์„ ์„ค๋ช…ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„

- ์ปดํ“จํ„ฐ๊ฐ€ ์ˆ˜ํ–‰ํ•  ๋ช…๋ น๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋Š” ๊ฒƒ

- ์‹คํ–‰๋  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ช…์‹œํ•จ.

 

๐Ÿ• ์„ ์–ธํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Declarative programming)

- ์ปดํ“จํ„ฐ๊ฐ€ ๋ฌด์—‡์„ ํ•ด์•ผํ•  ์ง€๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

- ๋ชฉํ‘œ๋ฅผ ๋ช…์‹œํ•˜๊ณ  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ช…์‹œํ•˜์ง€ ์•Š์Œ.

Ex) ์›นํŽ˜์ด์ง€๋Š” ์„ ์–ธํ˜•์ž„. ํŽ˜์ด์ง€๊ฐ€ ์ œ๋ชฉ, ๊ธ€๊ผด, ๋ณธ๋ฌธ๊ณผ ๊ฐ™์ด '๋ฌด์—‡'์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•˜๋Š”์ง€ ๋ฌ˜์‚ฌํ•˜๋Š” ๊ฒƒ์ด์ง€ '์–ด๋–ค ๋ฐฉ๋ฒ•'์œผ๋กœ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๋ฌ˜์‚ฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ.

 

๐ŸฆŠ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Functional programming)

- ์„ ์–ธํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•˜์œ„ ๊ฐœ๋…

- ์ž๋ฃŒ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ•™์  ํ•จ์ˆ˜์˜ ๊ณ„์‚ฐ์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ณ  ์ƒํƒœ์™€ ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ€๋ฆฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„

- ์ˆœ์ˆ˜ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” let x = 1์ด๋ผ๊ณ  ์ง€์ • ํ›„์— 2๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์—†์Œ. => 2๋ฅผ ํ• ๋‹นํ•  ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹

 

์ผ๊ธ‰ ๊ฐ์ฒด(First-citizen class)

> ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์— ์ผ๋ฐ˜์ ์œผ๋กœ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ์—ฐ์‚ฐ์„ ๋ชจ๋‘ ์ง€์›ํ•˜๋Š” ๊ฐ์ฒด

- Swift์—์„œ๋Š” ํ•จ์ˆ˜๋ฅผ ์ผ๊ธ‰ ๊ฐ์ฒด๋กœ ์ทจ๊ธ‰ํ•จ.

- ์ธ์ž๊ฐ’๊ณผ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ.

- ๋ณ€์ˆ˜์— ๋Œ€์ž…์ด ๊ฐ€๋Šฅํ•˜๊ณ , ๋น„๊ต๋„ ๊ฐ€๋Šฅํ•จ.

- ๋ณ€์ˆ˜๋‚˜ ๊ตฌ์กฐ์ฒด ์•ˆ์— ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Œ.

 

์ˆœ์ˆ˜ ํ•จ์ˆ˜(Pure function)

> ์™ธ๋ถ€ ์ƒํƒœ์— ์˜์กด์ ์ด์ง€ ์•Š์œผ๋ฉฐ ๋ถ€์ž‘์šฉ(side-effect)์ด ์—†๋Š” ํ•จ์ˆ˜. ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์™ธ๋ถ€์— ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜

 

- ์ž…๋ ฅ์œผ๋กœ ์ฃผ์–ด์ง„ ๊ฒƒ ์™ธ์˜ ์—ฐ์‚ฐ์€ ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ.

- ์ž…๋ ฅ์ด ๋™์ผํ•˜๋ฉด ์ถœ๋ ฅ์ด ๋™์ผํ•ด์•ผ ํ•จ.

- ์ƒํƒœ ๋ณ€ํ™”๊ฐ€ ์—†์–ด์•ผ ํ•จ.

 

# ํ…Œ์ŠคํŠธ๊ฐ€ ์‰ฝ๊ณ , ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„์ง.

# ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง.

 

// ์ˆœ์ˆ˜ํ•จ์ˆ˜ ์˜ˆ์‹œ
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

add(1, 2) // 3

 

๐Ÿคฉ RxSwift์˜ ํ•„์š”์„ฑ

  1. ๋ช…์‹œ์ ์œผ๋กœ ๊ณต์œ ๋œ mutable state๋ฅผ ์•Œ๊ธฐ ์œ„ํ•จ
  2. Imperative Programming(๋ช…์‹œ์  ์ฝ”๋“œ)์˜ ํ•œ๊ณ„ ๊ทน๋ณต
    • ๋ช…์‹œ์  ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•  ๋•Œ, ๋ฉ”์†Œ๋“œ ์ˆœ์„œ์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š” ๋“ฑ ์–ด๋ ค์šด ์  ๊ทน๋ณต ๊ฐ€๋Šฅํ•จ.
  3. Side Effects๋ฅผ ํ†ตํ•ด ์ƒํƒœ ํŒŒ์•…
    • ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ๊ทธ ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์˜ ์ž‘์—…์„ ์ง์ ‘ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ์Œ.
  4. Declarative code(์„ ์–ธ์  ์ฝ”๋“œ)
    • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ, ๊ทธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•จ.
  5. Reactive System
    • Responsive : ์–ธ์ œ๋‚˜ UI๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Œ.
    • Resilient(ํƒ„๋ ฅ์ด ์žˆ๋Š”) : ๊ฐ behavior๋“ค์€ ๋…๋ฆฝ์ ์ด๊ณ , ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ํšŒ๋ณตํ•  ๋•Œ ์œ ์—ฐํ•จ.
    • Elastic(์œ ์—ฐํ•จ) : ๋‹ค์–‘ํ•œ workload๋ฅผ ์ฒ˜๋ฆฌ(๋ฐ์ดํ„ฐ ๋ชจ์Œ, ์ž์› ๊ณต์œ  ๋“ฑ)
    • Message driven : components๋“ค์€ ๋ฉ”์‹œ์ง€ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ฏ€๋กœ ์žฌ์‚ฌ์šฉ์„ฑ์˜ ์žฅ์ ์ด ์žˆ๊ณ , lifecycle๊ณผ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ.

์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

Observable

> Observable = observable sequence = sequence 

 

- ๊ด€์ฐฐ์ž์ธ Observer๊ฐ€ ์žˆ๊ณ  ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” Observable์ด ์žˆ์Œ.

- Observer๊ฐ€ Observable์„ ๊ตฌ๋…ํ•˜๋Š” ํ˜•ํƒœ๋กœ ์ด๋ฃจ์–ด์ง. 

- Observable์€ ์–ด๋–ค ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๊ฐ€์ง€๋Š” next ์ด๋ฒคํŠธ๋ฅผ ๊ณ„์†ํ•ด์„œ ๋ฐฉ์ถœ(emitting)ํ•จ.
- Next, Error, Completed ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ.

- Next ์ด๋ฒคํŠธ๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ Error๋‚˜ Completed ์ด๋ฒคํŠธ๋Š” ํ•œ๋ฒˆ๋งŒ ๋ฐœ์ƒํ•จ

- Error๋‚˜ Completed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋” ์ด์ƒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์Œ.

  • onNext : Observable์ด ๋ฐฐ์ถœํ•œ ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ ๋ฐ›์Œ.
  • onError : Observable์ด ์›ํ•˜๋˜ ๊ฐ’์ด ์•„๋‹ˆ๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ. ์˜ค๋ฅ˜ ์ •๋ณด ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ ๋ฐ›๊ณ  onNext๋‚˜ onCompleted ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ.
  • onCompleted : Observable์€ ์ •์ƒ์ ์ธ ๋™์ž‘ ์ดํ›„ ์ œ์ผ ๋งˆ์ง€๋ง‰์— ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ.

Operator

- ์—ฐ์‚ฐ์ž๋Š” Observable ์ƒ์—์„œ ๋™์ž‘ํ•˜๊ณ  Observable์„ ๋ฆฌํ„ดํ•จ.

- ์—ฐ์†์œผ๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ์—ฐ์‚ฐ์ž ์ฒด์ธ์„ ์ œ๊ณตํ•จ. ํ˜ธ์ถœ ์ˆœ์„œ์— ๋”ฐ๋ผ ์‹คํ–‰ ๊ฒฐ๊ณผ ๊ฐ’์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์œ ์˜!

 

Scheduler

- Observable Operator Chain์— ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

- ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ Scheduler๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Œ. 

- DispatchQueue์™€ ๋™์ผํ•œ ๊ธฐ๋Šฅ

 

Subject

- Observer์™€ Observable์˜ ์„ฑ๊ฒฉ์„ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ, ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๊ณ  ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์Œ.

- subject๋Š” Next ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๊ณ  ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค subscriber์—๊ฒŒ ๋ฐฉ์ถœํ•จ.

- ํ•˜๋‚˜ ์ด์ƒ์˜ Observable์„ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ์Œ.

- subscriber๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด subject์— ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด๋„ ์‹คํ–‰๋˜์ง€ ์•Š์Œ.

  • AsyncSubject : Completed ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ์‹œ์ ์— ๋งˆ์ง€๋ง‰์œผ๋กœ ์ „๋‹ฌ๋œ Next ์ด๋ฒคํŠธ๋ฅผ subscriber๋กœ ๋ฐฉ์ถœ
  • PublishSubject : ๋นˆ ์ƒํƒœ๋กœ ์‹œ์ž‘ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ’๋งŒ subscriber์—๊ฒŒ ๋ฐฉ์ถœ
  • BehaviorSubject : ํ•˜๋‚˜์˜ ์ดˆ๊ธฐ๊ฐ’์„ ๊ฐ€์ง„ ์ƒํƒœ๋กœ ์‹œ์ž‘. ์ƒˆ๋กœ์šด subscriber์—๊ฒŒ ์ดˆ๊ธฐ๊ฐ’ ๋˜๋Š” ์ตœ์‹ ๊ฐ’์„ ๋ฐฉ์ถœ
  • ReplaySubject : ๋ฒ„ํผ๋ฅผ ๋‘๊ณ  ์ดˆ๊ธฐํ™”. ๋ฒ„ํผ ์‚ฌ์ด์ฆˆ ๋งŒํผ์˜ ๊ฐ’๋“ค์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ƒˆ๋กœ์šด subsucriber์—๊ฒŒ ๋ฐฉ์ถœ

 

Relay

- UI ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉํ•จ.

- RxCocoa๋ฅผ importํ•ด์„œ ์”€.

- Error์™€ Completed๊ฐ€ ์—†๊ณ  dispose ํ•  ๋•Œ๊นŒ์ง€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Œ. 

  • PublishRelay : PublishSuject์˜ Wrapper ํด๋ž˜์Šค. ๊ตฌ๋… ์ดํ›„์˜ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•จ.
  • BehaviorRelay : BehaviorSubject์˜ Wrapper ํด๋ž˜์Šค. ํ˜„์žฌ์˜ ๊ฐ’ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•จ. ๊ฐ€์žฅ ์ตœ์‹ /์ดˆ๊ธฐ๊ฐ’๋งŒ์„ ์ƒˆ๋กœ์šด subscriber์—๊ฒŒ ๋ฐฉ์ถœํ•จ.

 


ํ”„๋กœ์ ํŠธ์— RxSwift import ํ•˜๋Š” ๋ฐฉ๋ฒ•โœจ

  • Swift Package Manager

Repository ๋งํฌ ๊ฒ€์ƒ‰



๋ฒ„์ „, ๋ธŒ๋žœ์น˜, ์ปค๋ฐ‹๋ฒ„์ „ ์„ค์ •

 

์™„๋ฃŒ

import RxSwift