Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR} Coordinator 구조 개선 #19

Open
SuniDev opened this issue Jun 20, 2024 · 1 comment
Open

[REFACTOR} Coordinator 구조 개선 #19

SuniDev opened this issue Jun 20, 2024 · 1 comment
Assignees

Comments

@SuniDev
Copy link
Contributor

SuniDev commented Jun 20, 2024

💡 요약

  • Coordinator를 큰 피쳐에 따라 분리

[참고]

AuthCoordinator에서 MainCoordinator로 변환하는 것은 사용자 인증이 완료된 후 메인 앱 흐름으로 전환하는 것을 의미합니다. 이 작업은 다음과 같은 단계를 통해 수행할 수 있습니다:

  1. 현재 AuthCoordinator를 종료하고,
  2. 새로운 MainCoordinator를 시작하는 것입니다.

이를 위해서는 AuthCoordinatorMainCoordinator로의 전환을 관리하는 상위 Coordinator 또는 AppDelegate/SceneDelegate와 같은 상위 계층에 대한 참조를 가져야 합니다.

Step-by-Step Guide

1. Coordinator 프로토콜 수정 (옵션)

상위 Coordinator와의 상호작용을 위해 기본 Coordinator 프로토콜에 부모 Coordinator에 대한 참조를 추가할 수 있습니다.

protocol Coordinator {
    var navigationController: UINavigationController { get set }
    var parentCoordinator: Coordinator? { get set }
    func start()
}

2. AuthCoordinator 구현

AuthCoordinator는 인증이 완료되면 MainCoordinator를 시작합니다.

class AuthCoordinator: Coordinator {
    var navigationController: UINavigationController
    var parentCoordinator: Coordinator?

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

    func start() {
        let loginViewController = LoginViewController()
        loginViewController.coordinator = self
        navigationController.pushViewController(loginViewController, animated: true)
    }

    func didFinishAuthentication() {
        parentCoordinator?.childDidFinish(self)
        let mainCoordinator = MainCoordinator(navigationController: navigationController)
        mainCoordinator.parentCoordinator = parentCoordinator
        parentCoordinator?.childDidStart(mainCoordinator)
        mainCoordinator.start()
    }
}

3. MainCoordinator 구현

MainCoordinator는 기본 네비게이션 흐름을 처리합니다.

class MainCoordinator: Coordinator {
    var navigationController: UINavigationController
    var parentCoordinator: Coordinator?

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

    func start() {
        let viewController = MainViewController()
        viewController.coordinator = self
        navigationController.pushViewController(viewController, animated: true)
    }

    func showDetail() {
        let detailViewController = DetailViewController()
        navigationController.pushViewController(detailViewController, animated: true)
    }
}

4. RootCoordinator 구현 (상위 Coordinator)

상위 Coordinator는 앱의 전반적인 흐름을 관리하고, 자식 Coordinator를 시작하거나 종료합니다.

class RootCoordinator: Coordinator {
    var navigationController: UINavigationController
    var childCoordinator: Coordinator?

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

    func start() {
        showAuthentication()
    }

    func showAuthentication() {
        let authCoordinator = AuthCoordinator(navigationController: navigationController)
        authCoordinator.parentCoordinator = self
        childCoordinator = authCoordinator
        authCoordinator.start()
    }

    func showMain() {
        let mainCoordinator = MainCoordinator(navigationController: navigationController)
        mainCoordinator.parentCoordinator = self
        childCoordinator = mainCoordinator
        mainCoordinator.start()
    }

    func childDidFinish(_ child: Coordinator?) {
        if child === childCoordinator {
            childCoordinator = nil
        }
    }

    func childDidStart(_ child: Coordinator) {
        childCoordinator = child
    }
}

5. AppDelegate 또는 SceneDelegate에서 RootCoordinator 사용

AppDelegate 또는 SceneDelegate에서 RootCoordinator를 초기화하고 시작합니다.

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    var rootCoordinator: RootCoordinator?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        let navController = UINavigationController()
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = navController
        window?.makeKeyAndVisible()

        rootCoordinator = RootCoordinator(navigationController: navController)
        rootCoordinator?.start()
    }
}

요약

  • AuthCoordinator에서 인증이 완료되면 didFinishAuthentication 메서드를 호출하여 상위 Coordinator에게 알립니다.
  • 상위 Coordinator는 현재 AuthCoordinator를 종료하고, 새로운 MainCoordinator를 시작합니다.
  • RootCoordinator는 자식 Coordinator의 시작 및 종료를 관리합니다.

이 방법을 통해 AuthCoordinator에서 MainCoordinator로 전환할 수 있습니다. 이 패턴을 사용하면 앱의 네비게이션 흐름을 명확하게 관리하고, 코드의 유지보수성을 높일 수 있습니다.

@SuniDev SuniDev self-assigned this Jun 20, 2024
@SuniDev
Copy link
Contributor Author

SuniDev commented Aug 9, 2024

내비게이션 로직을 ViewController에서 분리하는 것은 코드의 유지보수성, 테스트 용이성, 확장성 등을 크게 개선할 수 있음.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant