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

๐ŸŽ iOS/Combine

[Combine] WWDC19 - Introducing Combine

์•ˆ๋…•ํ•˜์„ธ์š” ์ œ์ธ์ž…๋‹ˆ๋‹ค:)

์ง€๋‚œ ๊ธ€์—์„œ Combine์˜ ํ•ต์‹ฌ์ด์ž ๊ธฐ๋ณธ์ธ Publisher, Subscriber์— ๋Œ€ํ•ด ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ† ๋Œ€๋กœ ์ •๋ฆฌํ•ด๋ณด์•˜๋Š”๋ฐ์š”,

Combine์— ๋Œ€ํ•ด ๋” ๊นŠ๊ฒŒ ํ•™์Šตํ•˜๊ธฐ์— ์•ž์„œ WWDC19 - Introducing Combine ์˜์ƒ์„ ๋ณด๊ณ  ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์„ธ์…˜์—์„œ๋Š” Publisher, Subscriber, Operator ์— ๋Œ€ํ•ด ๊ฐœ๊ด„์ ์ธ ๋‚ด์šฉ์„ ๋‹ด๊ณ  ์žˆ์–ด Combine ํ”„๋ ˆ์ž„์›Œํฌ์— ๋Œ€ํ•ด ํ•œ ๋ฒˆ ํ›‘์–ด๋ณผ ์ˆ˜ ์žˆ์—ˆ๋˜ ์„ธ์…˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. 

Combine์ด๋ž€?

A unified declarative API for processing values over time.

Combine์€ ์‹œ๊ฐ„ ๊ฒฝ๊ณผ์— ๋”ฐ๋ฅธ ๊ฐ’ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํ†ตํ•ฉ๋œ ์„ ์–ธ์  API์ž…๋‹ˆ๋‹ค.

Key Concepts

  • Publishers
  • Subscribers
  • Operators

Publisher

  • Publisher๋Š” Combine API์˜ ์„ ์–ธ์  ๋ถ€๋ถ„
  • ๊ฐ’๊ณผ ์˜ค๋ฅ˜๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹์„ ์„ค๋ช…ํ•จ(์‹ค์ œ๋กœ ๋ฐ˜๋“œ์‹œ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ X)
  • ๊ฐ’ ํƒ€์ž…(=๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉ)
  • Subscriber(=์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ’์„ ๋ฐ›๋Š” ๊ฒƒ) ๋“ฑ๋ก์„ ํ—ˆ์šฉ

๋‘ ๊ฐœ์˜ associated type์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

  • Output: ์ƒ์„ฑ๋˜๋Š” ๊ฐ’์˜ ์ข…๋ฅ˜
  • Failure: ์ƒ์„ฑ๋˜๋Š” ์˜ค๋ฅ˜์˜ ์ข…๋ฅ˜
  • Publisher๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ never ํƒ€์ž… ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • Publisher์˜ ํ•ต์‹ฌ๊ธฐ๋Šฅ: Subscribe
    • Subsribe์—์„œ๋Š” Subsriber์˜ Input์ด Publisher์˜ Output๊ณผ ์ผ์น˜ํ•˜๊ณ , Subsriber์˜ Failure์ด Publisher์˜ Failure๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•จ

Example of Publisher - NotificationCenter

NotificationCenter๋ฅผ ์œ„ํ•œ Publisher

  • ๊ตฌ์กฐ์ฒด๋กœ ์ •์˜
  • Ouput ํƒ€์ž…์€ Notification
  • Failure ํƒ€์ž…์€ Never
  • center, name, object ์„ธ๊ฐ€์ง€ ํ•ญ๋ชฉ์œผ๋กœ ์ดˆ๊ธฐํ™” ๋จ

