Skip to content

✨[feat]: 공통 으로 쓸 화면 전환 구현#3

Merged
Roy-wonji merged 2 commits intodevelopfrom
Feature/navigation
Aug 12, 2025
Merged

✨[feat]: 공통 으로 쓸 화면 전환 구현#3
Roy-wonji merged 2 commits intodevelopfrom
Feature/navigation

Conversation

@Roy-wonji
Copy link
Contributor

  • 공통으로 사용할 화면 전환 로직 코디네이터 구현
  • navigationStack 방식으로 구현

✨ 작업 내용

  • 공통으로 사용 할 화면 전환 protocol 구현
  • coordinator 로 화면 전환 구현

📝 참고 사항

  • navigationpath 를 미리 정의 해서 데이터 넘길럴 미리 설정 하면 좋을 거 같아서 해당 코디네이터를 구현 했습니다

Key Changes 🔥 (주요 구현/변경 사항)

final class IntroduceCoordinator: NavigationControlling, ObservableObject {

  @Published var path = NavigationPath()

  // 액션 기반 네비게이션
  enum Action {
    case start
    case presentMain
    case pop
    case popToRoot
    case  presntDetail
  }

  func send(_ action: Action) {
    switch action {
    case .start:
      start()

    case .presentMain:
      path.append(IntroduceRoute(route: .introduceMain))

    case .pop:
      if !path.isEmpty { path.removeLast() }

    case .popToRoot:
      path = .init()

    case .presntDetail:
      path.append(IntroduceRoute(route: .teamAgreement))
      
    }
  }

  // MARK: - NavigationControlling 요구 구현
  func start() {
    reset()
    send(.presentMain)
  }

  // ⚠️ 프로토콜이 요구한다면 private 붙이면 안 됨
  func reset() {
    path = .init()
  }
}
import Foundation
import SwiftUI

// MARK: - Navigation 제어 프로토콜

/// SwiftUI `NavigationStack` 기반 화면 전환을 제어하는 공통 프로토콜입니다.
///
/// 각 탭 또는 플로우 별로 코디네이터가 이 프로토콜을 채택하면
/// 공통적인 `goBack`, `reset` 동작을 재사용할 수 있습니다.
protocol NavigationControlling: AnyObject {

  /// 현재 네비게이션 경로 상태입니다.
  ///
  /// `NavigationStack(path:)`에 바인딩되어 화면 이동을 제어합니다.
  var path: NavigationPath { get set }

  /// 초기 진입 지점을 설정하는 메서드입니다.
  ///
  /// 각 코디네이터에서 구현되어야 하며,
  /// 앱 시작 또는 탭 변경 시 루트 화면을 정의합니다.
  func start()

  /// 마지막 화면을 스택에서 제거하여 이전 화면으로 이동합니다.
  func goBack()

  /// 스택의 모든 경로를 제거하고 루트 화면으로 돌아갑니다.
  func reset()
}

// MARK: - NavigationControlling 기본 구현

extension NavigationControlling {

  /// 현재 화면을 스택에서 팝(뒤로 가기)합니다.
  ///
  /// - 동작:
  ///   - `path`가 비어있지 않은 경우, 마지막 항목을 제거하여 이전 화면으로 이동합니다.
  ///
  /// - 예시:
  ///   ```swift
  ///   coordinator.goBack()
  ///   ```
  func goBack() {
    guard !path.isEmpty else { return }
    path.removeLast()
  }

  /// 네비게이션 스택을 초기 상태(루트)로 리셋합니다.
  ///
  /// - 동작:
  ///   - 현재 경로 배열에서 모든 화면을 제거하여, 루트 화면만 유지합니다.
  ///
  /// - 예시:
  ///   ```swift
  ///   coordinator.reset()
  ///   ```
  func reset() {
    path.removeLast(path.count)
  }
}

To Reviewers 🙏 (리뷰어에게 전달하고 싶은 말)

  • 화면 전환을 간단하게 사용 하실 수있게 편리 하게 만들어봤습니다!

* 공통으로 사용할 화면 전환 로직  코디네이터 구현
*  navigationStack 방식으로 구현
@Roy-wonji Roy-wonji self-assigned this Aug 11, 2025
@auto-assign auto-assign bot requested review from Peter1119 and minneee August 11, 2025 07:51
@Roy-wonji Roy-wonji added the ✨ 기능추가 새로운 기능 추가 label Aug 11, 2025
Copy link
Collaborator

@Peter1119 Peter1119 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 ~! 리뷰 사항 한번 고려해주시고
수정사항도 수정 부탁드려요 ~!

Comment on lines +8 to +10
import Combine
import SwiftUI

Copy link
Collaborator

Choose a reason for hiding this comment

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

요건 중복되어 있어서 제거되는게 좋을 것 같아요 ~!

case presentMain
case pop
case popToRoot
case presntDetail
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기 오타가 있어서 수정해야할 것 같습니다 ~!

Comment on lines +32 to +34
case .presentMain:
path.append(IntroduceRoute(route: .introduceMain))

Copy link
Collaborator

Choose a reason for hiding this comment

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

이 앱은 페이지가 많지 않아서 크게 케이스가 많이 안생기겠지만
enum의 연관값으로 받아서 case .present(let path): path.append(IntroduceRoute(route: path))
이런식으로 확장에 열려있으면 어떨까 싶습니다 ~!

// 팀소개
case teamIntroduce
// 팀 블로그
case temBlog
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기도 수정 부탁드려요 ~!

Comment on lines +19 to +45

// MARK: - 내부 전용 초기화

/// 내부 Route 값을 기반으로 IntroduceRoute를 생성합니다.
///
/// 외부에서는 직접 case를 생성하지 않고, 내부에서만 변환을 허용합니다.
///
/// - Parameter route: 내부용 Route enum 값
init(route: Route) {
switch route {
case .introduceMain: self = .introduceMain
case .teamAgreement : self = .teamAgreement
case .teamIntroduce: self = .teamIntroduce
case .temBlog: self = .temBlog
}
}

// MARK: - 내부 전용 라우트 Enum

/// 외부 접근은 가능하지만 직접 IntroduceRoute를 생성할 수 없도록 제어하기 위한 내부 enum입니다.
enum Route {
case introduceMain
case teamAgreement
case teamIntroduce
case temBlog
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

라우팅 구조와 접근 제어 고민이 좋은 것 같습니다!

다만 외부 접근해서 생성하는 것이 불가능 하게 하는 의도라고 하셨는데 실제로는 외부에서 생성도 가능하고
새로운 route가 추가되었을 경우 3곳에서 수정사항이 생길 수 있어 복잡도가 올라갈 것으로 예상됩니다

그래서 우선은 단순하게 enum 타입으로 생성하는 것이 어떨까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Peter1119 흠 한번 고려 해봐서 수정 해볼계요

@Roy-wonji
Copy link
Contributor Author

@Peter1119 , @minneee
수정 했는데 보고 함 피드백 주세요!

Copy link
Collaborator

@minneee minneee left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 ~! 👍🏻

@Peter1119
Copy link
Collaborator

@Peter1119 , @minneee 수정 했는데 보고 함 피드백 주세요!

고생하셨습니다 ~!

@Roy-wonji Roy-wonji merged commit 40c52a3 into develop Aug 12, 2025
@Roy-wonji Roy-wonji changed the title ✨[feat]: 곧통 으로 쓸 화면 전환 구현 ✨[feat]: 공통 으로 쓸 화면 전환 구현 Aug 12, 2025
@Roy-wonji Roy-wonji deleted the Feature/navigation branch August 12, 2025 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ 기능추가 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants