8.1 Navigation이란?

Navigation이라는 단어는 사람마다 다양한 의미를 가질 수 있습니다. 대다수의 사람들은 Navigation이라는 단어를 들었을때, SwiftUI의 NavigationStack과 UIKit의 UINavigationController가 제공하는 drill-down 스타일의 Navigation을 떠올리곤 합니다. 그러나, 만약 drill-down 스타일이 Navigation으로 간주된다면, SwiftUI의 sheet와 fullscreen covers 역시 Navigation으로 볼 수 있습니다. 이 두 가지 방식과 기존 방식의 유일한 차이점은 sheet와 fullscreen covers View가 오른쪽에서 왼쪽 방향으로 나타나는 것이 아니라, 아래에서 위로 나타나는 애니메이션이 적용된다는 점입니다.

sheet와 fullscreen covers도 Navigation으로 간주된다면 popovers, alert, confirmation dialogs을 포함한 커스텀 Navigation도 모두 Navigation의 일종입니다.

따라서, Navigation의 정의는 다음과도 같습니다.

<aside> 💡 Navigation은 앱에서 모드를 변경하는 것이다.

</aside>

drill-down의 sheet, popovers, fullscreen covers, alert, dialogs 등은 모두 앱에서 ‘모드 변경’을 수행하는 요소입니다. 여기서 ‘모드 변경’은 다음을 뜻합니다.

<aside> 💡 모드 변경은 어떤 상태가 존재하지 않던 상태에서 존재하게 되거나 그 반대의 상태가 되는 것을 말한다.

</aside>

따라서, 상태의 일부가 ‘존재하지 않음’에서 ‘존재함’으로 전환되는 경우, 이는 앱 ‘Navigation’ 혹은 ‘모드 변경’을 나타내며, 상태가 다시 ‘존재하지 않음’으로 돌아오면 Navigation이 취소되고 이전 모드로 복귀합니다. 이는 상태 기반 Navigation에 대한 매우 추상적인 설명입니다.

TCA에서 Navigation은 앱의 화면 전환을 관리하는 기능을 의미합니다. TCA는 State와 Action을 사용하여 Navigation을 처리하므로, SwiftUI의 명령형 방식의 화면 전환 코드를 작성할 필요가 없습니다.

상태 기반 Navigation의 두 가지 주요 형태인 트리 기반 Navigation스택 기반 Navigation으로 구분됩니다. 대부분의 Navigation은 이 두가지 방식을 조합하여 사용하는데, 각각의 방식이 가진 장점과 단점을 이해하는 것이 중요합니다. 따라서 이제 트리 기반 Navigation과 스택 기반 Navigation이라는 상태 기반 Navigation의 두 주요 형태를 보다 구체적으로 살펴보겠습니다.

8.1.1 트리 기반 Navigation

앞서 상태 기반 Navigation은 상태의 존재 또는 비존재에 의해 제어된다고 설명했습니다. ‘존재’라는 용어를 정의하지 않았지만 이를 정의할 수 있는 몇 가지 방법이 있습니다. 그 중 상태의 존재 여부를 Swift의 옵셔널 혹은 열거형 타입으로 정의할 수 있는데, 이는 Navigation 상태가 중첩될 수 있음을 의미하고 트리와 같은 구조를 형성하기 때문에 트리 기반 Navigation을 구성할 수 있습니다.

아래는 item으로 구성된 인벤토리 리스트에서 항목 중 하나를 탭하면 해당 item의 세부 정보 화면으로 drill-down Navigation을 수행하는 예시 코드입니다.

drill-down Navigation을 제어하기 위한 State 변수를 옵셔널 타입으로 선언하고 PresentationState 프로퍼티 래퍼를 적용합니다.

struct InventoryFeature: Reducer {
  struct State {
    @PresentationState var detailItem: DetailItemFeature.State?
    /* code */
  }
  /* code */
}