SHcommit / LearnMoreSwiftInUdemy

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Clone/Instagram] ๐Ÿšฉ LoginController MVVM ๋ฆฌํŽ™ํ„ฐ๋ง(์—๋Ÿฌ์ฒ˜๋ฆฌ, clean code) with combine | LoginController Code Review ๐Ÿ–‹๏ธ | ๋งˆ์ฃผํ•œ ์—๋Ÿฌ & ๊ฐœ์„ ํ•ด์•ผ ํ•  ๊ธฐ๋Šฅ & ๋Š๋‚€์  & #13

SHcommit opened this issue ยท comments

TODO: ์ด๋ฒˆ์—” Never์ธ ๊ฒฝ์šฐ๋Š” ์—†๋‹ค๋Š” ์ƒ๊ฐ์œผ๋กœ LoginController ๋ฆฌํŽ™ํ„ฐ๋ง.

๊ตฌํ˜„ ์˜์ƒ


๊ฐ„๋‹จํ•œ LoginController ์ฝ”๋“œ ๋ฆฌ๋ทฐ ( ์‹œํ—˜ ๋๋‚˜๋„ ๊นŒ๋จน์ง€ ์•Š๊ธฐ ์œ„ํ•ด.. )

๐Ÿ‘‹ TODO: ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํ•˜๋Š” ๊ณผ์ •์„ ์ปด๋ฐ”์ธ์œผ๋กœ ๊ตฌํ˜„ with mvvm pattern + DI(Dependency Injection). ์ด๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์˜ค๋ฅ˜ throws -> ์ฒ˜๋ฆฌ.

  • LoginController

  • LoginViewModelProtocols

  • LoginViewModel

์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ, ํ™”๋ฉด๊ณผ ๊ด€๋ จ์žˆ๋Š”(ํšŒ์›๊ฐ€์ž… ๋นผ๊ณ !!) ์†Œ์Šค์ฝ”๋“œ๋Š” ์œ„์— ์žˆ๋Š” ๋‹จ 3๊ฐœ๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค.

1. LoginController์— ๊ด€ํ•ด (LoginController Link)

  • input/output pattern. DI

แ„…แ…ตแ„‡แ…ฒ1

๊ตฌํ˜„์˜์ƒ ์ดˆ๊ธฐ ํ™”๋ฉด์—์„œ ๋ณด๋“ฏ LoginController์˜ view๋Š” 2๊ฐœ์˜ textfield(id, pw ์ž…๋ ฅ) login button์œผ๋กœ ๊ตฌ์„ฑ๋˜๋œ๋‹ค. RxSwift์—์„œ MVVM ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ๋•Œ input/ output pattern์„ ์ด์šฉํ•œ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด Dependency Injection(DI) ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜๋‹ค. LoginController๊ฐ€ ์ดˆ๊ธฐํ™” ๋  ๋•Œ ๋ฐ˜๋“œ์‹œ LoginViewModelType๋กœ ์ดˆ๊ธฐํ™” ํ•จ์œผ๋กœ DIํ–ˆ๋‹ค.

  • input/output implement with error handling

แ„…แ…ตแ„‡แ…ฒ2

LoginController๋Š” viewModel์„ ์‚ฌ์šฉํ•  ๋•Œ ๋งŽ์€ ํ•จ์ˆ˜๊ฐ€ ํ•„์š” ์—†๋‹ค. ๊ทธ์ € input, ouput์„ ๋ฐ”์ธ๋”ฉ ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ LoginController์—์„œ๋Š” viewModel ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด transform ๋‹จ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋งŒ ์‹คํ–‰ํ•˜๋„๋ก ํ–ˆ๋‹ค. ์™œ? input/output pattern์„ ํ†ตํ•ด์„œ LoginController์—์„œ ๋ฐœ์ƒ๋˜๋Š” ๋ชจ๋“  view์˜ Event flow handling์„ viewModel์—์„œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • render(in:)

แ„…แ…ตแ„‡แ…ฒ3

ํ•œ๊ฐ€์ง€ ๋”! LoginController์—์„œ ์ฃผ์‹œํ•  ํ•จ์ˆ˜๋Š” renderํ•จ์ˆ˜์ด๋‹ค. LoginController์—์„œ ๋ฐœ์ƒํ•œ ๊ฐ๊ฐ์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ viewModel์˜ transform(input:) ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํŠน์ • publisher์˜ chains ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ํ๋ฆ„ ์ฒ˜๋ฆฌ ์ดํ›„์— ๊ฐ’์„ output๋กœ ๋ฐ›๋Š”๋‹ค.

