제목: Yeah, redesign(Part 1)

모바일 세상에서 어떻게 리디자인에 접근할 수 있을까

나는 디자인 수석으로서, 항상 내 자신에게 이렇게 질문한다. "우리 팀이 사용자에게 어떻게 최고의 제품 경험을 계속해서 전달할 수 있을까?" 내 대답은 항상 같다. '급격하게 변하는 커뮤니티에서 변화하고 진화하는 사용자의 기호를 항상 고려해야한다.' 그러나 제품 경험을 리디자인하는 것이 방법이라면, 시작된 프로세스를 얻어내기 위한 내부 토론을 어떻게 시작할까? 제품 아이덴티티는 유지한채로 새로운 기능과 디자인의 균형을 맞춰가며 확장가능할 솔루션을 어떻게 달성할 수 있을까?

여러분도 비슷한 디자인 과제를 안고있다면, 아래 질문들의 대답을 찾아가며 이 글이 어느정도 도움이 될 수 있을 것이다.

  1. 그 사용자가 이미 사랑하고 있을때 왜 제품을 리디자인해야할까?
  2. 어떻게 데이터 주도 회사의 패이스에 맞춰가며 리디자인을 시행할까?
  3. 결과물을 어떻게 측정할까?
  4. 다음 단계는 무엇일까?

이 질문에대한 답변을 찾는데 우리 메인 제품인 Sing! Karaoke가 겪은 리디자인을 공유하고, 우리 팀이 이 방법으로 어떻게 난과을 극복했는지 보여주고 싶다.

2년하고도 6개월전에 내가 처음 회사에 들어왔을때, 각 앱(Sing! Karaoke, Magic Piano, Autiharp, Guitar)마다 배치된 팀이 하나씩 있었다. 각 팀은 디자이너 한명, 프로덕트 메니저 한명, 그리고 두명의 엔지니어로 구성된다. 서로다른 성장 속도로인해 Smule 식구중에 Sing!이 선두에있는 앱이 되었다. 회사는 앱 기반 개발 구조에서 기능 기반 구조로 초점을 바꾸기 시작했다. Sing에 기능을 추가하는데 더 많은 노력이 들어가고 디자이너들 사이에 디자인 협업이 더 많이 필요하게 되었다는 의미이다. 사업이 바뀌면서 우리는 기존의 제품 디자인과 프로세스는 팀을 키우고 사용자를 만족시키는데 요구사항이 충족되지 못했다는 것을 알았다.

리디자인을 단지 한 프로젝트에만 적용시키는게 아니라 우리 사용자와 디자이너, 프로덕트 매니저, 인지니어, 이사원들을 끌여 들여야 한다는것을 알았다. 당사자들은 리디자인의 목적을 위해 초기 단계에 얻고 리디자인이 어떻게 진행되어야하는지에대한 피드백을 받음으로써 4가지 범주에서 리디자인이 달성하고자하는 명확한 목표를 설정할 수 있게 도와준다(Have these parties buy into at early stage for the reasons of redesign and provide feedback for “how” the redesign should happen helped us set a clear goal what redesign would achieve in four areas).


  • 사용자 경험 증진하기(Improve user experience)
  • 디자인 팀을 확장가능하게 만들기(Empower design team for scale)
  • 제품 인게이지먼트 증진하기(Increase product engagement)
  • 유지가능한 공학적인 솔루션 만들기(Build a sustainable engineering solution)

1. Sing!의 사용자 경험 증진하기
Sing! 경험에 일관성과 지속성 만들기
수많은 사용자 연구에서 사용성에 가장 강력하게 기여하는 녀석 중 하나가 일관성이라는 것을 알고있다. Sing!은 많은 기능으로 즐거운 제품이다. 이 제품이 2012년도에 출시되었을때는 더 적은 기능과 작은 사용자 기본을 가졌었다. 이런 적은 기능들은 서로 다른 문맥에서 분리된 컨텐트를 표현하기위해 서로다른 칼라를 쓰는 디자인의 결과를 낳았다. 예를들어 이전 버전의 Sing!은 다양한 사용으로 'Call to Actions'를 표시하는데 4가지 이상의 칼라를 사용했다. 예전 디자인이 사용자를 즐겁게하는 목적에 맞춰져있는동안 이런 여러 칼라 CTA(wiki, 역자가 이해한바로는 CTA는 광고버튼 등을 의미함)는 새로운 사용자를 혼란스럽게 만든다는 사실을 알아냈다. 현재 사용자 경험을 증진하기위해서 리디자인은 일관적인 UI 랭귀지를 설립할 필요가 있다는 의미이다.

새로운 사용자 인게이지먼트(engagement, 참고링크) 증진하기
컨덕팅 사용자 연구(Conducting user studies)에서는, 새로운 사용자는 그들의 (다른 앱이나 제품으로부터 UI 인터랙트했던) 예전 경험을 가져와서 처음 Sing!의 인터렉션 기능처럼 동작할거라 생각한다는 것을 인지해야 한다고 말한다. 그리고 아주 중요하게도, Sing! 인터페이스가 사용자 경험에 일치하지 않았을때는 그 인터페이스를 배우고 이해하는데 추가적인 에너지가 소비되고, 이것은 새로운 제품을 관심있게 시도해보게 만들기도 하지만 생소한것을 겪어야하기도 하게 만든다. 리디자인 과정에서 개발해온 패턴을 매칭시키기위해 표준적인 UI가 증가하거나 커스텀 UI를 바꾸는 것이 사용자들에게 더 빨리 더 쉽게 제품에 친숙해지게 돕는다는 생각했다. 이렇게하여 사용자들이 빨리 더 나은 인게이지먼트의 제품을 자연스럽게 이해하는데 도움을 줄 수 있다.

기존에있던 사용자 잔존율을 증가시키기
앱과의 인터렉션에서의 비용은 육체적(physical)으로나 정신적(mental)으로 둘 다 측정가능하다. 육체적 비용은 사용자가 필요로하는 특정 목표를 달성하는데 몇 단계인지 측정한다. 정신적 비용은 사용자가 한 작업을 완료시키거나 어떤 목표 혹은 스트레스(stress)를 달성하기위해 필요한 내제적, 외부적 인식 로드를 측정한다. 예를들어 Sing!의 사용자들이 다른 사용자와 듀엣을 시작하길 원할때, 이 목표를 달성하기위해 다중 UI로 넘어간다. 이것은 컨텐트의 이해를 돕지 못하여 시간적으로나 스트레스적으로 비용이 드는 것이다. 여기에는 명확한 표준적 인터렉션과 UI 디자인의 계획과 신조로 사용자의 육체적, 정신적 비용을 줄일 것이다.




2. 디자인 팀을 확장가능하게 만들기
Sing!을 위한 새로운 폰트 만들기
Sing!은 Gotham 폰트로 시작했었다, 이 폰트는 뉴욕시티의 중세 건축에서 착안되었다. Gotham은 Smule의 제미와 기발함, 환영하는 기분을 알리기위한 훌륭한 폰트이다. 오늘날까지도 Smule의 브렌드 아이덴티티로 표현되고 있다. 그러나 Gotham은 보통 인쇄나 미디어 어플리케이션에 사용되는 폰트이다. 모바일 기기에서 폰트를 사용할때, 많은 이슈를 야기한다. Gotham은 넓은 커닝(kerning, 텍스트가 시각적으로 보기 좋도록 글자간의 간격을 조정한것)을 가지고 있고, 주어진 단어나 문장에대해 너 많은 공간을 차지했다. 모바일 기기는 제한적인 소유지(화면 크기)를 가지므로 디자이너들은 항상 그 텍스트들을 iOS와 안드로이드 둘다에서 잘 보이도록 만들어야하는 추가적인 노력을 해야했다. 그 폰트 크기는 작은 공간에 맞추기위해 여러번 줄여야했고, 이것은 사용자에게 가독성 이슈를 만들었다. Gothan에의한 또다른 이슈로는 낮은 기준선(baseline)이다. 시각적으로 중앙에 놓으려면 이것때문에 수작업을 해야했다. 이런 예시들에서 볼 수 있듯, 결과적으로 개발동안 많은 디자인 이슈를 만났다. 이제는 리니자인을 하면서 해야할 것으로서, 확장가능하고 플랫폼 표준 폰트를 잦는것이 중요한 결정사항이라는 것을 안다.

