DEVLOG|개발 블로그

리액트와 리액트 네이티브

May 26, 2021 10:00 PM:react, react-native

리액트와 리액트 네이티브

쉽게 생각하면 리액트는 UI를 그리기 위한 라이브러리이다. 결국에 리액트를 써서 작성한 코드의 최종 결과물은 HTML, CSS, 자바스크립트 외 브라우저가 이해할 수 있는 정적 자산들로 빌드된다. 리액트로 작성한 UI는 브라우저 위에서 작동한다. 잘 알지 못하는 사람들이 하는 오해는 애플리케이션에 내 리액트 애플리케이션이 돌아간다고 해서 그 애플리케이션이 리액트를 지원하는게 아니라 애플리케이션에서 브라우저처럼 웹 화면을 보여줄 수 있는 부분이 있는 것이다.

시대가 지나면서 많은 플랫폼이 생겨났다. 모바일 환경에서도 브라우저가 있기 때문에 내가 만든 리액트 애플리케이션을 모바일 환경에서도 볼 수 있게 되었다. 한번 작성한 코드로 애플리케이션을 빌드하고 파일을 서버에 올리면 전세계 어디서든 브라우저가 있다면 모든 사람이 내 애플리케이션에 접근할 수 있다. 그럼 리액트만으로도 충분하지 않을까? 왜 리액트 네이티브라는 기술이 생겨났을까?

먼저, 리액트 네이티브는 리액트처럼 코드를 작성하되 작동하는 범위는 브라우저 위가 아니라 네이티브 모바일 환경이 된다. 앞서 정리했듯이 리액트의 최종 결과물은 HTML, CSS, 자바스크립트 등 브라우저가 인식할 수 있는 결과물이다. 네이티브 환경에서 뷰를 그려야 하는 모바일 입장에서는 이 결과물들이 뭔지 알지 못한다. HTML을 파싱해서 DOM을 그리는 브라우저와의 작동방식도 아예 다르다. 페이스북 개발자들은 리액트처럼 작성하되 네이티브 환경에서도 돌아가게 하자. 라는 생각으로 리액트 네이티브를 개발했을 것이다.

정리하면, 리액트 네이티브는 모바일 환경에서 사용할 수 있는 애플리케이션을 개발하기 위한 기술이며 리액트와 리액트 네이티브는 페이스북에서 만든 오픈소스 라이브러리이다. 리액트 네이티브로 작성한 코드는 iOS 및 안드로이드에서 동작한다.

뭐가 다를까

리액트 네이티브를 잘 모르는 사람이 작성한 글입니다. 맹신하지 마시고 이렇게 생각하는 구나라는 정도로 봐주시면 감사하겠습니다.

리액트스럽게 코드를 작성할 수 있는 것 외에 모든 것이 다른 것 같다. 리액트에서 사용하는 컴포넌트들은 브라우저 위에서 작동하는 녀석들이라 모두 HTML 태그를 사용하는데, 이 것들은 리액트 네이티브에서 사용할 수 없을 것 같다. 고로 리액트 네이티브 컴포넌트 전용 라이브러리 외에는 모두 네이티브에서 사용하지 못할 것 같다는 생각이 들었다.

뭐가 좋을까

리액트스럽게 작성할 수 있다는 것이 좋다. 기존에 리액트로 웹을 개발한 사람이라면 좀 더 익숙한 환경에서 개발을 시작할 수 있는게 장점인 것 같다. 그 외에는 한번 작성한 코드로 iOS와 안드로이드에서 모두 동작할 수 있는 것이지만 이는 다른 기술에서도 지원하는 부분이니까 딱히 리액트 네이티브만의 장점은 아닌 것 같다고 생각한다.

뭐가 안좋을까