แ„…แ…ตแ„‡แ…ฒ4

์ด๋•Œ์˜ output ์ข…๋ฅ˜๋Š” LoginControllerState์— ๋”ฐ๋ฅธ 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ์ฃผ ์—ญํ• ์€ view์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์œ„ํ•œ output์„ enum์œผ๋กœ ์ •์˜ํ•œ ๊ฒƒ ๋ฟ์ด๋‹ค. ๊ทธ์ € state์— ๋”ฐ๋ผ view์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

2. LoginViewModelProtocols์— ๊ด€ํ•ด (LoginViewModelProtocols Link)

LoginViewModel์„ ์„ค๋ช…ํ•˜๊ธฐ ์ „์— ์œ„์˜ protocols๋ฅผ ๋ณด๋ฉด์„œ ์ž‘์—…ํ•˜๋ฉด ํŽธํ•˜๋‹ค. ๋งจ ์ฒ˜์Œ์— delegate๊ฐ€ ์žˆ๋Š”๋ฐ ์ถ”ํ›„ ์—†์•จ ๊ณ„ํš์ด๋‹ค. (๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋•Œ๋งค ๊ผฌ์ด๋Š” ๋Š๋‚Œ์ด..)

  • viewModel's all error type

แ„…แ…ตแ„‡แ…ฒ5

LoginController์˜ upstream input๋กœ ์˜ค๋Š” ๊ฐ๊ฐ์˜ publisher์— ๋Œ€ํ•ด stream operator chains๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์˜ค๋ฅ˜๋ฅผ ์ •์˜ํ–ˆ๋‹ค. ๋งจ ์œ„ ์ œ๋ชฉ์—์„œ ๋ณด๋“ฏ Neverํƒ€์ž…์ด๋ž€ ์—†๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์—๋Ÿฌ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ์‹ถ์—ˆ๊ธฐ์— ์ •์˜ ํ–ˆ๋‹ค. ์›๋ž˜๋Š” ์ฝ˜์†”์ฐฝ์— ๋‹จ์ˆœํ•œ ์ถœ๋ ฅ์ด ์•„๋‹Œ ํŠน์ • case์— ๋”ฐ๋ฅธ ์•Œ๋ฆผ or ๋‹ค๋ฅธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ด ๋‹ค์‹œ ํŠน์ • ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. ๋ฐฉํ•™๋•Œ.. ํ•  ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ LoginController์˜ input, output publisher์˜ failureํƒ€์ž…์€ ์ „๋ถ€ LoginViewModelErrorType๊ฐ€ ๋œ๋‹ค. ( ์ œ๋„ค๋ฆญ๊ฐ’๋“ค์„ typealias๋กœ ๋ฐ”๊พธ๋ฉด ์–ผ๋งˆ๋‚˜ ์ข‹์„๊นŒ ์ฐพ์•„๋ดค๋Š”๋ฐ ์—†์—ˆ๋‹ค ใ…‹ใ…‹,,)

// ์—ฌ๋‹ด

ํ•œ๊ฐ€์ง€ ๋Š๋‚€์ ์€ c์–ธ์–ด๋กœ ํ…ŒํŠธ๋ฆฌ์Šค ๋งŒ๋“ค์—ˆ์„ ๋•Œ ๊ฐ๊ฐ์˜ enum์€ ์ˆซ์ž์˜ ๊ฐ’๋งŒ ๊ฐ–์„ ์ˆ˜? ์žˆ์—ˆ๋Š”๋ฐ swift๋Š” ํŠน์ • case์ž์ฒด๋ฅผ string์œผ๋กœ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ๊ฐ๊ฐ์˜ case์— ๋Œ€ํ•ด ํŠน์ • ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š”๊ฒŒ ์ง„์งœ ๋งค๋ ฅ์ธ๋“ฏ ํ•˜๋‹ค.

  • LoginViewModelInput

แ„…แ…ตแ„‡แ…ฒ6

๋‹ค์Œ์€ LoginController์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฒคํŠธ๋“ค์„ struct๋กœ ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค. ์ด ๊ฐ๊ฐ์˜ publisher๊ฐ€ publised๋  ๊ฒฝ์šฐ viewModel์—์„  ํŠน์ • input์˜ publiser์— ๋Œ€ํ•œ upstream publisher's operator chaining์„ ์ˆ˜ํ–‰ํ•œ ํ›„ output์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • LoginViewModelInputCase

