react-native의 지옥 1호 : navigation


(이종은(Jong Lee)) #1

제목이 좀 과격한가요?:smile: 그러나 지옥이 맞습니다. 일단 이름부터 지옥이죠. 말장난이 아니라 실제 존재하는 심지어 유명한 navigation 들입니다.

다른 개발자와 대화할 때 내비게이션을 이름으로 구분하기보다는 만든 회사(커뮤니티, 사람)으로 구분하는 것이 정신 건강에 좋습니다. 그간 RN이 아닌 다른 방식으로 앱을 만들어 오면서 별로 고생 안 했던 부분을 RN에서는 고생하는 것 같아 RN의 내비게이션이 지옥이라 느껴지더군요. 그럼 저는 결국 어떤 걸 쓰냐고요? 저는 react-navigation을 쓰다가 얼마 전 react-native-navigation으로 바꿨습니다.(가운데 native라는 단어가 없는 걸 쓰다가 있는 걸로… :scream_cat: )

바꾼이유를 한마디로 하자면 다음과 같습니다.

내비게이션만큼은 네이티브 컴포넌트!

react-native(이하 RN)의 공식 문서에도 나와있듯이 RN 자체에는 iOS, Android를 모두 커버하는 내비게이션 컴포넌트를 포함하고 있지 않습니다. 그렇다 보니 위에서 나열한 비슷한 이름의 다양한 3rd-party 내비게이션이 생겨났습니다. 이들을 네이티브 기반인지 js기반인지에 따라 구분할 수 있습니다.

제가 써본 두 컴포넌트 중에 하나가 바로 js기반이고 다른 하나가 native기반입니다.

  • React-navigation : js기반, navigation의 ui를 view와 애니메이션으로 직접 구현
  • React-native-navigation : 네이티브 기반, os에서 제공하는 navigation관련 네이티브 컴포넌트를 사용

이 구분에 따라 개발 및 사용성에서 다음과 같은 큰 차이점이 있습니다.

1. 화면 상단의 헤더

내비게이션의 헤더라 함은 iOS에는 navigationBar에 해당하고 Android에서는 ActionBar(ToolBar)에 해당하는 녀석입니다. iOS와 Android에 따라 제목 위치도 다르고 뒤로(Back)버튼 위치도 다릅니다. 게다가 OS버전에 따라 디자인이 다르기도 합니다. 예를 들어 iOS의 경우 iOS7에서 flat 디자인 패턴으로 바뀌었고, 최근 소개된 iPhoneX에서는 헤더의 크기와 모양이 달라졌습니다.

react-navigation의 Header는 View 컴포넌트로 네이티브 컴포넌트의 Header를 흉내 낸 것이고 react-native-navigation은 네이티브 컴포넌트 그 자체입니다. 따라서 view를 이용해 흉내를 낸 react-navigation의 경우 이러한 변화를 대응하려면 바뀐 모양을 또 흉내 내도록 구현해야 합니다. 애플이나 구글이 OS에서 이를 얼마나 섬세하게 만들었겠습니까? 애플과 구글이 만든 네이티브 컴포넌트는 터치에 대한 처리, 디자인, 성능면에서 미려하게 다듬어서 나온 결과물입니다. react-navigation은 이를 사용하지 않고 이를 흉내를 내는 것이기에 한계가 있기 마련입니다. (RN과 bridge를 이용한다는 점에서 유사한 아키텍처를 가지고 있는 Titanium의 경우를 생각해보면 Navigation 만큼은 View로 그리는 컴포넌트보다 네이티브를 활용한 컴포넌트가 사랑을 받았습니다.)

react-native-navigation의 경우 native기반이기에 별다른 것을 하지 않았는데 OS버전에 따라 OS버전 고유의 UI/UX를 가지게 되며 OS가 업데이트 될 때 추가된 속성이나 함수를 biridge를 통해 열어주기만하면 새롭게 선보인 Navigation의 기능을 어렵지 않게 쓸 수 있게 됩니다.

2. 화면을 관리하는 방법

iOS에서 한 화면을 구성하는 주체는 viewController라 할 수 있고, Android에서는 Activity라 할 수 있습니다. 이러한 화면의 전화에 있어 애니메이션 효과나 iOS swipe back같은 동작, 그리고 여러 화면이 열려있을 때의 리소스 관리 등 OS에서 알아서 효율적으로 해주는 부분이 많습니다.

그런데 react-navigation의 경우 하나의 viewController(Androd에서는 Activity)에서 화면 전환을 처리합니다. 그렇다 보니 네이티브보다는 하드웨어 리소스를 많이 사용하게되고 체감 속도가 느려지고 화면 전환 시 고려하지 않았던 키보드, 카메라 관련 부분에서 사이드 이펙트를 접하게 됩니다. (저는 화면 전환 시 키보드가 그대로 나타나 있다거나, 카메라 뷰를 닫았다가 다시 열었는데 preview화면이 나오지 않는 문제를 겪었습니다. 물론 이도 이런 저런 방법을 통해서 해결은 가능할지 모르지만 제 Titanium 경험상 네이티브 내비게이션을 사용할 때는 고민하지 않아도 되는 부분이었죠.)

