Coordinator 패턴.... 패...턴?

7과11사이·2024년 6월 10일
0

디자인 패턴

목록 보기
1/1

엥?? 이게 패턴이야??

라는 생각이 들만큼 당황했던 Coordinator!

'반복되는 코드'라는 개념으로 이해하고 바라보니... 맞네...
화면 전환을 할 때마다 push, pop 등 고정된 메서드로 호출하고 있었다.

이름부터 복잡해 보여서 걱정 태산이었는데, 나름(?) 이해한 것 같아 잊기 전에 정리 ㄱㄱ~


💾 Coordinator Pattern Code

// class에서 채택하여 활용할 수 있도록 AnyObject를 적용
// Coordinator는 가장 하위 구조라 생각하여 parentCoordinator만 정리했을 뿐, childCoordinator를 만들지 않았다
// 이후 적용은 알아서~
protocol Coordinator: AnyObject {
    var navigationController: UINavigationController { get set }
    var parentCoordinator: Coordinator? { get set }
    
    func start()
    func moveToChild(coordinator: Coordinator)
    func removeChildCoordinators()
}

화면 전환! 얼마나 중요한디

2015년 Soroush Khanlou가 소개한 Coordinator는 아래 코드에서 시작됐다고 한다

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let object = dataSource.object(at: indexPath)
    let detailViewController = SKDetailViewController(detailObject: object)
    // 화면 등장~
    navigationController?.present(detailViewController, animated: true, completion: nil)
}

'이 코드에 잘못이 있을까?' 라고 한다면 아니요!

화면 이동도 잘되고 원하는 정보도 잘 보인다!
하지만 Khanlou는 조금 다르게 바라보았는데,

  1. 테이블뷰를 가지고 있는 ViewController가 어떤 화면으로 넘어갈지 알고 있다는 점
  2. 자식 viewController가 부모에게 요청을 하고 있다는 점

이 분은 "한 화면의 모든 객체를 관리하는 대빵 UIViewController가 자식한테 요청을 받아?!"
라고 생각했다는데, 다시 돌아보면... 나름 이해가 될지도..?


🚛 다시 한번 pushViewController

class FirstViewController: UIViewController {
	
  ~~~ blah blah ~~~
    
  @objc func buttonTapped(sender: UIButton) {
      let destinationVC = SecondVC()
      sender.animatedWhenTapped {
          self.dismissAndAnimateTo(VC: destinationVC)
		}
	}
}

나 또한 개인 프로젝트를 할 때 위 코드로 화면 전환을 했다!
코드를 작성했을 때 만해도 충분히 추상화했다는 나름의 만족감을 느끼던 기억이...ㅋㅋㅋㅋㅋ

아.무.튼

코드 형태는 다를 수 있어도 궁극적으로 한번쯤은 도착 화면을 선언하고
pushViewController에 넣어 화면 전환을 구현해보지 않았을까 라고 조심스럽게 추측해본다.

khanlou가 언급한 'ViewController가 다음 화면에 대해 알고 있다'는 점을 생각해보면
위 코드에서도 FirstViewController 라는 객체가 SecondVC 존재를 알게 된다.

서로 알고 있는건 아니지만, SecondVC가 FirstVC에서 직접 생성된다는 점에서 프로퍼티, 메서드 등이 추가되면 FirstVC에서 접근이 가능해진다. 무엇보다 클래스 네이밍이 바뀌면 일일히 수정해주게 되는데, ViewController가 혼자 떨어져 있다고 보기 어려운 구조가 된다.

이 coupling 문제를 해결하는 패턴이 Coordinator 패턴이다!


🚛 Coordinator 적용

어떻게 Coordinator는 이 인연을 끊지 않고 관계를 유지시킬 수 있을까?
FirstVC가 SecondVC를 직접 생성시키지 않도록 객체를 만드는 것이다

SecondVC를 생성, 전환하는 역할을 다른 클래스에게 위임하고 해당 클래스를 MainVC는 참조만 하는 방식이다.

// 화면 전환을 담당할 객체
class MainCoordinator: BaseCoordinator {
    
    // FirstVC를 네비게이션에 올려둔다
    override func start() {
        let rootVC = FirstViewcontroller()
        rootVC.coordinator = self
        navigationController.pushViewController(rootVC, animated: false)
    }
    
	// SecondViewController로 넘어가는 과정!
    func moveToSecondScreen() {
        removeChildCoordinators()
        let coordinator = SecondScreenCoordinator(navigationController: navigationController)
        moveToChild(coordinator: coordinator)
    }
}

class ViewController: UIViewController {
	var coordinator: MainCoordinator?
    
	// 생략
    
    func buttonTapped() {
    	coordinator?.moveToSecondScreen()
	}
}

대략적이긴하지만 위처럼 viewController에서 화면 전환만 coordinator에게 요청하는 구조가 되겠다!

0개의 댓글