แ„…แ…ตแ„‡แ…ฒ7

๋‹ค๋ฅธ ๊ฑด ์—†๋‹ค. ๊ฐ๊ฐ์˜ input's upstream publisher์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ๋ฅผ stream์˜ ํ˜•ํƒœ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹ค์งˆ์ ์ธ ํ•จ์ˆ˜๋“ค์ด๋‹ค. ์ด๋•Œ protocol๋กœ ๊ตฌํ˜„ํ•œ ์ด์œ ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋“ˆํ™” ์‹œ์ผœ transform(input:)ํ•จ์ˆ˜์˜ ๋กœ์ง์„ ์ฝ์„ ๋•Œ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ทธ๋ ‡๋‹ค. ๋ฌผ๋ก  ๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ๊ฒŒ ์•„๋‹ˆ๋‹ค.(์–ธ์  ๊ฐ„ ๋‚˜๋งŒ์˜ ๊ทœ์น™์„ ๊ผญ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค... ๋Œ€์ค‘์ ์œผ๋กœ ์ธ์ •๋ฐ›์œผ๋ฉด ์ข‹๊ณ ,,) (๋งํฌ) ์š”๊ธฐ์—์„œ ๋ณด์ด๋Š” ์ฑ…์˜ ์ €์ž๊ฐ€ ๋งŽ์€ ์„ธ์›”์„ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ํ•˜๋ฉด์„œ ์Œ“์€ ๋…ธํ•˜์šฐ๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ ํด๋ฆฐ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๋‚œ ์ด ์ €์ž์˜ ๊ทœ์น™์ด ์ •๋ง ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์•„ ํด๋ฆฐ์ฝ”๋“œ์˜ ๊ทœ์น™์„ ๋”ฐ๋ผ ๊ตฌํ˜„์„ ํ–ˆ๋‹ค!!!

  • LoginControllerState

แ„…แ…ตแ„‡แ…ฒ8

input -> transform(input:) -> LoginViewModelInput -> LoginViewModelInputCase ๋ฅผ ๊ฑฐ์นœ ํ›„์— ๊ฐ๊ฐ์˜ input์— ๋Œ€ํ•ด์„œ Merge๋ฅผ ํ†ตํ•ด ์ตœ์†Œํ•œ์˜ subscriber๋œ ๊ฐ๊ฐ์˜ publiser ๊ฐ€ ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํฌ๊ฒŒ ๋ทฐ์˜ ์ƒํƒœ ๋ณ€ํ™”๋Š” 3๊ฐ€์ง€์ด๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ id, pw๋ฅผ ์ž…๋ ฅํ–ˆ๋Š”์ง€ -> ๋‘˜๋‹ค ์ž…๋ ฅํ–ˆ์„ ๊ฒฝ์šฐ loginButton enabled๋จ else disabled. none, ์‹คํ–‰์ค‘์ธ ์ธ๋””์ผ€์ดํ„ฐ ํ•ด์ œ. ์ด ์„ธ๊ฐ€์ง€๋‹ค!!

  • LoginViewModelNetworkServiceType

|แ„…แ…ตแ„‡แ…ฒ9

๊ทธ ๋ฐ–์— ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํ†ตํ•ด ๋กœ๊ทธ์ธ ํ•  ๋•Œ ํŒŒ์ด์–ด๋ฒ ์ด์Šค์— ๋“ฑ๋ก๋œ ๊ณ„์ •์ด ๋งž๋Š”์ง€ ์—ฌ๋ถ€ ํ•จ์ˆ˜๋‹ค. wwdc 2021์—์„œ ์†Œ๊ฐœ๋œ async, await ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋„์ž…ํ–ˆ๋‹ค. ํ—คํ—ค. ๋‚˜์ค‘์— ์ปด๋ฐ”์ธ๊ณผ ๊ฒฐํ•ฉ ํ•  ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๋‹ค.

