iOS : Navigation vs Modal (1)

Navigation Push & Pop

Jay Kim
11 min readSep 3, 2021
Photo by Halacious on Unsplash

오늘은 iOS 에서 화면을 전환할 때 사용하는 대표적인 두 가지 방법인

  • Navigation - Push & Pop
  • Modal - Present & Dismiss

중에서 Navigation - Push & Pop 에 대해 이야기 해보려고 한다.

사실 iOS 개발하시는 분들이 늘상 사용하는 것들이기 때문에 뭘 이렇게 글로 쓰기까지 해야하나(?)라는 생각도 들긴 하지만, 실제로 Navigation, Modal 을 평소에 사용하면서도 그 특성이나 내부 동작에 대해 잘 모르고 있는 분들이 의외로 많다는 것을 알게 되어… 별 것 아니지만 알고 사용하면 큰 도움이 될 만한 내용들을 정리해보려고 한다.

1. Navigation Push

이름 자체가 Navigation Push 이다. 무슨말인고 하니 일반 UIViewController 에서 동작하는 것이 아니라, UINavigationController 에서 발생하는 동작이라는 것이다.

간단하게 테스트를 진행하기 위해서 Xocde 에서 stroyboard 프로젝트를 하나 만들고 자동으로 생성된 ViewController 를 storyboard 에서 선택한 후에 [Editor → Embed In → Navigation Controller] 까지 진행을 해주자.

위 과정을 정상적으로 진행했다면 Initial View Controller 가UINavigationController 로 변경되었을 것이다.

이제 ViewController 에 Push VC 라는 버튼을 하나 만들어주고 Navigation-Push 동작으로 자기복제를 할 수 있는 코드를 추가해보자.

`Push VC` 라는 이름의 버튼을 만들어준다

위 화면처럼 stroryboard 에서 버튼을 하나 추가해준 뒤에, pushViewController() 함수랑 연결을 해주자.

자기복제 Navigation-Push 함수 만들기

모든 연결이 다 되었으면 실행을 해보자. 실행 화면은 다음과 같이 동작할 것이다.

Push 동작화면

이제 UINavigationController 에서 ViewController 들이 Push 되거나 Pop 될 때 ViewController-Stack 이 어떻게 변하는지 체크해보자.

UINavigationController 구조

애플 공식문서를 보면 UINavigationController 는 array 형태의 viewControllers 라는 property 를 가지고 있는 것을 알 수 있다.

실제로 UINavigationController 에서 push 나 pop 동작이 발생할 경우 push 의 경우에는 viewControllers 배열에 push 한 VC 가 추가되고, pop 한 경우에는 pop 한 VC 가 삭제되는 형태로 동작하는데, 이 동작을 확인하기 위해서 makeTitle() 이라는 함수를 현재 사용중인 ViewController 에 추가해보자.

makeTitle() — Navigation Stack 내용을 표시

위와 같이 코드를 추가해주면 ViewController 가 appear 되는 시점에 makeTitle() 에서 현재 Navigation-Stack 의 갯수를 체크한 후에 ViewController 의 title 로 해당내용을 표시해줄 수 있다.
또한 print 문을 통해서 Navigation-Stack 의 변경사항이 console 에 출력되도록 구현해준다.

구현이 완료된 후 앱을 실행해보면 push 나 pop 동작이 실행될 때마다 ViewController 의 title 에 Navigation-Stack 갯수가 표시되는 것을 볼 수 있고, console 화면에서 Navigation-Stack 의 내용변화도 확인해볼 수 있다.

2. Navigation Pop

위에서 Navigation-Push 동작에 대해 알아보면서 Pop 을 실행할 때는 Navigation-Bar 의 Back 버튼을 사용해서 Pop 동작을 실행했는데 이번에는 수동으로 Pop 을 시킬 수 있는 버튼을 추가해서 Pop 동작에 대한 구현을 추가해보겠다.

기본적으로 Natigation-Pop 동작을 실행시키는 함수는 크게 아래 3가지로 구분된다.

  • popViewController(animated: Bool)
  • popToRootViewController(animated: Bool)
  • popToViewController(UIViewController, animated: Bool)

위 함수들이 각각 어떻게 동작하는지 알아보자.

(1) popViewController(animated: Bool)

popViewController(animated: Bool) 를 실행하면 현재 Navigation-Stack 의 마지막 ViewController 를 Navigation-Stack 에서 제거하고 마지막 바로 이전의 ViewController 로 이동한다.

테스트를 위해서 아래와 같이 Pop VC 라는 이름의 버튼을 추가해주자.

버튼을 추가했으면 해당 버튼의 동작함수인 popViewController() 를 아래와 같이 구현해준다.
popViewController() 함수의 기본적인 동작은 View-Stack 의 갯수가 2개 이상일 때는 popViewController(animated:)를 호출하고, View-Stack 의 갯수가 1개일 때는 Pop 동작을 실행시킬 수 없다는 Alert 를 띄우는 형태이다.

이제 storyboard 에 추가한 버튼과 popViewController() 함수를 연결해준 다음 실행하면 아래와 같이 동작하는 것을 확인할 수 있다.
(Navigation-Stack 의 최상위 VC 에 도달하기 전까지는 UINavigationController 가 자동으로 만들어주는 Back 버튼과 동일하게 동작한다.)