Sing!은 그 디자인 언어인 표준화가 필요하다.
디자인은 유기적(organic)이기도하고 향수를 불러일으키기(nostalgic)도한 창의적인 과정이다. 표준 UX/UI 디자인 가이드라인이 제자리에 없이는, 프로젝트에서 작업하는 각 디자이너의 미학으로 이 제품은 뒤죽박죽이 될것이다. 이런 디자인으로 계속 작업하다가는 디자인 팀에서 혼란을 만들고, 디자이너 결과물의 한계와 질이 떨어진 제품을 만들었다. 우리의 예전 Sing! 디자인 표준이 명확하게 정의되있지 않았다는걸 알았다. 이런 모호함은 디자인 비평/검토 과정을 더 지연시키고 더 힘들게 하였다. 팀에서 누구도 우리가 목표로 하고있는 디자인 표준을 분명하게 말할 수 없었을때, 모든 피드백이나 리뷰는 개신 선호에따라 판단되었으며, 결국 대부분 정당성을 입증할 수 없었다. 한 팀으로서, 사용자에게 최고의 제품과 경험을 제공하기위해서는 협력적인 노력이 들것이라는 것을 인지했다. 결국 리디자인하고 앞으로 나가기위해서는, 모든 디자인 팀원들간에 소통할 수 있는 명확한 표준이 필요했음을 깨달았다. 우리는 팀에의해 모든 제품 디자인 결정사항에대한 표준을 설정하였다.

디자인팀에서 거대한 성장은 몇가지 규칙들을 설립해야한다는 것을 알게 만들어주었다. 이 가이드라인은 IA, 레이아웃, 폰트, 칼라, 그림요소(imagery), 인터렉션을 다루는 법을 세울 것이다. 이 가이드라인은 디자이너들이 한번에 올바른 디자인 결정을 만들 수 있도록하는데, 디자인 프로세스를 절감해 많은 디자인 이슈에 적용할 수 있는 프레임워크가 될 수 있다. 더욱 중요하게도 디자인 팀은 우리의 스타일, 요소, 패턴을 문서화하여 가지고 있어야하는데, 공유되고, 중앙 저장소이고, 필요한만큼 빈번하게 업데이트되야한다. 한곳에 공유된 중심원(hub)이 있으면 디자인의 일관성을 증진시킬 수 있으며, 뿐만 아니라 디자인의 질과 양도 따라온다. 즉 디자인팀은 Sing! 리디자인으로 가이드라인을 만들어낼 필요가 있었으므로, 분리되고 개인적인 디자인을 줄이고, 외관상으로 일관적이게 남길 것이다. 이것이 우리의 목표이며, 결국 디자이너들은 세세한 아이콘으로 작업할 수 없고 올바른 명세가 무엇인지 생각할 수 없을 것이다. 대신 사용자를위한 더 창의적인 디자인 솔루션에 집중할 수 있다.

디자인팀은 규모가 확장되야할 필요가 있다
제품에 추가되고있는 기능이 많아지고 더 많은 Sing 사용자가 생기면서, 우리 디자인 팀은 협력을 성장하고 증진할 필요가 있다. 협력을위한 기본적인 틀의 작은 블럭을 만드는 공통된 이해 없이는, 팀에게 이런 성장을 유지하기위해 넣는 압력은 복잡해진 의사소통을 만들 수 있다. 우리 팀이 잘하고있다는 확신을 위해서, 우리는 디자인 접근법과 워크플로우를 모듈화시켜야 한다는 점을 알았다. 이 말은,  리디자인팀이 작은 블럭을 만들며 디자인을 만들어야할 필요가 있다는 뜻인데, 이 블럭은 리디자인의 기초가 되고 모든 디자인 노력(effort)이 될것이다. 이렇게 각자가 블럭을 만드는 것은 디자이너들이 쉽게 협력할 수 있게 해주고 필요에따라 작업을 쪼개게 해준다. 게다가 새로운 디자이너가 오면, 기존의 팀원이 프로젝트를 이끌기위해 블럭을 만드는 것을 활용할 수 있고, 새 맴버를 위한 일정을 명확하게 정할 수 있게 된다.




3. 제품 인게이지먼트 증진하기
새 사용자에게 내장된 경험 증진하기
새로운 사용자가 새 앱을 쓰려고 할때, 한번에 두가지를 배우는데, 첫째로 앱의 기능이고, 둘째로 이 기능을 어떻게 쓰는지이다. 명확하고 표준화된 UI/UX 디자인이 없으면 사용자는 앱에서 개별적인 인터페이스 요소를 완전히 소화하지 못할 것이다. 사용자에게 인터페이스 디자인을 소개하는 것보다 제품 기능 사용에대해 초점을 맞추기 때문에, 우리는 새로운 사용자의 기대를 이해하고 그들에게 명확하게 유용한 정보를 전달해야했다. 전반적으로 새 디자인은 앱의 혼란스러운 부분을 간단하게 만들어야했고, 사용자들이 새 기능을 시도하고 인터렉트함에 편안하도록 해주어야 했다.

사용자 잔존율(retention)을 증가시키기
Smule에서는 새 사용자가 앱을 처음 경험하고나서 이후에 얼마만에 다시 돌아오는지(예를들어 2일이나 7일같이) 정의하여 사용자 잔존율을 면밀히 모니터링한다. 만약 사용자의 첫번째 경험이 좋지 않았다면, 이틀연속 다시 돌아오기 힘들 것이다. 사용자 연구를 통해 알아내었는데. 사용자들이 처음하는 시점에서 기능을 찾아내면 많은 기능들을 즐긴다. 혹은 이미 있는 기능들을 요청했다. 이런 발견으로부터 우리 디자인 안내가 사용자의 유지를 잡지 못하고 있음을 의미했다. 만약 디자인이 사용자의 생각속에 있는 기능을 어디서 찾고 어떻게 접근하는지 알려주지 못한다면 사용자들은 혼란에 빠지고 Sing을 계속 사용하고 싶다는 흥미를 잃어버리게 될것이다. 리디자인으로 사용자 잔존율과 제품 사업 목표를 만족시키는 더 나은 안내를 고안해내야한다.

개발과 배포 사이클 증진하기
2014년도에 리디자인을 고려하기 시작할때부터 iOS와 안드로이드에서의 제품 기능을 동일하지 않았다. Sing! iOS는 Sing 안드로이드보다 더 많은 기능이 있었다. iOS와 안드로이드간의 일관성 부재는 디자인 팀에게 일거리를 두배로 주고 개발 사이클을 지연시켰다. Sing!은 우리가 리디자인을 생각하기 시작할때부터 많은 사용자들이 생겼었다. 제품 디자인과 개발 사이클에 추진력과 속도를 높히고 싶었다. 이런 마음을 가지고 우리는 내부 디자인 팀의 워크플로우와 효율을 올리는데 리디자인이 필요하다는 것을 알았다. 리디자인으로 디자인과 개발 시간을 50%나 줄일 수 있었고, 이것은 현재 리소스로 새로운 기능을 테스트하고 배포하는데 더 많은 기회를 줄 것이다.




4. 유지가능한 공학적인 솔루션 만들기
개발 프로세스 증진하기
부조화스러운 UI는 사용성 이슈를 만들 뿐만 아니라 디자이너와 엔지니어들에게 추가적인 작업 과중을 안겨준다. 예를들어, 디자이너들은 한 아이콘일지라도 여러 시나리오에서 사용될 여러 칼라와 사이즈로 아이콘들을 만든다. 엔지니어에게 이 아이콘들을 올바른 화면에 놓게 하기위해 아이콘들을 만들고 명세하는데 디자이너들은 추가적인 40% 시간이 더 든다. 엔지니어도 이 명세를 따르고, 각 아이콘이 올바르게 위치하도록 커스터마이징된 코드를 짜야한다. 말은 쉬워보이지만 다양한 화면 크기나 플랫폼(iOS와 안드로이드)에 부딪혔을때 이 프로세스는 끔찍해진다. 엔지니어와 이야기하고나면 디자이너와 엔지니어 모두 더 나은 방법으로 서로 협력하고 싶어한다. 여기서 리디자인의 필요성에대한 서로다른 관점이 나온다. 디자이너와 엔지니어가 어떻게 효율적으로 제품을 설정하고 만들지에대한 체계적인 방법을 만들자.

제품 개발 품질을 증가시키기
디자인 QA를 하는것과 올바르게 구현되었는지 확인하는 것은 디자이너의 책임이다. 디자이너와 엔지니어에게 가장 비극의 순간은, 디자인 부분을 변경하다가 생긴 디자인 버그를 엔지니어가 수정하는 것인데, 여기서 또다른 버그가 만들어진다. 이때문에 엔지니어는 디자인 버그를 고치는데 더 많은 시간이 들고, 그 구현이 버그없이 디자인과 일치한다고 보장할 수 없었다. 앞단에 나오는 모든 디자인 버그를 해결하기위한 리디자인을 요구하는것은 비현실적이라는 것쯤은 우리도 안다. 그러나 마진을 어떻게 줄것인지, 아이콘 사이즈를 어떻게 만들것인지, 누른 상태는 어떻게 적용시킬지 등에 대한 표준의 중심 디자인 가이드라인을 만들어서 예전과같은 일이 일어나지 않게 할 수 있다.