Subscriber

  • Subscriber๋Š” Publisher์— ๋Œ€์‘๋˜๋Š” ๊ฐœ๋…
  • Publisher๊ฐ€ ์œ ํ•œํ•œ ๊ฒฝ์šฐ completion์„ ํฌํ•จํ•œ ๊ฐ’์„ ๋ฐ›๋Š” ๊ฒƒ
  • ์ฐธ์กฐ ํƒ€์ž…(์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ’์„ ์ˆ˜์‹ ํ•˜๋ฉด ๋™์ž‘ํ•˜๊ณ , ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ๋•Œ๋ฌธ. class๋กœ ๊ตฌํ˜„๋จ)

  • ๋‘ ๊ฐ€์ง€ associatedtype ์กด์žฌ (Input, Failure)
  • Publisher์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Subscriber๊ฐ€ Failure๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ Never ํƒ€์ž… ์‚ฌ์šฉ๊ฐ€๋Šฅ
  • ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ธฐ๋Šฅ
    • ๊ตฌ๋…์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ(๊ตฌ๋…์€ subscriber๊ฐ€ publisher์—์„œ subscriber๋กœ์˜ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•)
    • Input์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
    • ์—ฐ๊ฒฐ๋œ publisher๊ฐ€ ์œ ํ•œํ•œ ๊ฒฝ์šฐ, ์™„๋ฃŒ(Finished) ๋˜๋Š” ์‹คํŒจ(Failure)์ผ ์ˆ˜ ์žˆ๋Š” Completion์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

Example of Subscriber

  • Assign์€ ํด๋ž˜์Šค๋กœ ์ •์˜๋จ
  • ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค, ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค, ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๊ฐ์ฒด์— ๋Œ€ํ•œ ์œ ํ˜• ์•ˆ์ „ ํ‚ค ๊ฒฝ๋กœ(type safe key path)๋กœ ์ดˆ๊ธฐํ™” ๋จ
  • ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ํ•˜๋Š” ์ผ์€ ์ž…๋ ฅ์„ ๋ฐ›์œผ๋ฉด ํ•ด๋‹น ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์— Input์„ write ํ•˜๋Š” ๊ฒƒ
  • ํ”„๋กœํผํ‹ฐ ๊ฐ’๋งŒ writeํ•  ๋•Œ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— Assign์˜ Failure ํƒ€์ž…์„ Never๋กœ ์„ค์ •ํ•จ

The Pattern (๋™์ž‘ ๋ฐฉ์‹)

Subscriber๋ฅผ ๋ณด์œ ํ•˜๋Š” ์ผ์ข…์˜ ์ปจํŠธ๋กค๋Ÿฌ ๊ฐ์ฒด๋‚˜ ๋‹ค๋ฅธ ํƒ€์ž…์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” Subsribe๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Subscriber๋ฅผ Publisher์—๊ฒŒ ์—ฐ๊ฒฐํ•˜๋Š” ์ผ์„ ๋‹ด๋‹นํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ด ์‹œ์ ์—์„œ Publisher๋Š” Subscriber๊ฐ€ Publisher์—๊ฒŒ ํŠน์ • ์ˆ˜์˜ ๊ฐ’ ๋˜๋Š” ๋ฌด์ œํ•œ์„ ์š”์ฒญํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ๊ตฌ๋…(subscription)์„ Subscriber์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด, Publisher๋Š” ํ•ด๋‹น ์ˆ˜ ์ดํ•˜์˜ ๊ฐ’์„ Subscriber์—๊ฒŒ ์ž์œ ๋กญ๊ฒŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  Publisher๊ฐ€ ์œ ํ•œํ•œ ๊ฒฝ์šฐ์—๋Š” ๋งˆ์ง€๋ง‰์— ์™„๋ฃŒ(Completion) ๋˜๋Š” ์˜ค๋ฅ˜(Error)๋ฅผ ์ „์†กํ•˜๊ฒŒ ๋จ

→ ์š”์•ฝํ•˜์ž๋ฉด, ํ•˜๋‚˜์˜ ๊ตฌ๋…, 0๊ฐœ ์ด์ƒ์˜ ๊ฐ’ ๋ฐ ๋‹จ์ผ ์™„๋ฃŒ

 

์˜ˆ์ œ๋กœ ๋ด…์‹œ๋‹ค!

 

Wizard๋ผ๋Š” ๋ชจ๋ธ ๊ฐ์ฒด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๋‘๋Š” ๊ฒƒ์€ 'Wizard๊ฐ€ ์–ด๋–ค ํ•™๋…„์— ์†ํ•ด ์žˆ๋Š”์ง€' ์ž…๋‹ˆ๋‹ค.

5ํ•™๋…„์ธ merlin๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค. ์›ํ•˜๋Š” ๊ฒƒ์€ ํ•™์ƒ๋“ค์˜ ์กธ์—…์— ๋Œ€ํ•œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ํ•™์ƒ๋“ค์ด ์กธ์—…ํ•˜๋ฉด ๋ชจ๋ธ ๊ฐ์ฒด์˜ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•ด๋ด…์‹œ๋‹ค.

 