// ์—ฌ๋‹ด2 ์ด๋ฒˆ ๋ฐฉํ•™๋•Œ Swinject ์•„๋‹ˆ๋ฉด needle๋ฅผ ๊ณต๋ถ€ํ•  ๊ฒƒ์ด๋‹ค. DI๋Š” ์ง€๋‚œ 3์ฃผ๊ฐ„ ์ปด๋ฐ”์ธ ๊ณต๋ถ€ ๋•Œ ๋จธ๋ฆฟ์†์œผ๋กœ๋งŒ ๊ณ„์† ๋– ์˜ฌ๋ฆฌ๋‹ค๊ฐ€ ํ•™๊ต ๊ณผ์ œ ISS (๋งํฌ)์•ฝ 2์ฃผ๊ฐ„ Instruction Set Simulator๋ฅผ ๊ตฌํ˜„ ํ•  ๋•Œ ์˜์กด์„ฑ์ด ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋„์ž… ํ•˜๊ณ ์ž ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ–ˆ๋‹ค. iss ํ”„๋กœ์ ํŠธ ๋๋‚œ ํ›„ ๊ฐœ๋…์œผ๋กœ๋งŒ ์ˆ™์ง€ํ•˜๊ณ  ์žˆ๋˜ Combine์„ ์ ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ protocol ๊ด€๋ จ์€ ๋‚˜์˜์ง€ ์•Š๊ฒŒ ์Šค์œ„ํ”„ํŠธ์— ๋ฐ”๋กœ ๋„์ž…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
๊ทผ๋ฐ C++์— interface๊ฐ€ ์ง€์›์ด ์•ˆ ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์ง„์งœ ๋ชฐ๋ž๋‹ค. ๊ทธ๋ž˜์„œ define์œผ๋กœ ์ •ํ•˜๊ธด ํ–ˆ๋‹ค.. ๊ทผ๋ฐ ์ˆœ์ˆ˜ ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ์„ ์–ธ ํ•ด๋„ ๊ฒฐ๊ตญ์—” ์ƒ์†๋ฐ›๋Š” ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•  ๋•Œ .h ํŒŒ์ผ์— ์žฌ ์„ ์–ธ ํ›„ .cpp ํŒŒ์ผ์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š”๊ฒŒ ๋„ˆ๋ฌด ์•„์‰ฌ์› ๋‹ค. swift ์˜€๋‹ค๋ฉด ์ค‘์ฒฉ ์„ ์–ธ์ด ์—†๋Š” ๊น”๋”ํ•œ ์ฝ”๋“œ์˜€์„ ํ…๋ฐ.. ์•„๋ฌดํŠผ ISS๋ฅผ ๊ตฌํ˜„ํ•œ ๋•์— DI๊ด€๋ จ ๊ฐœ๋…์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋‚˜์˜์ง€ ์•Š์•˜๋‹ค๋Š” ๋ง!!

3. LoginViewModel (LoginViewModel Link)

์ด๊ฑฐ๋Š” ์ง์ ‘ ์ฝ”๋“œ๋กœ ๋ณด๋Š”๊ฒŒ ์ข‹๊ฒ ๋‹ค.

์›๋ž˜ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ์ •๋ง ์ข‹์•„ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฃผ์„ ์œผ๋กœ ๋ถ€์—ฐ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ๊ต‰์žฅํžˆ ์ข‹์•„ํ•œ๋‹ค.. ํ•™๊ต ๊ต์ˆ˜๋‹˜๋“ค์ด ์‹œ์ผœ์„œ ์Šต๊ด€์ด ๋œ ๊ฒƒ์ด ์žˆ๊ธฐ๋„ ํ–ˆ๋‹ค. ํด๋ฆฐ ์ฝ”๋“œ๋ฅผ ์ฝ์œผ๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ฝ์„ ๋•Œ ํ•œ๋ฒˆ์— ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋„ค์ด๋ฐ์ด ๊ต‰์žฅํžˆ ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์š”์ฆ˜์€ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์Šต๊ด€ ๋Œ€์‹  ๊นƒํ—™์˜ issue์— ๊ฐœ๋ฐœํ•˜๋‹ค๊ฐ€ ๋Š๋‚€ ๊ฒฝํ—˜์ด๋‚˜ ๋ฌธ์ œ, ์—๋Ÿฌ๋“ค์„ ๋ฌธ์„œํ™”?๋กœ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋‹ค. ๊ทผ๋ฐ ์ฝ”๋“œ๋ฆฌ๋ทฐ, ์ฃผ์„ ์Šต๊ด€์€ ์ •๋ง ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ฃผ์„ ์—†์ด ๋ช‡ ๋ฒˆ๋งŒ์— ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ์ฝ”๋“œ๋Š” ์ •๋ง ํ›Œ๋ฃกํ•œ ์ฝ”๋“œ์ด๊ณ  ์ฃผ์„์ด ํ•„์š” ์—†์ง€๋งŒ ์ค‘๊ฐ„์— ๋งˆ์ฃผํ•œ ์ƒํ™ฉ, ๋ฐฐ์šด์ ๋“ค์€ ์ฃผ์„์ด ์•„๋‹Œ issue์— ๊ธฐ๋กํ•˜๋Š” ์ƒˆ๋กœ ์Šต๊ด€์„ ๋“ค์ด๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœ๋Œ€ํ•œ ๋„ค์ด๋ฐ์„ ์ž์„ธํžˆ ํ•ด์„œ ์ฝ”๋“œ์˜ ํ๋ฆ„์„ ์ •ํ™•ํ•˜๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋‚ด ๋ชฉํ‘œ๋‹ค. +_+