세계 현지화 준비하기
리디자인에대한 생각을 시작할쯤에 Sing은 US 중심의 앱에서 다국적인 제품으로 옮겨가고 있었다. 세계 사용자에게 소통하기위해, 우리는 12가지 언어에서 20가지 언어로 현지화 시켜야 했다. 영어기반 앱을 외국어로 적용시킬때 UI는 쉽게 망가질 수 있다. 예를들어 영어와 독일어/러시아어를 비교해보면 같은 의미라도 독일어/러시아어가 더 많은 문자로 표현된다. 영어 레이블에 맟춰놓은 제한된 공간에서는 독일어와 러시아어가 제대로 작동하지 않을 수 있었다. 공간을 설정하고 올바른 계층을 적용시는 규칙을 명확하게 하지 않고서는 현지화된 언어가 작은 사이즈로 표시되거나 짤리게 될 것이다. 언어 하나하나 이 이슈를 해결하면서 엔지니어와 QA에 어마어마한 수고가 들어갔다. 리디자인을 통해 미래에는 서로다른 모든 언어를 최적화할 수 있는 유지가능한 솔류션을 찾아야한다.



이 블로그는 공부하고 공유하는 목적으로 운영되고 있습니다. 번역글에대한 피드백은 언제나 환영이며, 좋은글 추천도 함께 받고 있습니다. 피드백은 

으로 보내주시면 됩니다.



WRITTEN BY
tucan.dev
개인 iOS 개발, tucan9389

,

요즘 많은 사람들이 그들의 다음 그들의 다음 모바일 앱 개발에 사용할 플랫폼으로 리액트 네이티브에 다가가고 있다. 이것은 사소한 일이 아니다. 당신의 소프트웨어 개발 플랫폼을 바꾸는 것은 높은 초기 설정 비용을 수반하여 매일 프로그래밍 작업 플로우에 깊숙히 영향을 줄 것이다. 또한 지금까지 만들어놨던 모든 요소들을 전환하는 것도 가장 비싼 비용의 결정 중 하나이다.

아마 더 중요한 것은, 당신의 소프트웨어 개발 플랫폼 또한 소프트웨어 엔지니어로서 당신을 이루는 것 중 하나이다. 소프트웨어 개발 플랫폼은 한 언어만 사용하게하고, 어느 특정 아키텍처를 우선시하며, 특정 툴을 요구하고, 당신을 그 모든 생태계와 플랫폼의 개발자 커뮤니티와 결혼시켜버리도록 지향(혹은 강요)한다.

페이스북은 당신이 전환해오기를 바란다.

그리고 리액트 네이티브 팀의 꾸준하며, 공들인 노력은 그 야망과 같다. 그들은 우리의 전통적인 Xcode/Swift/Objective-C 스택을 대체할 수 있는지 고려해야하는, 너무 근본의 소프트웨어 개발 플랫폼을 만들어왔다.

이것이 실용적인 변화일 수 있을까? 내가 읽어온 리액트 네이티브에 관련된 블로그 포스팅들은 오히려 피상적인 접근을 알려주었다. 그것의 장점과 단점에대한 깊이있는 접근은 없고, 여러분이 누군가로부터 소프트웨어 개발 플랫폼을 바꿔라고 설득당한 사람이라고 가정하고 이야기를 시작한다.

지난 몇달동안 리액트 네이티브를 사용하면서, 나는 이것으로 개발할 수도 없고 이것을 사용하기를 추천하지도 않을 플랫폼인 것으로 결론이 나왔다. 이 글의 목표는 Swift 개발에서 리액트 네이티브로 전환하는 것에 대한 빈틈없는 평가의 찬반을 알려주는 것이다. 그리고 그 전환에대해 반대하는 이야기도 할 것이다.

찬성
선언 스타일(Declarative style)
리액트 네이티브와함께 작업할때 기뻤던 한가지는 UI 프로그래밍의 선언 스타일이었다. 리액트 방법으로 하면 UI는 함수의 상태와 프로퍼티들이다. 반면 Cocoa Touch에서는 UI를 명령적으로 짜야한다.

아래 예제가 내가 말하는 바를 설명해 줄 것이다. 화면 왼쪽 상단에 작은 사각형을 넣고 싶다고 가정하자. 이 작은 사각형은 사용자가 연결되있을 때는 빨강, 연결되지 않을때는 초록을 표시한다.

아래는 우리가 일반적으로 iOS에서 어떻게 했는지 보여준다.

명령형 스타일에서는 UI를 갱신하기 위해 이 모든 단계를 명시해주어야한다. isConnected가 바뀌었는지 듣고 있어야 하고, 뷰에 일치하게 갱신해야한다. 우리는 iOS에게 어떻게 상태를 컴퓨트할지 말해줘야한다.

이제 리액트의 선언 방법과 비교해보아라.

간단하게 어떻게 여러분의 앱이 주어진 점을 보여주는지 표현했고, 리액트는 데이터 갱신때마다 자동으로 모든 UI 갱신을 관리해줄 것이다.

리액트의 선언 스타일은 뷰의 render() 메소드로 작용하여 여러분의 UI를 묘사하개 해준다. 리액트 프레임워크는 상태의 모든 갱신을 다시 랜더링하도록 해준다. 여러분의 데이터 갱신(backgroundColor의 갱신이 일어날때)은 자동으로 UI 갱신으로 이어진다.

이렇게하면 모델의 갱신에대한 응답에서 손수 뷰를 갱신하지 않앋 되게 해준다. 여러분이 이 책임으로부터 벗어나고 싶든 아니든, 리액트는 당신의 설명에따라 갱신 관리를 보장해주는 점은 매우 좋은 점이며, 여러분은 더이상 isConnected 변수에대한 프로퍼티를 관리할 필요가 없다. 당신이 갱신한 모든 것은 상태이다.

또한 UI 요소들이 결국 클래스의 객체가 아니라 함수인것처럼 생각하게 될 것이다. 그것들은 상태를 받아서 UIKit 오브젝트로 랜더링한다. Component의 역할은, 요청이 들어왔을때 예상되는 상태에서의 그 자신을 반환하는 것이다.

UI에 대해서는 유용한 방법이라 생각한다. 그리고 MVC로부터 좋은 발전이다. 뷰는 단지 그 자체를 보여주는 역할만 하고 데이터를 관리하지는 않으며, UIViewController에서 시작하기를 좋아하고, 뷰와 컨트롤러 사이 관계에 밀접하게 붙어있는 장님으로 바뀐다.

빠른 반복
리액트 네이티브의 매력은 단지 지적임이 아니다. 프레임워크는 실용적이기까지 할 것이다.

여러분이 리액트 네이티브에서 프로그래밍을 하면, 프레임워크는 당신이 작업하고 있는 자바스크립트 코드를 서브하는 로컬 서버를 만들어 줄 것이다. 앱을 만들면 iOS 시뮬레이터나 기기에서 돌려보고, 리택트 네이티브는 자바스크립트로 만든 모든 변화를 앱에 반영하게 해준다.

여러분에게 두가지 옵션이 있다.
  • 실시간 리로딩(Live reloading)은 당신이 그 파일에 수정하고 저장할 때마다 앱을 리로드할 것이다. 기본적으로 시뮬레이터로 전환하는 것을 막고 ⌘ + R을 누르지 않아도 된다.
  • 핫 리로딩(Hot reloading)은 앱 전체를 리로드하지 않고 당신이 수정한 부분만 리로드한다. 당신이 네비게이션 스택 깊숙히 테이블 뷰 셀의 UI를 작업하고 있었다면, 그 바뀐점을 보기위해 시작화면에서 셀까지 찾아가지 않아도 된다. 그리고 컴포넌트는 이미 그 안에 있던 상태로 그대로 있을 것이다. 이것은 WYSIWYG 프로그래밍 경험(WYSIWYG programming experience)이다. 앱을 위해 Xcode가 결코 제공하지 않았던 호화로운 기능이다.

나는 앱을 시작에서부터 보여주고 싶은 ViewController마다마다 AppDelegate에 디버그 메소드를 넣었던 것을 기억한다. 그리하여 앱을 켤때마다 손수 그 페이지를 찾아가고 싶지 않아서 코드로 그 페이지를 찾아가게 했었다. 핫 리로딩은 나를 동굴에서 나온 사람의 기분으로 만들어 버렸다.

리액트 네이티브의 피드백 루프 주기는 넋이 나갈 정도로 낮다. 앱에서 파일을 저장하고 그것을 눈으로 보기까지 1~2초정도 걸린다. 이것은 Xcode에서 일반적으로 우리가 사용한 빌드&런보다 10배 작게 든다.

이것은 방송처럼 코드 갱신을 가능하게 해준다. 자바스크립트 코드에서의 어떤 변화라도 앱이 제품으로 출시되어 있는동안 사용자에게 즉시 적용될 수 있다.

크로스 플랫폼
품위없고 서튼 이야기를 기억한다.

