Skip to content

[Work 31] ViewController의 화면전환/조립 책임을 Coordinator와 ScreenFactory로 분리했습니다. - #20

Merged
snughnu merged 20 commits into
developfrom
WORK-31
Sep 9, 2026
Merged

snughnu merged 20 commits into
developfrom
WORK-31

Conversation

@snughnu

@snughnu snughnu commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

JIRA

📝 작업 내용

📌 요약

  • ViewController가 UseCase/Repository를 직접 조립하고 화면전환(push/present)까지 담당하던 구조를,
    Coordinator(화면전환 전담)와 ScreenFactory(조립 전담)로 분리했습니다.
  • 여러 화면에 중복 구현돼 있던 조립 로직(예: ChatViewModel 조립, SearchPlaceCardViewController 조립)을
    ScreenFactory 쪽 공용 메서드 하나로 통합했습니다.

🔍 상세

1. Coordinator / ScreenFactory 기반 구조 도입

  • 문제 상황
    • ViewController 하나가
      "Repository resolve → UseCase 조립 → ViewModel 생성 → push/present"까지 전부 담당하고 있었습니다.
  • 해결 방법
    • Coordinator
      • start()만 갖는 최소 프로토콜입니다.
      • 내비게이션 스택이 필요 없는 화면전환(AppCoordinator의 루트 화면 교체)도 채택할 수 있도록
        UINavigationController 요구사항을 넣지 않았습니다.
    • NavigationCoordinator
      • Coordinator를 상속하며 navigationController: UINavigationController를 요구하는 프로토콜입니다.
      • push, present, presentInNavigationController 등 push/present 보일러플레이트를 extension으로 제공합니다.
    • ScreenFactory
      • DIContainer를 들고 있으면서,
        화면별 조립 메서드(makeChatViewController, makeAppointmentRouteViewController 등)를
        화면 단위 extension 파일로 나눠 제공합니다.
      • Repository/UseCase 조합 코드는 이 레이어에만 존재하고, Coordinator와 ViewController는 이 코드를 갖지 않습니다.

2. 탭/화면별 Coordinator 도입

  • AppCoordinator / TabBarCoordinator
    • SceneDelegate가 직접 하던 로그인 화면 표시,
      로그인 성공 시 탭바 전환(cross-dissolve 애니메이션 포함),
      3개 탭의 UINavigationController 및 탭 Coordinator 생성을 이전했습니다.
  • HomeCoordinator / AppointmentListCoordinator / MyPageCoordinator
    • 각 탭의 루트 화면 및 하위 화면전환을 담당합니다.
    • AppointmentListCoordinator
      AppointmentListViewControllerPastAppointmentListViewController
      같은 내비게이션 스택을 공유하므로 하나의 Coordinator로 통합했습니다.
  • ChatCoordinator
    • ChatViewController가 모달로 띄우던 화면(약속 경로, 약속 정보, 내 위치 공유, 장소 검색/공유, 공유 장소 목록)과
      그 안의 AppointmentInfoViewController가 갖고 있던 하위 전환(날짜 선택, 장소 검색, 장소 지도 선택)까지 함께 담당합니다.
  • RouteSearchCoordinator
    • RouteSearchViewController가 항상 자체 UINavigationController로 감싸져 모달로 뜨는 독립 흐름이라,
      그 내비게이션 컨트롤러를 직접 생성해 소유하는 전용 Coordinator로 분리했습니다.

💬 리뷰 노트

1. Coordinator 단독이 아닌 Coordinator + Factory 조합을 선택한 이유

  • Coordinator 패턴만 단독 도입
    • 화면전환 흐름을 한눈에 볼 수 있다는 장점은 있지만,
      결국 Coordinator 자체가 UseCase 조립까지 떠안게 되어 "조립" 문제는 해결되지 않습니다.
  • DIContainer/ScreenFactory 확장만 단독 도입
    • 조립 문제는 해결되지만, push/present 같은 전환 책임은 여전히 ViewController에 남습니다.
  • Coordinator + Factory 조합 (채택)
    • ViewController: 화면 표시 / ScreenFactory: 조립 / Coordinator: 전환으로 책임을 3분할해,
      두 문제를 함께 해결할 수 있다고 판단했습니다.

2. Coordinator 프로토콜에서 UINavigationController를 필수로 두지 않은 이유

  • 처음에는 Coordinator 프로토콜 자체에 navigationController: UINavigationController를 요구사항으로 뒀는데,
    AppCoordinator처럼 UIWindow.rootViewController를 직접 교체하는 화면전환에는 내비게이션 스택 자체가 필요 없었습니다.
  • Coordinator(최소 프로토콜)와 NavigationCoordinator(내비게이션 스택이 필요한 경우에만 채택)로 분리해,
    push 기반 전환과 루트 화면 교체 양쪽을 모두 자연스럽게 표현할 수 있게 했습니다.