(2) popToRootViewController(animated: Bool)

popToRootViewController(animated: Bool) 을 실행하면 Navigation-Stack 의 첫 번째 ViewController 인 rootViewController 를 제외하고 그 하위에 있는 모든 ViewController 들을 Pop 시키고, rootViewController 로 이동한다.

아래와 같이 Pop to Root-VC 라는 버튼을 추가하고, 새로운 함수를 연결해보자.

이번에 새로 추가하는 함수인 popToRootViewController() 함수는 popViewController() 함수와 내용이 거의 같지만 마지막 Pop 실행을 할 때 호출하는 함수가 popToRootViewController(animated:) 로 변경되었다.

storyboard 에 추가한 버튼과 popToRootViewController() 함수를 연결해주고 앱을 실행하면 다음과 같이 동작하는 것을 확인할 수 있다.

(3) popToViewController(UIViewController, animated: Bool)

위에서 언급한 popViewController(animated:), popToRootViewController(animated:) 는 평소에도 다들 많이 사용하고 있을 것이고, 기본적인 동작에 대해서 대부분 이해하고 있을 것이라고 생각된다.

popToViewController(UIViewController, animated:) 는 실제로 필요에 의해서 사용하는 분들이야 잘 활용하고 있겠지만, 딱히 필요성을 느끼지 못하거나 정확한 용도를 몰라서 사용하지 않는 분들도 많을 것이라 생각되어, 어떤 경우에 유용하게 쓸 수 있는지 살펴보도록 하자.

예를 들어 아래와 같은 상품 쇼핑기능을 구현한 앱이 있다고 가정해보자.

  • 홈화면(HomeViewController) 에서 상품리스트 보기 버튼 을 터치하면
  • 상품리스트 화면(ProductListViewController) 로 이동한다.
  • 상품리스트 화면에서 상품 Cell 을 터치하면 상품상세 화면(ProductDetailViewController) 으로 이동한다.
  • 삼품상세 화면에서 프로모션 배너를 터치하면 프로모션 화면(PromotionViewController) 로 이동한다.
가상의 쇼핑앱 화면 Flow

만약 위의 4개 화면들이 Navigation-Push 를 통해서 화면전환을 진행했고, Navigation-Stack 의 마지막에 PromotionVC 가 들어있다고 가정을 해보자.
이 상태에서 ProductDetailVC 를 거치지 않고, ProductListVC 로 이동하려면 코드를 어떻게 구현해야할까?

뭐 방법이야 여러가지가 있겠지만 가장 쉬운 방법은 popToViewController(_ , animated:) 를 사용하여 아래와 같은 함수를 구현하면 된다.

moveToProductList() 함수

위와 같이 ViewController 의 class 나 protocol 로 체크해서 target-VC 를 결정하는 방법도 있고, Navigation-Stack 의 viewControllers 의 index 를 통해서 target-VC 를 설정하는 방법도 있다.

예를 들어 Pop 동작을 한 개의 ViewController 가 아닌 2개의 ViewController 씩 이동하는 기능을 한 번 만들어보기로 하자.

Navigation-Stack 에 3개 이상의 ViewController 가 있다고 가정했을 때 현재 ViewController 기준으로 Parent VC (VC)혹은 Grand-Parent VC 는 viewControllers 프라퍼티와 index 를 이용하여 아래처럼 접근이 가능하다.

현재 VC : navigationController.viewControllers[stackCount - 1]
상위 VC : navigationController.viewControllers[stackCount - 2]
상위's 상위 VC : navigationController.viewControllers[stackCount - 3]

일단 storyboard 에서 Pop to Grand-Parent VC 라는 버튼을 추가하고,

아래와 같은 함수를 만들어보자.
popToGrandParentViewController() 함수는 현재 Navigation-Stack 에 3개 이상의 ViewController 가 있다면 Grand-Parent VC (상위화면의 상위화면)으로 이동하고, 그렇지 않은 경우는 Alert 를 띄워주는 기능을 수행한다.

storyboard 에서 만든 버튼과 popToGrandParentViewController() 함수를 연결해준 다음 앱을 실행하면 아래와 같이 동작하는 것을 볼 수 있다.

아래 코드는 현재까지 데모를 진행했던 ViewController 의 소스코드이다

데모를 위해 작성한 ViewController 의 Full Source-Code

오늘은 iOS 의 화면전환 Flow 중 하나인 Navigation Push & Pop 에 대해서 알아보았다. Modal Presentation 에 대한 내용도 한 번에 정리하려고 했는데 글이 너무 길어지는 느낌이 있어 Modal Presentation 에 대한 내용과 Navigation 과 Modal 의 조합에 관한 내용은 다음 글에서 다뤄보려고 한다.

여기까지 읽어주셔서 감사하고,
모든 iOS 개발자에게 행복 있기를~

--

--

Jay Kim

iOS를 사랑하는 Software Engineer, 반복 설명하는 것이 점점 귀찮아져서 글을 씁니다 ^^;;;;