Book_Kitty - Coordinator(01)

โœ‹ Introduce

๊ธฐ์กด MVVM ํŒจํ„ด์—์„œ๋Š” ViewController๊ฐ€ ํ™”๋ฉด ์ „ํ™˜(Navigatoin) ๋กœ์ง์„ ๋‹ด๋‹นํ•˜๊ฒŒ ๋˜๋ฉด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(SRP) ์œ„๋ฐ˜ โž” ํ™”๋ฉด ์ „ํ™˜ ๋กœ์ง์ด ViewController์— ํฌํ•จ๋˜๋ฉฐ, UI์ฒ˜๋ฆฌ์™€ ํ™”๋ฉด ์ „ํ™˜์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ฒŒ ๋จ.
  2. ๋†’์€ ๊ฒฐํ•ฉ๋„ โž” ViewController๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ํ™”๋ฉด ์ „ํ™˜์„ ์ฒ˜๋ฆฌํ•˜๋ฉด, ์˜์กด์„ฑ์ด ๊ฐ•ํ•ด์ ธ ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ต๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋‚ฎ์•„์ง.


์•„๋ž˜ ์ฝ”๋“œ๋Š” ViewController์—์„œ ๋ณดํŽธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ™”๋ฉด ์ „ํ™˜ ๋กœ์ง์ž…๋‹ˆ๋‹ค.

class HomeViewController: UIViewController {
  // ...

  func navigateToDetail() {
    let detailVC = DetailViewController()
    navigationController?.pushViewController(detailVC, animated: true)
  }
}

ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด HomeViewController๊ฐ€ DetailViewController๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๊ณ  ๋„ค๋น„๊ฒŒ์ด์…˜ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ HomeViewController์™€ DetailViewController ๊ฐ„ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ DeatilViewController๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด HomeViewController์˜ ์ฝ”๋“œ๋„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์ด ๋–จ์–ด์ง€๊ณ , ๋‹ค๋ฅธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, navigateToDetail() ๋ฉ”์„œ๋“œ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿค” Why?

๋‹จ์ˆœํ•œ ํ™”๋ฉด ์ „ํ™˜ ๋กœ์ง์„ ์œ„ํ•ด Coordinator๋ฅผ ์ถ”๊ฐ€๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋‹ด, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ํŒ€์›๋“ค์˜ ๋Ÿฌ๋‹ ์ปค๋ธŒ ๋“ฑ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, MVVM๋งŒ์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์„ ๋•Œ ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ViewController์˜ ์—ญํ• ์ด ๋น„๋Œ€ํ•ด์ง€๊ณ , ํ™”๋ฉด ์ด๋™ ํ๋ฆ„์„ ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์—ฌ๋ ค์›Œ์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•˜์Šต๋‹ˆ๋‹ค.

๋‹น์žฅ์˜ ์ž‘์€ ๋ถˆํŽธํ•จ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ํฌ๊ธฐํ•  ์ˆ˜ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ™”๋ฉด ์ „ํ™˜์„ ๋ณด๋‹ค ์ผ๊ด€๋˜๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋ฉฐ, ViewController๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋ฉด์„œ๋„ ์œ ์—ฐํ•œ ์„ค๊ณ„๋ฅผ ์ง€์›ํ•˜๋Š” Coordinator ํŒจํ„ด์„ ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“์„ค๊ณ„

Memory-structure image

์œ„ ๊ทธ๋ฆผ์€ Book_Kitty ํ”„๋กœ์ ํŠธ์˜ MVVM ๊ตฌ์กฐ์—์„œ Coordinator๋ฅผ ์ ์šฉํ•œ MVVM-C ์•„ํ‚คํ…์ฒ˜ ๋ชจ์‹๋„์ž…๋‹ˆ๋‹ค.

  • View๋Š” ViewModel์— ์˜์กดํ•˜๋ฉฐ, View์—์„œ ๋ฐœ์ƒํ•œ ์‚ฌ์šฉ์ž ์•ก์…˜์€ ViewModel์˜ Input ์ŠคํŠธ๋ฆผ์„ ํ†ตํ•ด ViewModel ๋‚ด์—์„œ ๋ฐฉ์ถœ๋ฉ๋‹ˆ๋‹ค.

  • Coordinator๋Š” ํ™”๋ฉด ์ด๋™์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ViewModel์— ์˜์กดํ•˜์—ฌ View๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋˜์„œ ViewModel์—์„œ ๋ฐฉ์ถœ๋œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•ฉ๋‹ˆ๋‹ค.

    • BookKitty ํ”„๋กœ์ ํŠธ์—์„œ๋Š” โ€œRxSwift ๊ธฐ๋ฐ˜์˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜์—ฌ, ViewModel์ด Coordinator์— ์ง์ ‘ ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹คโ€.
    • ๋Œ€์‹ , ViewModel์—์„œ ํ™”๋ฉด ์ „ํ™˜ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” Relay๋ฅผ ์„ ์–ธํ•˜๊ณ  Coordinator๊ฐ€ ์ด Relay๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ํ™”๋ฉด ์ „ํ™˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋กœ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์œ„์™€๊ฐ™์€ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด ViewModel๊ณผ Coordinator์˜ ๊ฒฐํ•ฉ๋„๋Š” ๊ฐ์†Œ์‹œํ‚ค๊ณ  RxSwift ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ์—ฐ๊ฒฐ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ท ํ”„๋กœํ† ์ฝœ

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