3. ChatCoordinator를 각 탭 Coordinator가 어떻게 공유하는지

  • Chat 화면은 Home/AppointmentList 어느 탭에서 진입했는지에 따라 속한 내비게이션 스택이 다릅니다.
    그래서 ChatCoordinator를 미리 만들어두지 않고,
    HomeCoordinator/AppointmentListCoordinator가 채팅 화면을 push하는 시점에
    자신의 navigationController를 넘겨 ChatCoordinator를 생성하고,
    private var chatCoordinator: ChatCoordinator?로 강하게 소유하는 방식을 택했습니다.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI 코드 리뷰 - 아키텍처 관점

SceneDelegate에 인라인으로 작성되어 있던 화면 전환 로직 전체를 Coordinator 패턴으로 분리한 PR이다. ScreenFactory를 통해 DI를 일원화하고, View에서 직접 DIContainer를 참조하던 코드를 제거한 점은 의존성 방향 측면에서 개선이다. 다만 몇 가지 구조적 문제가 잔존한다. 첫째, Presentation 계층의 ViewController가 Coordinator의 구체 타입을 직접 참조하고 있어 계층 간 결합이 강하게 남아 있다. 둘째, HomeCoordinator가 UseCase를 직접 생성·실행하는 joinAppointment 메서드를 보유해 Coordinator의 책임 범위를 벗어난다. 셋째, ChatCoordinator.showAppointmentInfo가 ViewController를 반환하는 설계는 Coordinator 추상화와 일관성이 없다.

Comment thread WhereAreYou/WhereAreYou/Core/Coordinator/Implementation/HomeCoordinator.swift Outdated
Comment thread WhereAreYou/WhereAreYou/Core/Coordinator/Implementation/ChatCoordinator.swift Outdated
Comment thread WhereAreYou/WhereAreYou/Core/SceneDelegate.swift Outdated

@sangYuLv sangYuLv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

조립하는 ScreenFactory를 만든 점이 정말 좋은 것 같아요!
수고 많으셨습니다 🦦

중요한 작업인만큼 한 번 더 AI 리뷰를 받아보는 건 어떨까요?
재리뷰에서도 좋은 얘기를 해주기도 하더라구요!

이번 작업을 읽으면서 느낀 건데, 전체적으로 네이밍 수정/검토가 필요할 것 같아요.
단어 조합(e.g. PlaceSelection, PlaceSearch, RouteSearch)이 어떤 화면/기능을 의미하는지 잘 떠오르지 않거나 헷갈리기도 하네요.
큰 변화는 없을 것 같지만, 괜찮으시다면 나중에 한 번 작업을 진행해보겠습니다!

제 코멘트에 대한 답변이나 수정 작업이 모두 완료되면 리뷰 재요청 부탁드립니다. 파이팅 🫡

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI 코드 리뷰 - 아키텍처 관점

SceneDelegate에 인라인으로 작성되어 있던 화면전환 로직을 Coordinator 패턴으로 분리한 PR이다. 각 화면별 Coordinating 프로토콜을 정의하고, ViewController는 해당 프로토콜에만 의존하도록 변경했다. ScreenFactory를 통해 DI 조립 책임을 Coordinator 계층으로 이동시켜 ViewController 내부의 DIContainer 직접 참조를 제거했다. 전반적인 방향성은 적절하나, 일부 구조적 문제가 존재한다.

Comment thread WhereAreYou/WhereAreYou/Core/Coordinator/Protocol/MyPageCoordinating.swift Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI 코드 리뷰 - 아키텍처 관점

Coordinator 패턴을 도입해 SceneDelegate와 각 ViewController에 분산되어 있던 화면 전환 및 DI 조립 책임을 분리한 PR이다. 프로토콜 기반 Coordinating 인터페이스 정의, ScreenFactory를 통한 조립 위임, NavigationCoordinator 프로토콜 extension을 통한 공통 동작 제공 등 구조적으로 명확한 방향을 취하고 있다. 다만 몇 가지 아키텍처적 문제가 존재한다: MyPageCoordinating 프로토콜이 상위 계층의 구체 타입(MyPageViewModel)을 노출하고 있고, ScreenFactory가 싱글턴으로 설계되어 테스트 격리를 해친다. RouteSearchCoordinator의 start()는 실질적으로 빈 메서드로, Coordinator 프로토콜 계약을 위반하는 구조다.

Comment thread WhereAreYou/WhereAreYou/Core/Coordinator/Protocol/MyPageCoordinating.swift Outdated
Comment thread WhereAreYou/WhereAreYou/Core/DI/Implementation/ScreenFactory.swift
Comment thread WhereAreYou/WhereAreYou/Core/Coordinator/Implementation/AppCoordinator.swift Outdated
@snughnu
snughnu requested a review from sangYuLv September 7, 2026 01:04
@snughnu
snughnu requested review from sangYuLv and removed request for sangYuLv September 8, 2026 01:16

@sangYuLv sangYuLv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고 많으셨습니다 🦦

@snughnu
snughnu merged commit 1ddcada into develop Sep 9, 2026
5 checks passed
@snughnu
snughnu deleted the WORK-31 branch September 9, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants