왕논의 연구실

Coordinator 패턴을 적용한 앱 예제 본문

iOS/Swift

Coordinator 패턴을 적용한 앱 예제

ywangnon 2025. 3. 16. 23:37

🎯 예제 목표:

  • 로그인 → 메인(탭바) → 기능 실행(메모 작성) → 결과 → 홈으로 돌아가기
  • Coordinator 패턴을 적용하여 화면 전환을 효율적으로 관리
  • 일반적인 예제 앱으로 만들어 블로그에서 사용 가능하도록 구성

🚀 예제 앱 개요

📝 메모 앱 예제
1️⃣ 로그인 화면 (LoginCoordinator)

  • 로그인, 회원가입, 비밀번호 찾기
  • 로그인 성공 시 메인 화면(탭바)로 이동

2️⃣ 메인 화면 (MainCoordinator)

  • 홈(HomeViewController) → 새 메모 작성 기능
  • 메모 리스트(MemoListViewController) → 작성된 메모 보기
  • 설정(SettingsViewController)

3️⃣ 메모 작성 기능 (FeatureCoordinator)

  • 새 메모 작성 (NewMemoViewController)
  • 미리보기 (PreviewViewController)
  • 저장 후 메모 리스트로 이동

🏗 Coordinator 패턴 적용 5단계

1️⃣ 앱 화면 구조를 정의한다
2️⃣ 각 Coordinator의 역할을 정리한다
3️⃣ Coordinator 클래스를 생성한다
4️⃣ Coordinator 간의 화면 전환을 구현한다
5️⃣ 앱의 루트 Coordinator를 설정하여 시작한다


1️⃣ 앱 화면 구조 정의하기

📌 앱의 화면 흐름

[LoginCoordinator] 
  └→ LoginViewController  → MainCoordinator

[MainCoordinator] (탭바)
  ├─ HomeViewController (메모 작성 버튼)
  ├─ MemoListViewController (작성된 메모 확인)
  └─ SettingsViewController (설정 화면)

[FeatureCoordinator] (메모 작성 흐름)
  ├─ NewMemoViewController
  ├─ PreviewViewController (미리보기)
  └─ MemoListViewController (저장 후 이동)

2️⃣ 각 Coordinator의 역할 정리

Coordinator 역할
LoginCoordinator 로그인/회원가입 관리
MainCoordinator 탭바(홈, 메모 리스트, 설정) 관리
FeatureCoordinator 메모 작성 기능 관리

3️⃣ Coordinator 클래스 생성하기

🔹 1. 공통 Coordinator 프로토콜

모든 Coordinator는 start() 메서드를 가지고 있음.

protocol Coordinator {
    func start()
}

🔹 2. LoginCoordinator (로그인 화면 관리)

로그인이 끝나면 MainCoordinator로 이동하는 역할을 한다.

class LoginCoordinator: Coordinator {
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        let loginVC = LoginViewController()
        loginVC.onLoginSuccess = { [weak self] in
            self?.navigateToMain()
        }
        navigationController.pushViewController(loginVC, animated: true)
    }

    private func navigateToMain() {
        let tabBarController = UITabBarController()
        let mainCoordinator = MainCoordinator(tabBarController: tabBarController)
        mainCoordinator.start()
        navigationController.setViewControllers([tabBarController], animated: true)
    }
}

📌 설명:

  • 로그인 화면을 띄운다.
  • 로그인 성공하면 MainCoordinator로 이동한다.

🔹 3. MainCoordinator (탭바 관리)

메인 탭바를 초기화하고, 화면 전환을 담당한다.

class MainCoordinator: Coordinator {
    private let tabBarController: UITabBarController

    init(tabBarController: UITabBarController) {
        self.tabBarController = tabBarController
    }

    func start() {
        let homeVC = HomeViewController()
        let memoListVC = MemoListViewController()
        let settingsVC = SettingsViewController()

        homeVC.onStartNewMemo = { [weak self] in
            self?.navigateToNewMemo()
        }

        tabBarController.viewControllers = [
            UINavigationController(rootViewController: homeVC),
            UINavigationController(rootViewController: memoListVC),
            UINavigationController(rootViewController: settingsVC)
        ]
    }

    private func navigateToNewMemo() {
        if let navController = tabBarController.selectedViewController as? UINavigationController {
            let featureCooperator = FeatureCooperator(navigationController: navController)
            featureCooperator.start()
        }
    }
}

📌 설명:

  • 탭바 구성: 홈, 메모 리스트, 설정을 관리
  • 홈에서 새 메모 작성 버튼을 누르면 FeatureCoordinator 실행

🔹 4. FeatureCoordinator (메모 작성 흐름)

class FeatureCoordinator: Coordinator {
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        let newMemoVC = NewMemoViewController()
        newMemoVC.onComplete = { [weak self] in
            self?.navigateToPreview()
        }
        navigationController.pushViewController(newMemoVC, animated: true)
    }

    private func navigateToPreview() {
        let previewVC = PreviewViewController()
        previewVC.onComplete = { [weak self] in
            self?.navigateToMemoList()
        }
        navigationController.pushViewController(previewVC, animated: true)
    }

    private func navigateToMemoList() {
        navigationController.popToRootViewController(animated: true)
    }
}

📌 설명:

  • 새 메모 작성 → 미리보기 → 메모 리스트 로 화면 전환을 관리
  • 모든 화면 전환을 FeatureCoordinator가 담당

4️⃣ 앱의 루트 Coordinator 설정하기

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var rootNavigationController: UINavigationController?

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        rootNavigationController = UINavigationController()
        window?.rootViewController = rootNavigationController
        window?.makeKeyAndVisible()

        let loginCoordinator = LoginCoordinator(navigationController: rootNavigationController!)
        loginCoordinator.start()

        return true
    }
}

🚀 Coordinator 패턴의 장점

각 화면은 다음 화면을 신경 쓰지 않음
화면 흐름을 쉽게 변경 가능
유지보수가 용이함

💡 Coordinator 패턴을 적용하면 화면 전환이 체계적으로 관리되어 확장성과 유지보수성이 높아진다!