๋งˆ์ฃผํ•œ ์—๋Ÿฌ1

Combine์˜ publisher tryMap์˜ ์‚ฌ์šฉ์‹œ failureํƒ€์ž…์— ๊ด€ํ•œ ์—๋Ÿฌ.

แ„‹แ…ฆแ„…แ…ฅ1

แ„‹แ…ฆแ„…แ…ฅ2

tryMap์„ ์‚ฌ์šฉํ•ด error๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ์„ ๊ฒฝ์šฐ publisher์˜ failureํƒ€์ž…์€ Never๊ฐ€ ๋˜๋ฉด ์•ˆ๋œ๋‹ค. Merge -> ๊ทธ๋Œ€๋กœ eraseToAnyPublisher()๋กœ ๋ณ€ํ™˜ํ•œ subscription์„ ๊ฐ–์„ ๊ฒฝ์šฐ์— ํƒ€์ž…์˜ ๋ชจํ˜ธํ•จ ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค.

๋งˆ์ฃผํ•œ ์—๋Ÿฌ2

failure ํƒ€์ž…์ด Never๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ

แ„‹แ…ฆแ„…แ…ฅ3

tryMap ์€ any error ํƒ€์ž… ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋‚ด๊ฐ€ ์›ํ•˜๋Š” publisher failure type์— ๋งž๊ฒŒ mapError๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ปค์Šคํ…€ errorํƒ€์ž…์œผ๋กœ ์—๋Ÿฌ๋ฅผ ์บ์ŠคํŒ… ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ subscriber์—๊ฒŒ failure๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค. publisher์˜ failureํƒ€์ž… Never๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” map์ด ์•„๋‹Œ tryMap๊ฐ™์€ try ๊ธฐ๋Šฅ์ด ๋‹ด๊ธด ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

LoginController์™€ MainHomeTabViewController ๊ฐ„์— ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์ด์ „์— ์ž‘์„ฑํ–ˆ๊ธฐ์— ์‚ด์ž‘ ๋ณต์žกํ–ˆ๋Š”๋ฐ publisher์˜ input output์— ๋‘๊ฐœ์˜ vc๋ฅผ ์ „๋‹ฌํ•จ์œผ๋กœ ํ•ด๊ฒฐํ–ˆ๋‹ค.

๋ณต์Šตํ•œ ๊ฐœ๋…

A, B๋‘ ๊ฐœ์˜ publisher๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •.
let myZip = A.zip(B)

  • combineLatest
    ์–˜๋Š” A๊ฐ€ publishํ•˜๊ณ  B๋˜ํ•œ publishํ•ด์•ผ๋งŒ myZip์ด published๋œ๋‹ค. ์•ฝ๊ฐ„ ์ปคํ”Œ๋Š๋‚Œ? ํ•œ ์Œ์ด publish๋˜์•ผ๋งŒ ๋น„๋กœ์†ŒmyZip์ด ์ž‘๋™ํ•œ๋‹ค. ์•ฝ๊ฐ„ ๋‚ด๊ฐ€ ๊ตฌํ˜„ํ•˜๋Š” id,pw๋‘˜๋‹ค ์ž…๋ ฅํ•ด์•ผ๋งŒ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ํ•ด์ œ๋˜๋Š” ๋กœ์ง๊ณผ ๊ฐ™์Œ. ์•„๋ž˜๊บผ๋Š” ์•ฝ๊ฐ„ password ๋‘๋ฒˆ ์ž…๋ ฅํ•ด์„œ ์ž๊ธฐ๊ฐ€ ์ž…๋ ฅํ•œ password ๋งž๋Š”์ง€ ํ™•์ธํ•  ๋•Œ์˜ operator๋ผ๊ณ  ๋ณด๋ฉด ๋  ๊ฑฐ๊ฐ™๋‹ค.

  • zip
    ์–˜๋Š” A๊ฐ€ publishํ•˜๊ณ  B๊ฐ€ publishํ•ด์•ผ๋งŒ myZip์ด publised๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  A๊ฐ€ publish๋˜๋ฉด B์˜ ์ตœ์‹  ๊ฐ’๊ณผ ํ•จ๊ป˜ publish๋œ๋‹ค. ์ฆ‰ ๋‘˜๋‹ค publishedํ•œ ๊ฒฝ์šฐ์— A๋งŒ publishํ•ด๋„ B๋Š” ์ตœ์‹  publis ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•œ๋‹ค. ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋„ ๊ฐ™๋‹ค.