protocol Coordinator: AnyObject {
    // ...

    var finishDelegate: CoordinatorFinishDelegate? { get set }

    var childCoordinators: [Coordinator] { get set }

    func start()
    func finish()
}

childCoordinators

Coordinator ํŒจํ„ด์„ ํ™œ์šฉํ•˜๋‹ค ๋ณด๋ฉด, ํ•˜๋‚˜์˜ ํ™”๋ฉด ํ๋ฆ„๋งŒ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ™”๋ฉด ํ๋ฆ„์„ ๊ด€๋ฆฌํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ, ๋ถ€๋ชจ Coordinator๊ฐ€ ์ž์‹ Coordinator๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ์ด๋ฅผ ์œ„ํ•ด childCoordinators๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

์•ฑ์ด ์ปค์งˆ์ˆ˜๋ก ๋‹จ์ผ Coordinator๋กœ ๋ชจ๋“  ํ™”๋ฉด ์ „ํ™˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ ํ๋ฆ„์„ ๋‹ด๋‹นํ•˜๋Š” Coordinator๋ฅผ ๋ณ„๋„๋กœ ๋งŒ๋“ค๊ณ  ๋ถ€๋ชจ Coordinator๊ฐ€ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ์œ ์—ฐํ•˜๋‹ค ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ๋ถ€๋ชจ Coordinator๋Š” ์ž์‹ Coordinator๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ childCoordintors ๋ฐฐ์—ด์— ์ €์žฅํ•˜์—ฌ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ž์‹ Coordinator๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ๋ฐฐ์—ด์—์„œ ์ œ๊ฑฐํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func start()

start() ๋ฉ”์„œ๋“œ๋Š” Coordinator์˜ ์‹คํ–‰์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํ™”๋ฉด์„ ์ƒ์„ฑํ•˜๊ณ , navigationController์— pushํ•˜์—ฌ ํ™”๋ฉด์„ ํ‘œ์‹œํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

func finish()

extension Coordinator {
    func finish() {
        childCoordinators.removeAll()
        finishDelegate?.coordinatorDidFinish(childCoordinator: self)
    }
}

finish() ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ Coordinator๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ, ์ž์‹ Coordinator๋ฅผ ๋ชจ๋‘ ์ •๋ฆฌํ•˜๊ณ  ๋ถ€๋ชจ์—๊ฒŒ ์ข…๋ฃŒ๋ฅผ ์•Œ๋ฆฌ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

finishDelegate

protocol CoordinatorFinishDelegate: AnyObject {
    func coordinatorDidFinish(childCoordinator: Coordinator)
}

finishDelegate๋Š” Coordinator๊ฐ€ ์ž์‹ ์˜ ์—ญํ• ์„ ๋งˆ์นœ ํ›„, ๋ถ€๋ชจ Coordinator์—๊ฒŒ ์ด๋ฅผ ์•Œ๋ฆฌ๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋Š” Delegate์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ Coordinator๋Š” ํŠน์ • Coordinator์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๊ฐ€ ๋๋‚ฌ์Œ์„ ๊ฐ์ง€ํ•˜๊ณ  ์ ์ ˆํ•œ ์ •๋ฆฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ๋ฌด๋ฆฌ

Book_Kitty ํ”„๋กœ์ ํŠธ์—์„œ๋Š” MVVM-C ์•„ํ‚คํ…์ฒ˜์™€ RxSwift ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ณด๋‹ค ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ์„ฑ ๋†’์€ ํ™”๋ฉด ์ „ํ™˜ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์ด ๋›ฐ์–ด๋‚œ ํ™”๋ฉด ์ „ํ™˜ ํ๋ฆ„์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


ยฉ 2024. All rights reserved.

Powered by Hydejack v9.2.1