"훌륭한 앱이군요! 안드로이드에서도 동작하나요? [...]오, 안드로이드 버전은 언제 배포할 계획이시죠?[...], 오."

이제 코드베이스가 수백만 개의 추가 장치에서 실행될 수있는 앱을 만들 수 있으며 아웃 리치를 몇 배 증가시킬 수 있다.

그리고 여러 플랫폼에서 동일한 코드가 더욱 확실하게 같은 모습과 같은 동작의 앱을 만들 것이라 확신한다.

같은 코드베이스로 여러분 앱의 안드로이드 것을 만들 수 있고, 그래픽적으로든 기능적으로든 iOS쪽과 동등해지게 한다.

크로스 플랫폼 프레임워크의 명백한 장점은 언제나 시장 개발, 통합 코드베이스 및 앱의 코드베이스를 유지하는데 필요한 통합 기술 세트이다.

반대
불확실한 로드맵
리액트 네이티브를 사용할 때 생기는 중요한 걱정은 그 프로젝트에서의 장기적인 보장이 없다는 것이다. 

만약 이 프로젝트가 네트워크 라이브러리나 CGPath를 그리는 SVG같은 부가적으로 합쳐서 쓸 수 있는 요소라면, 장기적인 지원이 두번째 걱정으로 밀려날것이다. 리액트 네이티브 개발자들이 그만둬버리거나 리액트 네이티브 개발 속도가 마음에 들지 않으면, 대충 비슷한 라이브러리로 대체하거나 아니면 내 스스로 고쳐 쓸수도 있었을 것이다. 이것은 큰 작업이 될지도 모르겠지만, 이러나저러나 거대한 일은 아니다. 한 라이브러리를 쓸 수 없게 되었다해서 프로젝트 전체가 붕괴되지 않음을 보장하기 위해선 모든 나의 써드파티 라이브러리/CocoaPods을 내 프로젝트에서 충분히 떼어놓으면 된다.

그러나 리액트 네이티브는 CocoaPod처럼 부가적으로 쓰는 요소가 아니며, 단지 SDK도 아니고, 단지 라이브러리도 아니다. 이것은 완전히 소프트웨어 개발 플랫폼이다. 내 앱이 이것에 "아주 붙어있다"고 말하는 것은 너무 조심스러운 표현이고, 애 앱이 그것에 완전히 의존적이라고 말해야한다. 만약 페이스북이 리액트 네이티브 유지보수를 중단하면, 그것을 쓰고 있던 내 앱은 썩어갈 것이고, 내가 할 수 있는 "리액트 네이티브 대체물"은 없을 것이다. 만약 그것을 내 스스로 개발하려 한다면 리액트 네이티브 소스에도 친숙해야할 뿐 아니라, React.js 코드베이스, 네이티브 CLI 툴, JavaScriptCore에도 익숙해져야 할것이다. 커뮤니티가 이 프로젝트의 생존을 보장해줄까? 아마-만약 그렇게 되버리면 우리가 사용할 수 있을 정도의 개발 속도가 나지 않을 것이다.

깃헙 저장소에서는 2주에 한번 정도 건강한 속도로 리액트 네이티브 릴리즈가 되고있다. 두개의 분리된 것과 복잡한 소프트웨어 개발 플랫폼을 타겟으로 하는 소프트웨어 개발 플랫폼에는 나쁘지 않다. 페이스북이 오늘 약속할지도 모르지만, 지속적인 네이티브를 유지하기위한 장기간의 약속을하지 않았다. 회사에서는 이 프로젝트에서 손을 떼지 않을 거라는 어떠한 보장도 하지 않고 있다. 가까운 미래뿐만 아니라 여러분의 앱이 살아있는 동안에 말이다. 다른 말로는, 현재 시점에서 리액트 네이티브가 iOS11이나 iOS12에 호환될거라는 보장은 어디에도 없다는 것이다.
여기서 다음년도로!
2016년 4월 이후 공식적인 리액트 네이티브 블로그 포스팅은 종료되었다. 그 이후엔 어떻게 되었을까? 그것에대해 페이스북은 걱정없이 침묵만 지키고 있다.
우리는 곧 계획을 발표할 것이다-Konstantin
2015년 12월에 리액티브 팀이 말한 것이다. 이 계획이란것은 아직도 발표되지 않고 있다. 확실히 리액트 네이티브의 페이스북 장기간 비용 분석 결과는 당신이 생각한 만큼 멋지게 보이지 않는다.

다시 말하면, 우리는 개별의 CocoaPod에대해 이야기하는게 아니라, 여러분의 코드가 실행될 수 있는 유일한 플랫폼에대해 이야기하고 있는 중이다. 굉장히 장기적인 시각으로 다뤄야할 중요한 문제이다.

명백히 위압하는(Patently daunting)
리액트 네이티브는 복제를 허용하는 BSD-스타일 라이센스와함께 페이스북의 추가적인 특허권 문서(Additional Grant of Potent Right)를 만들었다.(버전2) 이 파일을 넣은 페이스북의 입장은 분명하지 않고, 이 파일 자체도 불분명하다.

양극의 문서이다. 문서가 끝나자마자 리액트 네이티브를 사용하기 위해서는 "perpetual(영속의), worldwide(널리), royalty-free(무료저작권), non-exclusive(독점불가능한), irrevocable(변경불가능한)" 라이센스를 따라야한다고 한다. 아래 조항들을 제공받으면서 말이다.

The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates, (ii) against any party if such Patent Assertion arises in whole or in part from any software, technology, product or service of Facebook or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software.

나는 변호사에게 이것을 명확하게 해달라고 직접 물어보았다(여러분이라도 그렇게 할 수 있었을 것이다). 그 변호사 말에 따르면 이 조항은 다음으로 요약된다. 내가 만약 페이스북에게 특허권 위배를 주장하며 소송을 걸면 리액트 네이티브를 사용하는 라이센스가 즉시 사라질 수 있다.(아래 Appendix에서 그의 더 세부적인 설명을 인용했다)

실제로는 특허권으로 페이스북으로 고소하지 못하게 하는 것처럼 보였다. 이런 의미에서, 이것은 페이스북이 내 특허권을 침해할 수 있는 기회를 주는 것처럼 보였다.("당신이 여기에있는 훌륭한 양자 물리학 기술은 당신의 앱에 나쁜 일이 생길 경우 부끄러운 일이 될 것입니다.")

위 설명이 비판적이라고 생각할지도 모르겠다. 그러나 소프트웨어 라이센스와 특허권을 평가할 때는 비판적으로 해야한다. 알고리즘이 최악의 시나리오에서 얼마나 잘 동작하는지 그 효율을 평가한다. 똑같은 이유로서 소프트웨어 라이센스와 특허권도 그렇게 평가해야한다고 생각한다.

리니어 서치(linear search) 알고리즘은 타겟값이 리스트의 첫번째로 일어나는 시나리오에서는 최적화된 동작을 할 것이다. 그 이유 하나로, 모든 시나리오에 리니어 서치 알고리즘을 사용하라고 나를 설득하기엔 만족스러운 이유가 아니다. 만약 타겟값이 리스트 마지막에 있을 수 있다면, 내 리니어 서치 알고리즘의 평균 퍼포먼스는 굉장히 나빠질 것이다.

비슷한 맥락에서, 페이스 북이 내일 일련의 IP를 침해하는 것이 가능하고 React Native를 사용하기위한 라이센스를 취소함으로써 내측으로부터의 보복을 처벌 할 수 있다면, 페이스북이 오늘 일련의 IP 침해를 하지 않았다는 사실은 나를 조금 안심시킨다.(원문: Likewise, the fact that Facebook happens not to be a serial IP infringer today reassures me little if it is possible for Facebook to become a serial IP infringer tomorrow and punish any retaliation from my side by revoking my license to use React Native.) 만약 내일 페이스북이 내 IP를 침해하고(그러나 그것이 내 소프트웨어와 관련은 없다) 그들에게 소송을 걸면,  페이스북에게 내 앱에서 리액트 네이티브를 빼내게 만들 기회를 주는 셈이 되버린다.

내 앱이 그 플랫폼에 의존적인 것 뿐만 아니라 영리한 내 프로퍼티들까지도 위험하게된다.

iOS 앱들은 완전히 애플의 재량으로 앱스토어에 들어간다. 나는 쉽지 않은 느낌을 두배로 느끼고 싶지 않다.

명백히 침묵하는(Patently silent)
위의 해석이 정확한가? 최악의 시나리오 가능성인가? 이런것들을 걱정할 만큼 좋은 이유가 있는가? 걱정하지 않아도 될 좋은 이유가 있는가?

수많은 깃헙 이슈와 포럼 포스팅에서, 그들의 법률 부서가 이런 조항 때문에 리액트나 리액트 네이티브를 쓰지 마라고 조언한다고 이야기해왔다. 볍률 부서가 없는 개발자들에게는 유감스럽게도 이 문제들이 모호하게 남아있다.