Merlin์˜ ์กธ์—…์— ๊ด€ํ•œ default ์„ผํ„ฐ์˜ NotificationCenter Publisher๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

๋‹ค์Œ์œผ๋กœ Assign Subscriber๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Merlin์˜ ํ•™๋…„ ํ”„๋กœํผํ‹ฐ์— ์ƒˆ๋กœ์šด ํ•™๋…„์„ ์“ฐ๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ, subscribe๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ publisher์— subscriber๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํƒ€์ž…์ด ์ผ์น˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด์ฃ !

 

NotificationCenter๋Š” ์•Œ๋ฆผ์„ ๋ณด๋‚ด์ง€๋งŒ Interger ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ์— ์“ฐ๋„๋ก ๊ตฌ์„ฑ๋œ Assign์—๋Š” Intํƒ€์ž…์˜ ์ •์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

→ notification๊ณผ integer ์‚ฌ์ด์—์„œ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•˜๋‹ค! ์ฆ‰, ์—ฐ์‚ฐ์ž(operator)๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ!!

Operator

  • Publisher ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒ → ์ผ์ข…์˜ Publisher์ธ ๊ฒƒ
  • ๊ฐ’ ํƒ€์ž…(์„ ์–ธ์ ์ด๊ธฐ ๋•Œ๋ฌธ)
  • ๊ฐ’ ๋ณ€๊ฒฝ, ๊ฐ’ ์ถ”๊ฐ€, ๊ฐ’ ์ œ๊ฑฐ ๋˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋™์ž‘์„ ์„ค๋ช…ํ•˜๋Š” ์—ญํ• ์„ ํ•จ
  • ๋˜ํ•œ, Publisher(upstream)๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ Subscriber(downstream)์—๊ฒŒ ๋ณด๋ƒ„

Example of Operator - Map

  • Map์€ upstream์— ์—ฐ๊ฒฐํ•˜๊ณ , upstream์˜ ์ถœ๋ ฅ์„ ์ž์ฒด์ ์ธ ์ถœ๋ ฅ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ตฌ์กฐ์ฒด
  • ์ž์ฒด์ ์œผ๋กœ Failure๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— upstream์˜ Failure ์œ ํ˜•์„ ๋‹จ์ˆœํžˆ ๋ฏธ๋Ÿฌ๋งํ•˜๊ณ  ํ†ต๊ณผ์‹œํ‚ด

๋”ฐ๋ผ์„œ Map์„ ์‚ฌ์šฉํ•˜๋ฉด ์•Œ๋ฆผ๊ณผ ์ •์ˆ˜ ์‚ฌ์ด๋ฅผ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๊ฐ€ ์กด์žฌํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ!

 

map ํด๋กœ์ €๋กœ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  Int ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜์„ ํ•ด์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณ€ํ™˜ ์„ฑ๊ณต == subsriber์— ์—ฐ๊ฒฐ ์„ฑ๊ณต

 

์œ„์™€ ๊ฐ™์ด Generic๊ณผ ํ”„๋กœํ† ์ฝœ extension์„ ํ™œ์šฉํ•ด ๋ชจ๋“  Publisher๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Publisher์˜ extension์œผ๋กœ ์ •์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— self๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ๊ฐ€ ์ข€ ๋” ๊ฐ„๋‹จํ•ด์ง‘๋‹ˆ๋‹ค.

 

์•Œ๋ฆผ(=notification)์„ ๋ฐ›์œผ๋ฉด map ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ๋งคํ•‘ํ•œ ๋‹ค์Œ Merlin์˜ grade ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ๊ตฌ๋ฌธ์€ ๋‹จ๊ณ„๋ณ„๋กœ ์ผ์–ด๋‚˜๋Š” ์ผ์— ๋Œ€ํ•ด ๋งค์šฐ ์„ ํ˜•์ ์ด๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํ๋ฆ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

Assign์€ Cancelable์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ทจ์†Œ ๊ธฐ๋Šฅ(cancelation)๋„ combine์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ทจ์†Œ(cancelation)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์š”ํ•œ ๊ฒฝ์šฐ publisher์™€ subscriber ์‹œํ€€์Šค๋ฅผ ์กฐ๊ธฐ์— ์ค‘๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์œ„์—์„œ ์‚ดํŽด๋ณธ ๋‹จ๊ณ„๋ณ„ ๊ตฌ๋ฌธ(step-by-step syntax)์€ Combine ์‚ฌ์šฉ๋ฐฉ๋ฒ•์˜ ํ•ต์‹ฌ์ด๋‹ค.