react-native-navigation 좋았던 점들

그외 좋았던 점들을 간단히 나열해 보자면 다음과 같습니다.

  • 상단 Header의 버튼 지정 시 아이콘만 지정해도 터치 영역 등이 네이티브 기본 버튼처럼 넉넉히(?) 잡히는 점
  • 상단의 버튼의 press를 이벤트 형식으로 Component에서 받을 수 있는 점

그 밖의 참고 사항

  • react-native-navigation은 현재 2.0 버전을 개발 중입니다. 저는 2.0 버전으로 바로 쓸까 하다가 2.0에서는 navigator id가 생긴 것 말고 크게 api가 달라지는 것 같지 않기도 하고 무엇보다 베타 테스터가 되기 싫어서 1.0을 우선 쓰고 있습니다. 사실 아직도 2.0을 쓸까 종종 고민됩니다.(선택하고 후회 잘하는 성격이라…)
  • react-native-navigation이라고 단점이 없는 건 아닙니다. 현재 제가 발견하고 해결책을 찾지 못한 것 중에 하나는 header에 subtitle까지 지정했을 때 swipe back하면 title 역역이 왼쪽에 붙었다가 다시 가운데 붙는 일종의 튀는 현상이 보이기도 합니다. 해결책을 아시는 분은 도와주세요. ㅠ
  • 어디까지나 두 내비게이션을 오래 써본건 아닙니다. RN의 navigation 모듈을 사용하면서 자꾸 오랫동안 만져왔던 Titanium과 비교하게 되었고 이를 정리해봤습니다.
  • 이 글을 쓰도록 동기 부여를 해준 글은 wix가 왜 이런 접근을 했는지에 대해 적은 글입니다. Titanium이 이런 구조라 그럴까요? wix의 글을 보면서 맞장구를 치게 되더군요.ㅎ

(김준극) #2

저는 RN을 주로 사용하고 있는데요, 이종은 님 글을 보고 RNN을 테스트해보고 있습니다.
현재 제가 사용한 테스트 중인 버전은 1.1.236입니다.
Drawer를 설정해서 해단 스크린에서 이동은 handleDeepLink로 해결할 수 있었는데요,
한가지 Drawer를 설정하면 Home(메인) 스크린에서 스크린을 터치하고 오른쪽으로 이동하면 Drawer 'open’과 같이 스크린 이동이 되는데요,
이런 부분을 설정할 수 있는 옵션 값이 있을 것 같은데 찾지 못해서 혹시 이런 부분은 어떻게 해결하셨는지 궁금합니다.


(이종은(Jong Lee)) #3

navigator.push 할 때 애니메이션을 주고 싶지 않다는 말씀이신가요?
push에서 animated속성을 변경하면 됩니다.

this.props.navigator.push({
  screen: parts[1],
  ...payload,
  animated: false //여기
});

drawer의 animation도 비슷합니다.

this.props.navigator.toggleDrawer({
  side: 'left',
  animated: true //여기
});

(김준극) #4

navigator.push의 제어는 아닙니다.
drawer를 Navigation.startTabBasedApp 에 설정한 경우 최초 스크린에서 영역 터치 무브로 drawer가 open되는 것을 없애고 싶습니다.


(이종은(Jong Lee)) #5

drawer를 gesture 로 열지 못하도록 하고 싶으신건가요?
맞다면 disableOpenGesture 사용하면됩니다.


(김준극) #6

빠른 답변 고맙습니다.
disableOpenGesture: true 로 해결 했습니다.


(Jeff Kang) #7

으 이거 네이티브로 안쓰면 진짜 느리더라고요. 알짜 정보 감사합니다.


(Minoo Joo) #8

리액트 네이티브 입문자인데 도움이 많이 됐습니다^^
마지막에 링크 걸어주신 Wix팀의 글을 읽어보니 많은것들이 이해되지만,
리액트로 웹개발만 하다가 리액트 네이티브를 쓰려니 모르는 개념이 많네요 ㅎㅎ


리액트 네이티브
(이종은(Jong Lee)) #9

사실 이 네비게이션 경쟁은 곧 종식 될지도 모릅니다. :pray: 지난번에 리액트 네이티브 블로그에서 리액트 네이티브가 코어 부분을 다시 만든다고 할 때 기존의 문제점으로 네이티브 네비게이션을 언급했거든요. 개인적으로는 리액트 네이티브 코어에서 네이티브 네비게이션을 사용하는게 더욱 수월해지길 기대해봅니다.

Once these changes are completed, closer integrations will be possible. Today, it’s not possible to incorporate native navigation and gesture handling or native components like UICollectionView and RecyclerView without complex hacks. After our changes to the threading model, building features like this will be straightforward.

출처 : https://facebook.github.io/react-native/blog/2018/06/14/state-of-react-native-2018