[SwiftUI] 네비게이션 버그 ?!

·2025년 5월 6일
0

SwiftUI포스팅

목록 보기
2/2

문제 발생

기존 닫기는 fullScreenCover에 맞게 dismiss로 해주고 있었는데, 이제는Navigation으로 대체를 하면서 dismiss가 안먹히게 된 상황!
그래서 기존 NavigationManager.setAuthRoot를 통해서 RootView를 전환시켜주려했는데, 다음과 같이 계속 유저타입선택 페이지에서 무한히 머무르는 버그가 발생했다.

userTypeSelection의 닫기버튼

ToolbarItem(placement: .navigationBarTrailing) {
	Button("닫기") {
		navigationManager.setAuthRoot()
	}
}

SignInView에서 로그인(회원가입)시 로직

await MainActor.run {
	isLoading = false
    // 기존 코드
    navigationManager.rootview = .auth(.userTypeSelection) 
    // 변경코드
	navigationManager.navigate(to: .userTypeSelection)
}

NavigationManager 파일은 다음과 같다.
navigate를 통해서 path에 넣어주는 식이다.

Navigation Manager

class NavigationManager: ObservableObject {
    @Published var path = NavigationPath()
    @Published var rootView: AppRootView = .auth(.login)

    // 같은이름 navigate 3개를 하나로 합친 상태 
    func navigate<T: Hashable>(to destination: T) {
        path.append(destination)
    }

    func popToRoot() {
        path = NavigationPath()
    }

    func pop() {
        path.removeLast()
    }

    func setMainRoot(userType: UserType) {
        path = NavigationPath()
        switch userType {
        case .mentor:
            rootView = .mentor(.home)
        case .learner:
            rootView = .learner(.home)
        }
    }

    func setAuthRoot() {
        path = NavigationPath()
        rootView = .auth(.login)
    }
}

문제 원인

SignInView에서 신규 유저일 경우(회원가입이 진행되어야함) 버그가 발생한다.

if isExistingUser {  //이미 있는 유저면 ..
	checkUserType()
} else {
	navigationManager.rootView = .auth(.userTypeSelection)
}

신규 유저로 판단되면 RootView를 .auth(.userTypeSelection)으로 바꾸는데, 닫기 버튼을 누르면 다시.auth(.login)으로 돌아가고, 이때 SignInView가 다시 그려진다.
문제는 이 SignInView에서 로그인 로직이 다시 실행되면서 동일하게 .auth(.userTypeSelection)으로 이동해 무한 루프가 발생했던 것이다.

두 동작이 반복되면서 루프에 빠지게 된다
1. 닫기 → .auth(.login)
2. 로그인 로직 재실행 → .auth(.userTypeSelection)
→ 무한 반복

해결

기존에는 rootView 자체를 덮어씌우는 방식이었지만, 아래처럼 NavigationStack의 path에만 뷰를 추가하는 방식으로 해결해주었다.
navigationManager.navigate(to: .userTypeSelection)
이렇게 하면 rootView는 여전히 .auth(.login)으로 유지되고, SignInView는 재실행되지 않는다.
따라서 userTypeSelection에서 닫기 버튼을 눌렀을 때 더 이상 루프가 발생하지않고, 잘 수행되는 것을 확인할 수 있다.

해결 결과물

profile
기억보단 기록을

0개의 댓글