๊ฐ ๋‹จ๊ณ„๋Š” ์ฒด์ธ์˜ ๋‹ค์Œ ๋ช…๋ น ์„ธํŠธ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ publisher ์—์„œ ์ผ๋ จ์˜ ์—ฐ์‚ฐ์ž๋“ค์„ ๊ฑฐ์ณ subscriber๋กœ ๋๋‚˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ’์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‹ค์–‘ํ•œ ์—ฐ์‚ฐ์ž๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ๋“ค์€ ์„ ์–ธ์  ์—ฐ์‚ฐ์ž API(Declarative Operator API)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

 

  • ๊ธฐ๋Šฅ์  ๋ณ€ํ™˜ - ex. map
  • ๋ฆฌ์ŠคํŠธ ์—ฐ์‚ฐ - ex. filter, reduce ..
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ - ์˜ค๋ฅ˜๋ฅผ ๋””ํดํŠธ ๊ฐ’์ด๋‚˜ ๋Œ€์ฒด ๊ฐ’์œผ๋กœ ๋ฐ”๊ฟˆ
  • ์Šค๋ ˆ๋“œ ๋˜๋Š” ํ ์ด๋™ - ex. ๋ฌด๊ฑฐ์šด ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ์ด๋™ํ•˜๊ฑฐ๋‚˜ UI ์ž‘์—…์„ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ์ด๋™
  • ์Šค์ผ€์ค„๋ง ๋ฐ ์‹œ๊ฐ„ - ๋ฃจํ”„, ๋””์ŠคํŒจ์น˜ ํ, ํƒ€์ด๋จธ ์ง€์›, ํƒ€์ž„์•„์›ƒ ๋“ฑ๊ณผ์˜ ํ†ตํ•ฉ์„ ํฌํ•จ

์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์ž์˜ ์ข…๋ฅ˜๊ฐ€ ๋งค์šฐ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ฒƒ์ด ๋‹ค์†Œ ๋ถ€๋‹ด์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿด ๋•Œ, ํŒ๋‹จ ๊ธฐ์ค€์„ Combine์˜ ํ•ต์‹ฌ ๋””์ž์ธ ์›์น™, ์ฆ‰ Composition์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์„ ๊ถŒํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์• ํ”Œ์—์„œ๋Š” ๋งŽ์€ ์ผ์„ ํ•˜๋Š” ๋ช‡๋ช‡ ์—ฐ์‚ฐ์ž๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋Œ€์‹ , ๊ฐ๊ฐ ์กฐ๊ธˆ์”ฉ๋งŒ ์ˆ˜ํ–‰ํ•˜๋Š” ๋งŽ์€ ์—ฐ์‚ฐ์ž๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์—ˆ์œผ๋ฉฐ,

๊ฐœ๋ฐœ์ž๋“ค์ด ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก Swift Collection API์—์„œ ์ด๋ฆ„์„ ๋งŽ์ด ๋”ฐ์™”๋‹ค๊ณ  ํ•˜๋„ค์š”!

 

์™ผ์ชฝ์—๋Š” Synchronous(๋™๊ธฐ) API๊ฐ€ ์žˆ๊ณ  ์˜ค๋ฅธ์ชฝ์—๋Š” Asynchronous(๋น„๋™๊ธฐ) API๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์œ„์ชฝ์—๋Š” ๋‹จ์ผ ๊ฐ’, ์•„๋ž˜์ชฝ์—๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Swift์—์„œ ํ•˜๋‚˜์˜ ์ •์ˆ˜๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ๊ฒฝ์šฐ์—” Int๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜์ง€๋งŒ Combine์„ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Future๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ๋™๊ธฐ๋กœ ์‚ฌ์šฉํ•  ๋•Œ๋Š” Array, ๋น„๋™๊ธฐ๋กœ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ผ๋ฉด Publisher๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ์‹œ๋กœ ๋ด…์‹œ๋‹ค.

Example of Operator - CompactMap, filter