์ถ”๊ฐ€, ๊ฐœ์„  ํ•ด์•ผํ•  ๊ธฐ๋Šฅ

  • ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•ด ์„œ์น˜๋ฐ”๋ฅผ ํด๋ฆญํ•  ๋•Œ tableView reloadData๊ฐ€ ์‹คํ–‰๋œ๋‹ค. ์ด๊ฒƒ์„ ์—†์• ์•ผํ•œ๋‹ค.

  • LoginController ๋น„๋ฐ€๋ฒˆํ˜ธ ์ตœ์†Œ ์ž…๋ ฅ ๊ฐœ์ˆ˜ ์ œํ•œ

  • RegistrationController

๋˜ํ•œ ํ† ์Šค์˜ ํšŒ์›๊ฐ€์ž… ์ ˆ์ฐจ์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด ๋ณผ ๊ฒƒ์ด๋‹ค.

์ƒˆ๋กœ ๋ฆฌํŽ™ํ„ฐ๋ง ํ•ด์•ผํ•  ๊ฒƒ

  • Feed VC ๊ด€๋ จ
  • Upload VC ๊ด€๋ จ

SearchController ๋ฅผ SearchViewModel๊ณผ ๋ถ„๋ฆฌํ•  ๋•Œ SearchViewModelProtocols ์š”๊ธฐ์—์„œ ์ด ๋‘ ํ•จ์ˆ˜๋ฅผ ๊ผญ UserViewModel๋กœ ๋ถ„๋ฆฌํ•ด์•ผํ•œ๋‹ค. SearchViewModel์— ์˜์กด์ ์ด๋‹ค.

แ„€แ…ขแ„‰แ…ฅแ†ซแ„’แ…ขแ„‹แ…ฃแ„’แ…กแ‡‚

์‹œํ—˜์ด 6์ผ ๋‚จ์•˜๋‹ค.. ์ •๋ง ํฐ์ผ๋‚ฌ๋‹ค.

๋Š๋‚€์ 

์‚ฌ์‹ค ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ๋‹จ์ˆœํžˆ ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅํ–ˆ๋‹ค. ๋ฐฉํ•™์ด ๋‚ด๊ฒŒ ์˜จ๋‹ค๋ฉด ํŠน์ • ์ƒํ™ฉ์— ๋งž๋Š” ์•Œ๋ฆผ์ด๋‚˜ ์˜ค๋ฅ˜๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๋‹ค.

(์‹œํ—˜๋งŒ ๋๋‚œ๋‹ค๋ฉด ์ปด๋ฐ”์ธ ์ฑ…์œผ๋กœ ์ถ”๊ฐ€ ๊ณต๋ถ€ํ•  ํ…๋ฐ)

MVVM ๋ฆฌํŽ™ํ„ฐ๋ง ์ถ”๊ฐ€

ProfileHeaderView.
fetch Network ( async, await + combine)
MainHomeTabControler


์ถ”ํ›„ cache ๊ณต๋ถ€ํ•ด์„œ ์ด๋ฏธ์ง€ fetch ๊ฐœ์„ ํ•ด์•ผํ•จ.

ProfileHeader, ProfileHeaderViewModel ๋ฆฌํŽ™ํ„ฐ๋ง ์™„๋ฃŒ.

๊ฐœ์„ ํ•ด์•ผ ํ•  ๊ธฐ๋Šฅ์€ Network fetch ๊ด€๋ จ ๋ถ€๋ถ„์ ์œผ๋กœ ๋ฆฌํŽ™ํ„ฐ๋ง ํ–ˆ๋˜ async/await ์ „์ฒด์ ์œผ๋กœ ์ ์šฉ์‹œํ‚ค์ž (์‚ฌ์šฉ์ž ํŒ”๋กœ์šฐ, ํŒ”๋กœ์ž‰ ๊ด€๋ จ๋งŒ ํ•˜๋ฉด ๋จ. + actor์ ์šฉ.