[iOS] View 전환 시 강한 결합(Strong Coupling) 문제와 Coordinator 패턴을 활용한 해결 방법

iosCoordinator Pattern
avatar
2025.03.12
·
3 min read

개인 프로젝트에서 한 ViewController에서 다른 ViewController로 이동할 때, 직접 객체를 생성하고 메서드를 호출하는 방식을 사용했다.

class FirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func navigateToNextView(_ sender: UIButton) {
        let secondVC = SecondViewController()
        navigationController?.pushViewController(secondVC, animated: true)
    }
}

이 방식에는 여러 문제가 있었다.

  1. ViewController 간의 직접적인 의존성 발생: FirstViewControllerSecondViewController의 구체적인 구현을 알아야 함.

  2. 유지보수 어려움: ViewController 간의 이동 방식이 변경될 경우 모든 호출 코드를 수정해야 함.

  3. 테스트 어려움: FirstViewControllerSecondViewController를 직접 참조하므로, 단위 테스트 작성이 어려워짐.

검색을 통해 이러한 문제들을 Coordinator 패턴을 도입하여 해결할 수 있었다.


Coordinator 패턴이란?

ViewController 간의 이동을 관리하는 별도의 객체(Coordinator)를 두어, ViewController 간 결합도를 낮추는 구조적 패턴

Coordinator의 핵심 원칙

  • ViewController는 화면 이동을 직접적으로 처리하지 않는다.

  • Coordinator가 화면 전환을 관리하며, ViewController는 Coordinator에게 이동을 요청한다.

  • 화면 이동 로직을 ViewController에서 분리하여 유지보수성을 높인다.

Coordinator 패턴 적용하기

Coordinator 프로토콜 정의

Coordinator는 화면 이동을 담당하는 객체이므로, 이를 추상화한 프로토콜을 정의한다.

protocol Coordinator {
    func start()
}

MainCoordinator 구현

앱에서 화면 이동을 관리하는 MainCoordinator를 생성하여, ViewController 간의 네비게이션을 담당하도록 한다.

class MainCoordinator: Coordinator {
    var navigationController: UINavigationController
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    func start() {
        let firstVC = FirstViewController()
        firstVC.coordinator = self
        navigationController.pushViewController(firstVC, animated: false)
    }
    
    func showSecondView() {
        let secondVC = SecondViewController()
        navigationController.pushViewController(secondVC, animated: true)
    }
}

ViewController에서 Coordinator 사용하기

FirstViewController에서 Coordinator를 사용하도록 변경한다.

class FirstViewController: UIViewController {
    var coordinator: MainCoordinator?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func navigateToNextView(_ sender: UIButton) {
        coordinator?.showSecondView()
    }
}

AppDelegate 또는 SceneDelegate에서 Coordinator 초기화

앱이 실행될 때 Coordinator를 초기화하고, UINavigationController에 연결해야 한다.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    var coordinator: MainCoordinator?
    
    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        
        let navController = UINavigationController()
        coordinator = MainCoordinator(navigationController: navController)
        coordinator?.start()
        
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = navController
        window?.makeKeyAndVisible()
    }
}






- 컬렉션 아티클