์œ„์˜ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” key๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ •์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’ 0์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์ด ์ž˜๋ชป๋œ ๊ฐ’์ด ์ง„ํ–‰๋˜์–ด ๋ชจ๋ธ ๊ฐ์ฒด์— ๊ธฐ๋ก๋˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์•„์ด๋””์–ด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด ํด๋กœ์ €๊ฐ€ nil์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ—ˆ์šฉํ•œ ๋‹ค์Œ, nil ๊ฐ’์„ ํ•„ํ„ฐ๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Swift 4.1์—์„œ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํ•ด๋‹น ์ž‘์—…์— ๋Œ€ํ•œ ์ด๋ฆ„์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ CompactMap์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Publisher์—๋„ CompactMap์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ CompactMap๊ณผ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

ํด๋กœ์ €์—์„œ nil์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด CompactMap์€ ์ด๋ฅผ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์ŠคํŠธ๋ฆผ ์•„๋ž˜๋กœ ๋” ์ด์ƒ ์ง„ํ–‰๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๋ช‡๊ฐ€์ง€ ์นœ์ˆ™ํ•œ ์ด๋ฆ„๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ๊ณ„๋ณ„ ์ง€์นจ์„ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

ํ•™๊ต์—๋Š” 5ํ•™๋…„ ์ด์ƒ์˜ ํ•™์ƒ๋“ค๋งŒ ์ž…ํ•™์ด ํ—ˆ์šฉ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

filter๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

filter๋Š” ์˜ค์ง ํ•ด๋‹น ์กฐ๊ฑด์„ ํ†ต๊ณผํ•˜๋Š” ์š”์†Œ๋งŒ ๊ณ„์† ์ง„ํ–‰ํ•˜๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” Array์˜ filter์™€ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ๋‹ค๊ฐ€ ์กธ์—…์€ ์ตœ๋Œ€ 3๋ฒˆ๊นŒ์ง€๋งŒ ํ—ˆ์šฉ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐฐ์—ด์—์„œ ์ฒ˜์Œ ์„ธ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•˜๋Š” ๊ฒฝ์šฐ prefix(3)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

publisher์—์„œ๋„ ์ฒ˜์Œ ์„ธ ์š”์†Œ๋งŒ ๋ฐ›์œผ๋ ค๋ฉด prefix(3)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ํ•˜๋Š” ์ผ์€ ์„ธ ๊ฐœ์˜ ๊ฐ’์„ ๋ฐ›์€ ํ›„ ์—…์ŠคํŠธ๋ฆผ์„ ์ทจ์†Œํ•˜๊ณ  ๋‹ค์šด์ŠคํŠธ๋ฆผ์œผ๋กœ ์™„๋ฃŒ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

map, filter๋Š” ํ›Œ๋ฅญํ•œ API์ด์ง€๋งŒ ์ฃผ๋กœ ๋™๊ธฐ ๋™์ž‘์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Combine์€ ๋น„๋™๊ธฐ ์„ธ๊ณ„์—์„œ ์ž‘์—…ํ•  ๋•Œ ๋น›์„ ๋ฐœํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์ •๋ง ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ์—ฐ์‚ฐ์ž์— ๋Œ€ํ•ด ์‚ดํŽด๋ด…์‹œ๋‹ค.

Example of Operator - zip, combineLatest

1. Zip

  • ์—ฌ๋Ÿฌ ์—…์ŠคํŠธ๋ฆผ ์ž…๋ ฅ์„ ๋‹จ์ผ ํŠœํ”Œ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋‹ค์šด์ŠคํŠธ๋ฆผ์œผ๋กœ ์ „๋‹ฌ
  • when/and ์ž‘์—…์œผ๋กœ ๋งŒ๋“ฆ - downstream์œผ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” tuple์˜ ๋ชจ๋“  ๊ฐ’์ด ์ž…๋ ฅ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ upstream์˜ ๋ชจ๋“  input์ด ์ „๋‹ฌ๋œ ํ›„์— downstream์œผ๋กœ tuple์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ
  • ์ฆ‰, ๊ณ„์† ์ง„ํ–‰๋˜๋ ค๋ฉด ๋ชจ๋“  upstream input๊ฐ’์ด ์ „๋‹ฌ๋˜์–ด์•ผ๋งŒ

์˜ˆ์‹œ๋กœ zip ์˜ ๋™์ž‘์„ ์ดํ•ดํ•ด๋ณด์ž๋ฉด,