좀 더 걱정스럽게도, 페이스북은 이 문제를 더 명확하게 하기 위한 근본적인 노력을 해오지 않고 있다. 2015년 페이스북 오픈소스 블로그 포스팅에서는 이러한 "혼란"에대해 인정했고, 기꺼히 추가적인 특허권 문제에대해 명확하게 할것이라 알렸었다. 깃헙에서 그것과 연관된 5개의 이슈 이후에도 그 불분명함은 사라지지 않고있따.

여러 페이스북 개발자들이 이 이슈에대해 응답해오고 있는데, 그들이 적어놓은 것에는 안심될만한게 하나도 없으면서 그것을 명확하게 하는 동안에 개발자들을 안심시키려고 노력하고 있다. 그들 중 한명은 Reddit과 HackerNews에있는 이 이슈에대한 토론 링크를 주기도 했었다(도움이 되지 않을 뿐더러 오해시키기까지 했다).

이것은 해석학과 추측의 작업으로 바뀌어버렸다. 페이스북은 리액트 네이티브 라이센스를 취소 할 수 있을까? 그렇다면 어떤 조건에서?

자바스크립트
Swift에서 리액트 네이티브로 전환할때 생기는 심각한 부정적인 면은 기술적 역행이다. 여러분은 자바스크립트에 적응하고 사용해야하는데 이 언어는 다음과 같은 특징을 담고있다.
  • 기술적으로 불완전함
  • 언세이프
  • 늦은 발전
왜 그렇게 말하는지 보자.

여기 이후에 예제에 나오는 모든 자바스크립트 코드는 ES2016에 유효하다.

자바스크립트의 결점
내가 좋아하는 법퍼 스티커에서 하는 말이다.
안전은 사고가 없는 것이다(Safety is no accident)
처음 봤을땐, 이 말은 중의적이었다. 우리는 안전의 정의를 사고가 나지 않는 것과 여러 안전장치 제품의 제안으로 알고 있다.

자동차에 안전벨트나 에어백이 탑재된 여러 안전장치의 제품은 안전하다고 할 수 있는가?

물론 대답은 같은 조건에서 둘 다이다.

운전자는 수많은 안정장치가 탑재된 차를 더 선호할 수 있다. 운전하기 어렵게 만들지라도 막을 수 있는 사고는 최대한 줄일 것이다.

비슷한 의미에서, 프로그래밍 언어는 프로그래머 에러에 대비한 안전장치를 제공할 수 있다.

수많은 운전자가 생산성을 위해 안전벨트를 착용하지 않고 운전한다는 사실은 옳바른 주장이 아니다. 비슷하게, 수많은 자바스크립트 개발자들이 생산성을 위해 태생의 언세이프 언어를 쓴다는 것도 옳바른 주장이 아니다.

프로그래밍 언어에서 안전의 중요성은 iOS 개발 툴이 진화하고 있는것의 진가를 인정하는 것이기도 하다.

오토 레퍼런스 카운팅이 Objective-C에 처음 나타났을때, 여러분의 iOS 프로젝트에서 그 옵션을 끄고 작업했을 수도 있다. 왜 ARC를 끄는게 나쁜 생각이었을까? 그 이유는, 이제 컴파일러가 당신의 오브젝트 라이프타임 계산을 할 수 있게 되었는데, 당신이 계산하는 것보다 더 빠르게 해준다. "컴파일러가 당신보다 더 똑똑해졌다"는 진언이고, 레퍼런스 카운팅에 관해서는 확실해졌다. 결과적으로 EXC_BAD_ACCESS 런타임 크레쉬를 줄였다는것을 알게되었을때 얼마나 만족했었는지 기억한다.

Obejctive-C는 한 변수 타입을 id로 설정할 수 있는데, 이것은 "어떤 것이든 모든 타입"의 의미이다. 그러나 컴파일러가 막을 수 있는 크레쉬임에도, 이러한 습관때문에 런타임 크레쉬가 일어날 수 있다. 컴파일러가 해결할 수 있는 문제라면, 컴파일러가 해결하게 놔두고 당신은 다른 문제를 해결하러 가면 된다.

여러분은 unrecognized selector sent to instance 크레쉬를 기억할 것이다. 응답하지 않는 오브젝트에 메소드를 호출할 때 생기는 크레쉬이다. 타입에러. 내 버그에서 3번째이다.

당연하게도 Swift를 사용하고나서 나의 첫 반응은 "Objective-C에서 런타임 크레쉬를 막고 싶었던 누군가가 만들었구만"이었다.

Swift는 안전하다. String을 받길 예상한 함수에 Int값을 넣도록 컴파일러가 허용하지 않는다. 사실 컴파일러가 타입 추론을 할 수 없었다면, 명시적으로 그렇게 할 수 있었을 것이다. 

그러나 자바스크립트는 프로그래머 에러에 대비한 안전장치가 부족하며, 여러분의 루틴에서 런타임 크레쉬를 막아야하고, 프로그래머 에러를 막아야한다.

타입 에러
자바스크립트는 변수나 함수에서 파라미터의 타입을 정해주지 않는다.

어떤 변수라도 언제든 무엇이든 될 수 있다.

자바스크립트는 class, typeof, instanceof와같은 키워드로 타입과 클래스 개념이 있다고 믿게 만든다.

여기서 우리는 다음을 보자.
  • 자바스크립트에서의 "class", "type", "instance" 개념은 주요 프로그래밍 세계에서의 개념과 완전히 다르다.
  • 자바스크립트에서는 타입을 너무 신뢰할 수 없게 정의해서, 이것들이 유용한 용도를 제공하지 못한다.

이  unrecognized selector sent to instance 크레쉬가 기억나는가? 이것이 이제 여러분 곁을 떠날것이라 생각하는가? 아래에는 리액트 네이티브의 것들이 있다.


옵셔널 결핍
Objective-C 코드(혹은 다른 수많은 오래된 언어)에서 엄청나게 많은 양의 버그들은 프로그래머가 부주의하게 nil에다가 메소드를 호출해서 생긴다.

리액트 네이티브와 자바스크립트 세계에서는 아래 에러를 종종 볼 수 있다.

그리고 이론적으로나 실무적으로나 막을 수 있다.

Swift는 옵셔널을 만들어냄으로서 이 문제를 해결했는데(옵셔널이란 nil일 수도 있고 값이 들어있을 수도 있는 타입이다), 이것을 사용할 때는 여러분에게 강제로 nil 체크를 거쳐서 사용하게 만든다.

함수 기호(function signature)의 결핍
자바스크립트에서는 함수가 리턴타입을 가지고 있지 않으며, 이 함수가 어떤 타입을 반환할지 모르거나 함수가 어떤것이든 반환할 수 있다.

좀 더 재미있게 만들어보자. 자바스크립트에서는 어떤 식이든 어떤 함수에의해 어떤 시간에든 계산될 수 있다. 자바스크립트 표준 라이브러리에 있는 map과 parseInt 함수를 사용한 예제를 생각해보자. map은 아마 Swift의 map과 동일한 것이고, parseInt는 문자열을 숫자로 파싱해주는 함수이다.
parseInt 함수는 2개의 파라미터(val, radix)를 받는데 반해, map은 3개의 파라미터(currentValue, index, array)를 보내기 때문에 이런 엉망의 결과가 생긴다. 이런것들이 여전히 합법적인 자바스크립트이다(일부 사람들이 함수형 프로그래밍 언어에 유용할것이라고 생각하는 언어).

불변성
자바스크립트가 지원하는 불변성은 매우 안 좋다.

const 연산자가 있는데, 이것은 기본타입(primitive)이 바뀌지 않는 것을 보장하는데 도움을 준다. 그러나 기본타입이 아닌 나머지 모든 것은 젤리처럼 유연하다.

유일한 복사? 아니다. 어떤 유일한 객체라도 언제든지 여러분의 앱에의해 수정될 수 있다. 멀티스레딩에 행운을 빈다. 정말로.

앱 개발을 힘들게하는 많은 것들은 가변을 쫓고 상태를 유지하는 것이다.

페이스북의 Immutable.js 문서에서 말한 내용이다(자바스크립트에서 불변 데이터 구조를 만들기위해 설계된 프레임워크이다).

그러나 아래는 리액트에서 어떻게 불변성을 만드는지이다.

이 컴포넌트에 넣는 인풋을 props라 부르는데, "properties"의 준말이다. 그들은 JSX 문법으로 속성들을 보낸다. 여러분은 이것을 컴포넌트에 불변할 것이라 생각할 수 있는데, 이것은 절때 this.props에 덮어 씌울 수 없다.

여러분은 상태를 바꾸지 말자고 공손히 물어본다. 그렇다 위 글은 리액트 네이티브 문서에서 가져온 것이다.