모바일 애플리케이션에서는 UI 스레드와 자바스크립트 스레드가 존재하는데 이 둘 사이의 다리 역할을 하는 것이 리액트 네이티브라고 한다. 각각의 네이티브 플랫폼에서는 자바스크립트를 해석하기 위해 사용되는 엔진이 있는데, 안드로이드 진영에서는 그 유명한 V8 엔진을 사용하고 iOS에서는 자바스크립트 코어(JavaScriptCore)라는 엔진을 사용한다. 네이티브 플랫폼에서 자바스크립트를 동작시킬 때 성능은 우수하나 보안상의 이유로 해당 엔진이 사용이 불가능한 상황이 있을 수 있다.

JIT 또한 리액트 네이티브와 타 네이티브를 다룰 수 있는 언어와의 차이점이라고 생각한다. 리액트 네이티브 외 네이티브 플랫폼에서 동작하는 애플리케이션을 작성할 수 있는 언어가 Dart(Flutter), Objective-C, Java, Swift 등이 있는데, 이는 모두 컴파일 언어이다. 즉 컴파일 하는 동시에 최적화까지 이루어질 수 있다. 하지만 자바스크립트는 인터프리터 언어 및 JIT를 지원한다. JIT는 런타임 시에 선택적으로 최적화를 진행하는데 이는 성능을 예측할 수 없게 만들 수 있다. 그 외 컴파일 언어는 최적화까지 이루어지고 애플리케이션이 실행되기 때문에 성능을 예측하기 쉽지만 자바스크립트는 그렇지 않다.

리액트 네이티브 컴포넌트가 어느 한 OS에서만 동작할 수도 있다. 예를 들어 iOS에서는 동작을 잘 하지만 안드로이드에서 동작을 하지 못할 수 있다. 이 때 OS마다 선택적으로 컴포넌트를 집어 넣는 것이 까다롭다고 알고있다. (틀릴 수 있습니다)

모듈의 의존성 또한 단점으로 작용하는 부분인 것 같다. 리액트 네이티브의 버전과 모듈의 버전이 호환되지 않고 그 모듈을 반드시 사용해야 한다면 현재 리액트 네이티브가 상위 버전이라도 하위 버전으로 내려야할 수 있다. 현재 상위 버전으로 작성된 리액트 네이티브 코드가 다운그레이드 된다면 호환되지 않는 부분이 분명히 존재할 것이고 이는 큰 문제로 작용할 수 있을 것 같다.

마지막으로, 퍼포먼스가 매우 중요한 애플리케이션을 개발해야 한다면 절대적으로 크로스 플랫폼을 지원하는 네이티브 기술(리액트 네이티브, 플러터)는 절대로 쓰면 안된다는 이야기를 많이 들었다. 결국에 모바일 환경의 자원을 효율적으로 관리하면서 최대한의 성능을 끌어올리려면 개발에 적합한 코틀린, 스위프트 등을 써야한다는 이야기다.

뭐가 같을까

react.startsWith('리액트') === reactNative.startsWith('리액트')

리액트 네이티브 시작하기

리액트 환경이라면 로컬 서버를 띄워 브라우저에서 개발하면 되지만 리액트 네이티브는 모바일 플랫폼에서 동작하므로 모바일 환경과 비슷한 테스트 환경이 필요하다. 그 테스트 환경을 지원하는 것이 바로 expo라고 하는 것 같다.

npm i -g expo-cli
expo init rn-test

 Choose a template: tabs (TypeScript)     several example screens and tabs using react-navigation and TypeScript

cd rn-test

공식 문서에 나와있는 대로 expo-cli를 설치한다. yarn을 사용한다면 yarn global add expo-cli로 설치한다. expo init 시도시 yarn이 설치되어 있으면 자동으로 yarn을 통해 의존성을 설치하는데, expo init rn-test --npm으로 설치하면 npm을 통해 의존성이 설치된다.

npm run android

안드로이드 환경과 비슷한 환경에서 테스트할 수 있는 웹 서버가 열린다. 에뮬레이터를 구동시키니 오류가 발생한다. 에뮬레이터를 설치해야 한다. 이상하게 크로스 플랫폼으로 개발하려면 해당 환경에 맞는 개발 도구가 필요하다.... (XCode나 안드로이드 스튜디오)

추후에 에뮬레이터 설치 및 expo 연동 관련 정리 글 쓰기