3๊ฐœ์˜ ์—…์ŠคํŠธ๋ฆผ์ด ํ•„์š”ํ•œ zip์„ ์‚ฌ์šฉํ•˜์—ฌ 3๊ฐœ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์–ด์•ผ ๋‹ค์šด์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ bool ํƒ€์ž…์˜ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” 3๊ฐœ์˜ ๋น„๋™๊ธฐ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ , ๋ชจ๋‘ ์™„๋ฃŒ๋˜๋ฉด ๊ฐ’์„ ๋ฒ„ํŠผ์˜ isEnabled ์†์„ฑ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ๋งคํ•‘ํ•จ์œผ๋กœ์จ ์„ธ ๊ฐ€์ง€ ์กฐ๊ฑด์ด ๋ชจ๋‘ ๋งŒ์กฑ๋  ๋•Œ๋งŒ Continue ๋ฒ„ํŠผ์„ ํ™œ์„ฑํ™” ์‹œํ‚ค๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. CombineLatest

  • zip๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์—ฌ๋Ÿฌ ์—…์ŠคํŠธ๋ฆผ ์ž…๋ ฅ์„ ๋‹จ์ผ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜
  • ๊ทธ๋Ÿฌ๋‚˜ zip๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์ง„ํ–‰ํ•˜๋ ค๋ฉด ์—…์ŠคํŠธ๋ฆผ ์ค‘ ์–ด๋Š ํ•˜๋‚˜์˜ ์ž…๋ ฅ์ด ํ•„์š”ํ•˜๋ฏ€๋กœ when/or ์ž‘์—…
    • ์—…์ŠคํŠธ๋ฆผ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋‹ค์šด์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ฐ’์„ ์ „๋‹ฌ
  • ๊ฐ ์—…์ŠคํŠธ๋ฆผ์—์„œ ๋ฐ›์€ ๋งˆ์ง€๋ง‰ ๊ฐ’์„ ์ €์žฅ
  • ๊ฐ’์„ ๋‹จ์ผ ๋‹ค์šด์ŠคํŠธ๋ฆผ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋กœ์ €๋กœ ๊ตฌ์„ฑ๋จ

3๊ฐœ์˜ ์—…์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋Š” CombineLatest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ† ๊ธ€ ์Šค์œ„์น˜์˜ ์ƒํƒœ๊ฐ’์— ๋”ฐ๋ผ play ๋ฒ„ํŠผ์˜ ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๊ฐœ์˜ ์Šค์œ„์น˜ ๋ชจ๋‘ bool ์ƒํƒœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋จ์— ๋”ฐ๋ผ ์ด๋ฅผ ๋‹ค์‹œ ๋‹จ์ผ bool๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์ด๋ฅผ play ๋ฒ„ํŠผ์˜ isEnabled ์†์„ฑ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์–ด๋Š ํ•˜๋‚˜์˜ ๊ฐ’์ด๋ผ๋„ false ์ด๋ฉด ๊ฒฐ๊ณผ๋Š” false์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋˜์ง€ ์•Š๊ณ , ๋ชจ๋‘ true ์ด๋ฉด ๊ฒฐ๊ณผ๋Š” true ์ด๋ฏ€๋กœ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

Combine์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ๋ณ€ํ™˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์ ์ง„์ ์œผ๋กœ Combine์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค๊ณ  ํ•˜๋„ค์š”! ์˜ˆ์ œ๋กœ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ์ƒํ™ฉ์—์„œ ์ ํ•ฉํ•œ operator๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋น„๋™๊ธฐ ์ž‘์—… ์ค‘ ๊ฐ€์žฅ ๋งŽ์ด ํ•˜๋Š” ์ž‘์—…์ด ๋„คํŠธ์›Œํ‚น์ธ๋ฐ, URLSession์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•œ ๋’ค JSON Decoder๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” decode ์—ฐ์‚ฐ์ž๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

 

ํ•ด๋‹น ์˜์ƒ์—์„œ๋Š” Combine์˜ ์•„์ฃผ ๊ธฐ๋ณธ์ ์ธ ๋‚ด์šฉ๋“ค๋งŒ ๋‹ค๋ฃจ๋Š”๋ฐ, Combine์—๋Š” ๋” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค!

๋” ์ž์„ธํ•œ ๋‚ด์šฉ๊ณผ ์˜ˆ์ œ ์ฝ”๋“œ๋“ค์€ ๋‹ค๋ฅธ ๊ฒŒ์‹œ๊ธ€๋กœ ๋” ์ •๋ฆฌํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!!๐Ÿ˜Š๐Ÿ˜Š