배열을 믿을 수 없다.
여러분은 배열이 "행과 열로 된, 비슷한 객체들의 질서정연한 배치"라 생각하는가? 아래를 보고 다시한번 생각해보아라.
자바스크립트에서 배열은 우리가 원래 배열이라 부르는 그것보다는, 보통의 자바스크립트 객체에 더 가깝다. 정확한 수서성의 결여와 가변성은 잘 동작하기 힘들게 만든다.

에러 핸들링하기 힘들다
자바스크립트에서는 경고 없이 런타임이나 예외를 던지는 함수를 만들 수 있다.
예외로 당신이 원하는 무엇(문자열, Date, 함수 등)이든 던질 수 있다. 팀원의 코드를 잠제적으로 크레쉬할 수 있다는 표시를 함수에 한다던가, 예외의 과정이 어떻게 되는지 명시할 메커니즘이 따로 없다. 문서에서는 대신에 if문을 사용하라고 권장한다.

당신의 예상하지 못한 예외 처리를 다루기 위해서는 마지막 라인의 방어로 예외를 남겨놓는게 최고이다. 그리고 예상되는 에러를 컨트롤 플로우 문으로 관리하기에도 최고이다.

디시멀(Decimal)을 지원하지 않는다.
하드웨어에서 대부분의 소수 자릿수들은 이진수로 정확하게 표현되지 않으며, 많은 프로그래밍 언어(자바스크립트와 Swift를 포함한)는 종종 수학적으로 잘못된 소수 계산을 내놓을 것이다.
이것이 왜 다른 언어의 표준 라이브러리가 소수 자릿수를 지원하는지 이유이다(예를들어 Swift에서는 Decimal을 사용할 수 있다). 자바스크립트에서는 서드파티 라이브러리나 여러분이 직접 만든 코드에 의지해야한다.

믿지 못하는 수학
초등학교 산수에도 주의를 기울여야함을 기억해라. 자바스크립트는 0과의 관계가 복잡하며 이것은 숫자가 아니다.

언세이프한 초기화
자바스크립트는 속성을 초기화 할 필요가 없으므로 객체를 만든 후 모순된 상태로 둘 수 있다.

if 다음에 선택적으로 가능한 커리 중괄호(curly brace)
if문 뒤에 커리 중괄호는 선택적이다.
여러분의 컨트롤 플로우 문에 모험의 취향을 추가한다.

모호한 커리 중괄호
프로그래머의 의도가 정확하게 추론된 것이 아니라면, 이 언어는 커리 중괄호를 선택적으로 할 수 있게 놔두지 않는다.

fallthrough 전환
switch  절에서 break를 깜빡했다면, 아래로 쭉쭉 떨어질 것이다. 또한 Swift에서는 케이스 철저성을 확인하지 않아도 된다.

어떤것이 '무(없음)'일까? (What's nothing)
 모든 의도나 목적에서 null이 아닌 것이 무가 될 수 있다. 도움이 되지 않는 구별이다.

그리고 변수에 어떤 데이터가 담겨있는지 아닌지 알고 싶다면 어떨까? 음, 확인이 너무 거추장스럽게 null과 undefined 둘 다 체크해야한다.


빈약한 표현력
  • 열거형이 없다. 연관타입을 가진 열거형은 말할것도 없다. 신뢰성 높은 상태 표현에 행운을 빌 수 있을까.
  • guard문이 없다.
  • 제네릭이 없다.
  • 컨트롤 플로우문의 표현력을 늘리기위한 where이 없다.

지극히 느린 진화
ES2016 때 자바스크립트에 새로 추가된 기능을 보라.
1. 배열을 위한 includes 메소드
배열이 특정 값을 가지고 있는지 확인한다. 아래에 어떻게 사용하는지 나와있다.
이건 사용하지 말자.
2. **연산자
지수 연산에 사용하기위한, a**b는 Math.pow(a, b)의 축약이다.

한번 생각해보면, 파이썬의 **연산자는 파이선1에 있었고, 루비의 **연산자는 20년도 전에 있었던 연산자이다.

따라서 자바스크립트는 이 기본적인 산수 연산자와 배열을 위한 꽤 제한된 맴버쉽 체크 메소드를 추가하는데 20년이나 걸렸고, 이 특징이 한 해중에 가장 의미있는 것이었다.

Flow로 구조받자!(Flow to the rescue!)
Flow는 위의 수많은 불평으로부터 내놓은 페이스북의 대답이다. 이것은 자바스크립트를 위한 정적 타입 체커이고, 여러분 코드에서 변수의 타입을 추론하고 추적할 수 있는 능력이 있으며, 여러분에게 일어날 운명(옮긴이: 실행되었을 때 일어날 오류)을 경고한다.

위에서 보았던 함수 기호의 결핍으로부터 나온 문제의 예제를 다시 보자.(number가 들어오길 예상한 divideByFour 함수는 문자열을 받는다) 여기엔 Flow가 이것을 어떻게 다루는지 보여준다.

함수 기호 부재 때문에 생기는 많은 문제를 고쳐준다.

제네릭 배열에도 동일하게 할 수 있다.

Flow는 nullability를 잘 다룰 수 있게해주고, 값이 null이되면 안되는데 null일 수 있을때 여러분에게 경고를 띄워 줄 것이다.

만약 j가 string으로 가정하지만, 언제든 null이 될 수 있으면, Flow는 그 사실을 우리에게 적절하게 알려주려 할 것이다. 따라서 인자로 string을 받되 null이면 안되는 곳에서 인자를 넘겨주기 전에 굳이 null 체크를 할 필요가 없다면 불만을 가질 수 있을 것이다.

Flow의 기능들은 타입체킹과 주석을 달아주는 것을 넘어, 새로운 구성체(new construct)를 지원한다. 그 중 하나는 리터럴 타입인데, 우리가 만드는데 사용할 수 있으며, 그 예로 열거형이 있다.

그리고 Flow는 direction이 "North"도 아니고 "South"도 아닌 것을 반환하려하면 뭔가 불평하고 있을 것이다.

내가 찾은 또다른 유용한 구성체는 유니온(Union) 타입이다. 이것은 딱 하나의 값으로 제한하고, 미리 정의해놓은 타입들 중에서 하나로 제한한다. 아래 예제는 Flow 문서에서 온 것이다.

Flow은 도움이되는한 꽤 도움이 되는 리액트 네이티브와 훌륭한 동반자이다. Flow 문서에서는 구성 요소의 유형에 올바르게 주석을 추가 할 때 어떤식으로 동작하는지 보여주는 좋은 예시를 제공한다.

저 주석은 Flow가 어디서 경고를 내는지 알려주며, 여러분 계약에 만족스럽지 않다고 충분히 꾸짖는다.

Flow는 전적으로 강력한 도구이다. 여기에는 여러분이 해볼 수 있는 유용한 커멘드라인 인터페이스 예제가 있다.
  • suggest는 주어진 파일에대해 타입 주석 제안을 보여준다(suggest Shows type annotation suggestions for given files)
  • type-at-pos는 주어진 파일과 위치에 타입을 보여준다(type-at-pos Shows the type at a given file and position)
  • get-def는 변수나 프로퍼티의 선언 위치를 받는다(get-def Gets the definition location of a variable or property)

Flow는 flossing와 비슷하다
이제 자바스크립트가 고쳐졌을까? 아니다.

Flow가 했을 공학의 노력에 감명받았고, 이것은 자바스크립트의 부모집합(superset)으로 남았으며, 따라서 당신을 태생적으로 약한 파운데이션에서 만들게 한다. 자바스크립트의 결점을 치료하는 어느 종류로서 Flow가 빗발치는 것은 (Monty Python and the Holy Grail으로부터) Swamp Castle and its King을 떠올리게 했다.

내가 여기 처음 왔을때, 여기는 전부 늪이였어. 여기 늪에 성을 세울거라는 말에 모두가 나를 얼간이라 했지만, 똑같이 만들어서 그냥 보여주었지. 그것이 늪으로 가라앉았고, 나는 두번째 것을 지었어. 그것도 늪으로 가라앉았고 세번째것을 또 지었어. 그것은 불에타고 쓰러져서 늪에 가라앉았어. 그러나 네번째는 버티고 있어. 그리고 이게 너가 얻어야 할 것이고, 영국에서 가장 강한 성을 얻어냈지.

안전하지 않은 파운데이션을 만들수 있을거라는 말이 파운데이션을 더 안전하게 만들진 않고, 더 효율적인 과정이지도 않을 것이다. 그리고 이 행동을 저지하려는 주장은 그 불합리함을 놓치게 만든다.

아마 더 의미있게, 자바스크립트 부모집합, 린터(linters), 정적 분석기는 당신이 더 안전한 언어를 고를 수 없는 플랫폼을 다룰때 완화시키는 방법으로서 일시적으로 억제해줄 것이다. 그게 된다면, 그것들을 사용하면서 도움을 구하지 않아도 될 것이다.

이런 일시적인 조치에는 또다른 근본적인 문제가 있다. 이것이 실제로 그 권위자가 쓰지도 않고 커뮤니티에서도 존경받지 못하면 법같은 이 안전장치는 아주 조금만 의미있게 된다.

Flow는 당신이 코드바운드로 리액트 네이티브 앱을 만들고 실행시키는 것부터 런타임 크레쉬를 생성하는 것까지 당신의 작업을 멈추게 하지는 않는다. 그리고 그것은 프로그래밍 언어에대한 기본적인 안전 요구사항이다. 만약 에러를 막을 수 있으면, 그 언어는 능동적으로 막으려고 할 수 있고, 안전하지 않은 코드를 짜고 실행시키는 것을 디폴트에의해 방해할 것이다(그 후에 하는게 아닌).

리턴값이 모호한 함수를 짜라고 팀에게 말할 수는 없을 것이고, 그것에 응답하지 않는 객체에 메소드를 호출하라고 나에게 말할 수도 없으며, 컴포넌트에 proptypes을 정의하지 않고 proptypes이 정의되있다는 코드 리뷰를 하는 동안 나에게 손수 끄집어내라고 할 수 없을 것이다.

유닛 테스트와 flossing과같은 Flow는 유익하고 선택적이고 지루한것의 저주를 낳는다. It’s in your next year’s resolutions.

그리고 여기에 현실이 있다. 깃헙에 공개된 .js 파일에 Flow를 사용하는 파일(즉, Flow가 체크할 수 있는 @flow가 포함되있는 파일)이 몇개나 될까? 어림잡아 80,000,000개의 .js파일에서 1,400,000개정도이다. 안전한 자바스크립트를 짜기 위해 2%보다 작은 곳에서 이 툴을 사용하고 있었다.

여기에 관련된 노트인, awesome-react-native에서 100개가 넘는 리액트 네이티브 저장소들이 있는데, 여기서 Flow를 제대로 사용하고 타입 주석을 사용한 저장소는 한개도 발견할 수 없었다. 오직 리액트 네이티브 튜토리얼에만 Flow를 사용하고 있었다.

자바스크립트 생태계: 속박과 굴레
자바스크립트 개발자를 제외한 나머지 모두는 자바스크립트의 결핍에대한 깊은 인상을 받은것 같다. 위에서 내가 설명한 자바스크립트는 흉측한 사마귀가 아니라는 사람들에게는, they’re “quirks” or “gotchas” that you, not your language, have to be on the lookout for.

왜냐하면 자바스크립트 개발자들은 자바스크립트가 불충분하다고 믿지 않기 때문이다.

언어에서 불변성을 지원하지 않는다? 그럼 만들면 된다. 언어에서 typing을 지원하지 않는다? 그럼 만들면 된다. 언어에서 decimal을 지원하지 않는다? 그럼 만들면 된다. 언어에서 안전한 함수형 프로그래밍 언어를 허용하지 않는다? 그럼 만들면 된다. 언어에서 nullability를 지원하지 않는다? 그럼 만들면 된다.

혹은... 당신이 이 기능들이 근본적으로 중요하다고 인정하면, 여러분은.. 바깥세상에서의 그것을 지원하는 언어로 전환해버리면 될까?(잘 모르겠다. 그냥 생각난것을 말한거다)

내 생각엔, 자바스크립트가 태생적으로 결핍하다고하여 그것을 계속 갈고 닦는게 아니라 다른것으로 대체하려 한다면 그것은 일반화된 고집의 거부(generalized obstinate refusal)이다. 갑자기 증가한 개선이나 버팀목의 결과는 살아있는 생태계의 신호로 보이나, 실제로 이것이 의미하는 것은 이 언어가 근본적으로 중요한 기능의 결핍이 있다는 것이다.

아래 그림은 이러한 상황을 만화로 잘 표현했다.

삽질으로부터의 자유는 당신이 필요한 것이 내장된 언어를 선택하는 것에 달렸다. 이러한 삽질은 에너지 낭비이다. 자바스크립트는 다음의 이유로 좋은 소프트웨어를 제작하는데 도움이 되지 않게 하고 있다: 자바스크립트는 우선 당신이 개발하게 만들고, 다른 언어가 제공하는 것에 의존적이게 만든다.

사슬(Chains)
자바스크립트는 튀긴 커다란 생선을 가지고 있다. 이 언어는 다양한 버전의 인터넷 브라우저의 몇십억 사용자 입맛에 맞춰주어야한다. 이것이 언어의 발전을 더디게 만든다.

typeof(null)==='object'를 기억하는가? 음, 예전에 type of null을 null로 바꾸자고 제안했었다. 그러나

이렇게하면 현존하는 수많은 사이트가 망가지게 될 것이다. 자바스크립트의 스피릿에 적합하지 않다.

그리고는 이 제안이 거절되었다. ES06에의해 null은 여전히 object이다.

자바스크립트의 발전 과정은 필요에의해 입맛에만 맞추고 있다.
  • 수많은 구식 버전의 브라우저 사용자들
  • 각색의 브라우저 벤더 집합
  • 수십억의 사이트와 그 사이트의 각 개발자들
이것들은 훌륭한 민주주의이긴하나 한편으로는 다른 언어에비해 굉장히 더디게 발전한다. 그리고 이것은 이식성이 좋은 만큼 개발자의 인간환경공학은 좋지 않을 것이다.

넓은 시각(Wider angles)
역사적인 관점에서, 한 언어가 인기를 얻고나서, 그것을 넘겨받고싶은 점유자들이 거부하게되는 패턴은 겉으로보기에 불충분한 언어에게 나타나는 익숙한 패턴이다.

여기 따뜻한 모닥불 옆에 앉아서 내 얘기를 좀 들어봐라.

1994년으로 돌아가보자. Richard Stallman은 "왜 Tcl을 쓰면 안되는가"라는 다소 모호한 타이틀로 comp.lang.tcl 뉴스그룹(news group)에 글을 하나 썼다. Stallman은 프로그래밍 언어로서 Tcl의 단점을 심술궂게 꾸짖었고, 목적에 맞지 않는 Tcl을 고발했다. 자바스크립트에대해 내 불평과 유사하게 매우 장관이었다.

Emacs의 주요 수업에선 확장을 위한 언어는 단지 "확장 언어"가 될 수 없다고 한다. 실제 프로그래밍언어가 되야하고, 상당한 양의 프로그램을 짤 수 있어야하며, 그것을 유지보수할 수 있게 설계되야한다. 왜냐하면 사람들이 그것을 바라니까! [...] Tcl은 진지한 프로그래밍 언어로 설계되지 않았다. 이것은 "스크립트 언어"가 되기위해 설계되었으며, "스크립트 언어"라 가정하는 것은 실제 프로그래밍 언어가 되려고 할 필요가 없었음을 의미한다. 따라서 Tcl은 하나의 능력을 빼먹었는데, 배열이 부족하다; 링크드리스트를 만들 수 있는 구조체를 빼먹었다. 그것은 가짜로 넘버를 가지고 있는데, 매우 느리지만 동작은 한다. Tcl은 작은 프로그램을 만드는데 적합하나, 그 넘어를 하기엔 적합하지 않을 것이다.

이 글은 1994년에 Tcl 전쟁을 촉발시킨 글이다. 그가 들었던 대답들중에 가장 인상적이었던 John Ousterhout(Tcl을 만든 사람)의 대답이다.

언어 설계자로서 이 언어가 왜 선천적으로 더 낫고 더 나쁜지 우열을 가리는 토론을 사랑한다. 그러나 이런 건방진 주장에는 많은 문제가 있다. 궁극적으로 모든 언어의 이슈는 그 사용자가 원하는 것을 투표할 때 합의가 생긴다. 만약 Tcl이 그들이 사용하는 것보다 더 생산적이게 만들었다면(혹은 이미 그렇게 되었다), 다른 언어 사용자들이 이것이 더 낫다고 하면서 온다면, 그때 사람들은 언어를 바꾼다. 이것이 법칙이고 이게 맞다.

Outsterhout의 반격은 내가 활동하고 있던 많은 사람들 앞에서 이루어졌고, 그의 일격은 더 가까이서 볼 수 있었다.

(몇몇 독자들은 Ousterhout가 순회적으로 말했다는 것을 알아차릴 것이다. "왜 사람들이 언어를 바꿀까? 그게 더 낫기 때문이다. 왜 그것이 더 나을까? 사람들이 많이 쓰기 때문이다." 그의 주장은 더 많은 설명이 필요함에도 불구하고 조금도 하지 않았는데, 우리는 종종 특정 기술 스택(예를들어 여러분이 생각하고 있는 리액트 네이티브)에 여러 주장에서 이런 추런 라인을 보았었기 때문이다)

Ousterhout에 따르면, 프로그래밍 언어는 그 언어가 더 낫다고 말할 수 있는 두가지 특징을 가지고 있는데, 바로 선천적인 특징들(프로그래밍 패러다임, 문법, 표준 라이브러리. 이식성과같은 그 고유의 특성)과 후천적인 특징들(수많은 개발자들이 폭넓게 채택한것)이다. 만약 언어A가 언어B보다 후천적으로 낫다면, 선천적으로 언어B가 언어A보다 더 낫다고해도 별로 소용없어질것이다.

다른말로 하자면, 채택되는 것이야말로 기술 우선순위에서 최고봉이다.(언어 설계자가 어떤것을 우위로 정의했는지 상관없이 말이다)

Ousterhout 주장에 딱 맞아보이는 앨범 커버이다.

더 많은 팬을 가진 가수가 그를 더 낫게 만든다. 요점은 팬이나 히트 기록의 양에의한 인기이며, 이것이 가수를 평가하는 좋은 기준이다.

그러나 언어가 널리 채택되고 그것으로 만들어진 멋진 앱들을 자랑할 수 있다는 사실로는 그 메리트로 당신의 판단에 설득시킬 수 없을지도 모른다.

복잡해보이거나 보기에 멋진 앱이 기술X로만 만들었다는 의미는 기술X가 복잡해보이거나 보기에 멋진 앱을 만들기에만 최적화되있고, 보통 일에는 최적화되있지 않다는 뜻일 수도 있다.

전세계에서 열리는 모래성 대회는 당신도 만드는데 쓸 수 있는 모래와 물로 아름다운 구조물을 만들어서 보여준다. 이것은 모래가 좋은 장난감임을 주장할 수 있는 근거가 될 수는 있으나, 모래성 대회를 근거로하여 모래로 여러분의 집을 지을 수 있다고 납득하기는 어려울 것이다. 그러나 많은 이들이 납득되어 버렸다.

The King of Swamp Castle은 수많은 해커의 왕이다.

비슷하게, 인기는 프로그래밍 언어를 평가하기엔 신뢰할 수 없는 기준이다. 아주 기본적인 이유로, 인기는 벤더를 속박시키거나(브라우저에서만 돌아가는 프로그래밍 언어가 된다던지), 벤드웨이건 효과나, 레거시(legacy) 코드베이스의 결과를 매우 잘 만들지도 모른다.

프로그래밍 언어의 고유 특징들(프로그래머 에러에 대비한 안전장치, 표준 라이브러리, 이식성 등)은 여러분의 기준에 기반해야한다. 이것은 생산성 향상의 기본요소이다.

사실은 많은 것들이 부정적인 생산성을 이끌기도 한다. 그 예이다.
  • 피할 수 있는 에러를 만드는 당신을 막는 안전장치의 부족
  • 많은 목적에 맞지 않는 작은 표준 라이브러리
  • 당신의 의도를 명확하게 표현하지 않는 문법과 의미론(syntax and sementics)
  • 더딘 발전
  • 위의 모든 것들(자바스크립트)

의존성
리액트 네이티브는 총 648개의 의존성을 가지고 있다.

특별히 놀랄 것 없게도, 의존성 체인은 세상의 npm 중에 길수 있으므로, 리액트 네이티브의 패키지 매니저이다.(원문: Not particularly surprising, as dependency chains can be long in the world of npm, React Native’s package manager.)

이 광경은 오픈소스의 동료관계이다. 여러분의 앱은 600명 이상의 사람들의 지속된 노력으로 만들어졌다.

이게 함정이기도한데, 여러분은 648명의 자원 봉사자가 그 라이브러리를 유지해주어야 앱이 잘 돌아가며, 그 자원봉사자들로부터 어떤 약속 따윈 없다.

그들의 라이센스가 당신의 소프트웨어에 맞게 유지될까? 희망적으로?

그리고 그 구현이 모두 보안면에서 최고의 실천을 하고 있을까? 혹은 648개의 별개의 잠재적인 보안 리스크를 묵인할 수 있겠는가?

더 나은 제안들
크로스-플랫폼 개발 때문에 리액트 네이티브를 선택하게 되었다면, 다른 옵션도 생각해볼 필요가 있다.

리액트 네이티브는 지금 Xamarin과 Appcelerator라는 두개의 크로스 플랫폼 개발과 경쟁하고 있다.

Xamarin과 Appcelerator 둘 다 iOS, 안드로이드, 윈도우 폰을 지원한다. 그리고 둘 다 아래의 것들도 지원한다.
  • 더 종합적인 API
  • 더 성숙한 IDE
  • 더 나은 문서
  • 명확하고 친숙한 라이센싱
  • 동등한 퍼포먼스(더 낮진 않더라도)

Xamarin 개발은 C#으로 하는데, 이것은 자바스크립트에 비해서 버그를 줄여주는 경향이 있고, 더 표현력이 좋다(more expressive). 만약 자바스크립트를 쓰는 개발자라면 Appcelerator 개발이 자바스크립트로 할 수 있다.

리액트 네이티브와 비교하여 Xamarin과 Appcelerator 둘 다 멀리 보았을때 더 나은 가능성을 가지고 있다. Appcelerator(Titanium의 아버지)(3억  5천만 기기에 앱으로 실행 되었었다)는 2016년 1월에 인수되었고 Xamarin(포춘지 선정 500 대 기업에서 100 기업 이상 사용했다)는 마이크로소프트에의해 2016년 2월에 인수되었다. 둘 다 이전보다 8천만달러 이상의 주식형펀드가 올랐다.

나에게 지원해주기 위한 비즈니스의 회사가 빽으로 있다면, 프로젝트들은 이 크로스 플랫폼이라는 레드오션에서 신뢰할 수 있는 소프트웨어 개발 플랫폼으로 살아남고 성장해야한다(최근에 세어보니 10개 이상의 활발한 개발 프로젝트들이 있었다).

(의미있는 언급으로 Flutter(이하 플루터)에 대해 이야기 하겠다. 이것은 구글이 만든 크로스-플랫폼 개발 플랫폼이다(iOS, 안드로이드 둘다 지원한다). Dart라는 언어를 사용하는데, 이 언어는 자바스크립트보다 안전하고 표현력도 더 좋다. 또한 메트리얼 디자인 원칙을 따르게 도와주고, 네이티브하게 컴파일 된 코드를 만들어준다. Xamarin과 Appcelerator와는 다르게 오픈소스이며, 아직 제품으로 준비되지는 않았지만 그럼에도 불구하고 약속해놓았다.)

결론
좋은 소프트웨어 개발 플랫폼은 4가지 필수 특징을 가진다.
  • 이식성 - 한가지 이상의 플랫폼을 타겟으로 한다.
  • 생산성 - 성숙한 IDE와 다른 개발 툴, 문서, 그리고 표현력 있는 그 개발 언어
  • 안전 - 당신이 만들 수 있는 실수를 그 플랫폼이 얼마나 막을 수 있는지의 정도
  • 지속성(longevity) - 당신의 앱이 살아있는 동안 플랫폼이 얼마나 오래 가는지
비록 우리 산업이 아직까지는 이것을 가늠하기위한 확립된 오픈 표준이 없지만, 나는 내 경험과 조사를 바탕으로 내 평가를 공유하고 싶다.


리액트 네이티브의 강점을 이식성과 생산정의 면에서 보자면 너무 과하고, 안전, 장기간 프로젝트에는 불확실성, 위압적인 특허 라이센스에는 부족함이 있다.


Xamarin과 Appcelerator와같은 성숙한 플랫폼은 최고의 이식성(윈도우 폰을 지원한다), 성숙된 개발 툴, 프로그래밍 언어를 선택할 수 있게 해주는 것을 제공하는데, 언어 선택으로 생산성과 안전성을 얻어낼 수도 있다. 그리고 이것들이 잘 투자받은 회사의 핵심 제품이라는 사실이 장기간의 면에서 안심시켜준다.


Swift 개발은 안전성, 지속성, 생산성 면에서는 좋다. 이식성의 면은 상대적으로 낮으나 무시해도 되는 수준이다. 안드로이드 버전을 개발 할 수 있게 해주는건 아니지만 macOS 버전이나 백엔드 서버 앱을 만들 수 있게 한다.





여기까지가 내가 왜 리액트 네이티브 개발자가 되지 않는지의 그 이유였다.

감사
이 글의 초안에 도움을 준 Rami Chowdhury와 Alkis Papadakis에게 감사를 표한다. 그리고 난해한 IP 텍스트들을 해독하는데 도움을 준 Greg McMullen에게도 감사하다.

바뀐 이력
이 글이 바뀐 이력은 여기에서 확인할 수 있다.

커멘트
이 글에 대한 토론 에 팔로우하여 참여하고 싶으면 Hacker News, Hacker News(Again)/r/programming로 와라.

참조
 



WRITTEN BY
tucan.dev
개인 iOS 개발, tucan9389

,