Dende
React Native or Flutter ? (펌) 본문
IOS용 Swift나 Android용 Java를 사용하지 않고 기본 앱을 빌드 할 수 있는 프레임워크가 등장하면서 크로스 플랫폼 모바일 앱을 개발하는 것이 요즘 유행하고 있다고 합니다.
그 중 가장 널리 사용되는 두 가지 모바일 개발 프레임워크는 React Native 와 Flutter.
React Native와 Flutter는 하나의 코드베이스, 핫 리로딩, 뛰어난 UI, 멋진 툴링 및 기본 기능을 사용하여 크로스 플랫폼앱을 빌드하는 거소가 같은 많은 유사점을 제공합니다.
동시에 몇 가지 차이점이 있습니다.
언어의 차이
- Flutter: Dart
- React Native: JavaScript
일단 2가지 컴파일 방식의 개념에 대해 간단히 짚고 넘어가겠습니다.
JIT — “Just in Time”. 컴파일러가 코드를 번역하고, JIT이 런타임중에 코드를 선택적으로 최적화 한다. 빠른 스타트업 속도를 보여주지만 준비시간(warm-up)이 걸리고 첫번째 실행해서는 퍼포먼스가 다소 낮지만 실행이 반복될수록 점차 향상된다. 하지만 상황에 따라 예측불가한 퍼포먼스를 보여준다.
AOT — “Ahead of time”. 컴파일과 최적화가 실행 전에 이루어진다. 컴파일 시간은 오래걸리지만 최적화가 완전히 이루어졌기 때문에 전반적으로 예측가능한 성능을 보여주고 특히 애니메이션과 같이 무거운 작업에서 좋은 퍼포먼스를 보여준다.
그렇다면, React Native와 Flutter가 어떻게 다를까? 이 두 프레임워크의 언어를 기반으로 전반적인 특징들을 살펴보겠습니다.
리액트 네이티브는 자바스크립트 언어를 사용한다. 원래 리액트(React)가 웹 어플리케이션 개발용으로 먼저 개발되었고 리액트 네이티브가 차후 네이티브 플랫폼을 타겟으로하여 만들어졌는데 기존의 비즈니스 로직과 많은 모듈들을 활용하기 위해서는 자바스크립트를 사용해야 했다.
그렇다면 React Native 가 자바스크립트 코드를 네이티브 플랫폼에서 실행되기 위한 전반적인 프로세스에 관하여 간단히 알아보자: React Native는 자바스크립코드를 번들화해서 그것을 디바이스로 전송한다. 그 다음 네이티브 플랫폼상에서 번들화된 명령어를 수행하여 브릿지를 통해 UI렌더링을 실행할것을 React Native 에게 명령한다. 여기서 브릿지는 자바스크립트가 네이티브 플랫폼에서 그에 맞는 형태로 실행 될 수 있도록 도와주는 인터페이스 역할을 담당한다. (iOS — Objective-C / Android — Java)
플러터는 Dart언어를 사용한다. Dart는 자바스크립트에 비해 유연하다. 이 언어가 자바스크립트와 달리 갖는 특별한 점은 정적 타입 또는 다이나믹 타입 성격을 유동적으로 지닐 수 있다는 것이다. 그러므로 다트는 JIT뿐만 아니라 AOT 또한 지원할 수 있다. 게다가, Dart는 플러터를 개발한 구글에서 만든 언어이기 때문에 구글은 필요와 상황에 맞게 언어를 조정할 수 있다. 그리고 실제로 AOT가 Dart 2부터 도입되었다. 다트의 이러한 예외적인 성격은 iOS와 안드로이드 뿐만 아니라 다른 플랫폼까지도 확장될 수 있다는 가능성을 보여준다.
빌트인 컴포넌트의 차이
리액트 네이티브와 플러터 둘다 많은 빌트인 컴포넌트를 제공한다. 이는 플러터에서는 위젯이라고 부른다. React Native 에는 기본적으로 제공하는 컴포넌트 외에 특정 플랫폼에서만 동작하는 것들도 있다. 사용자가 하나의 코드로 다수의 플랫폼에서 동일하게 동작하기를 기대하지만 각각의 플랫폼에 적합한 컴포넌트를 구분해서 사용해야 하는 번거로움이 있다. 그 중 React Native 에서 내가 가장 다루기 어려웠던 부분이 네비게이션이다. 네비게이션이 모바일 어플리케이션에서 중요한 부분임에도 불구하고 React Native는 네비게이션을 위한 충분한 빌트인 컴포넌트를 지원하지 않고, 사용자는 외부 모듈을 가져와서 사용해야한다. 이는 시간이 걸리고 관리하기가 쉽지 않다.
반면 Flutter 에서는 굉장히 많은 빌트인 위젯들을 제공한다. 그 범위가 상당히 넓은데, 예를 들어 플러터는 iOS를 위한 Cupertino 테마, 안드로이드를 위한 Material테마를 각각 제공하여 개발자들에게 플랫폼 별 색이나 텍스트, 크기 스펙을 찾을 필요가 없도록 도와준다. 또한 Hero나 Slivers 위젯의 경우 이 자체가 지닌 애니메이션 효과로도 충분히 UI구현이 가능하기 때문에 애니메이션 구현 시간을 덜어준다. Hero 위젯의 경우 위의 데모 어플리케이션에서 실제로 사용했다. Flutter 에서 발견한 유용하다고 생각한 또다른 위젯중에 RichText가 있다. React Native 에서는 한 문장 안에서 글자나 단어 단위로 스타일을 변경하고 싶을 때 HTML 태그를 텍스트에 적용해야 각각에 다른 스타일을 적용할 수 있었다. 하지만 Flutter의 RichText 위젯을 이용하면 그 안에 다수의 TextSpan child 위젯을 넣을 수 있고 각각의 TextSpan에 스타일을 적용할 수 있다.
하지만 이렇듯 기능이 이미 많이 내장된 빌트인 위젯들은 사용하기가 굉장히 편리하더라도 많이 의존하게 되면 차후 UI가 변경되거나 다른 기능들이 추가로 필요할 경우 커스터마이징이 어려울 수 있다.
React Native 의 모든 컴포넌트들은 각 OS별 네이티브 컴포넌트를 사용합니다.
Flutter 는 거의 다 자체구현 되어 있죠.
그래서 React Native 는 플러그인들 또한 OS에 엄청나게 의존하고 있습니다. OS가 업그레이드되서 더 이상 호환이 안되게 되면 그 플러그인 못쓸 수도 있습니다. 업데이트 제공 안해주면.
Flutter는 상대적으로 OS 의존도가 적습니다. 화면에 그리는 작업을 거의 자체적으로 해결하거든요.
스타일링
리액트 네이티브는 HTML과 비슷한 React 컴포넌트 JSX 문법을 사용한다. 그리고 컴포넌트의 스타일 속성은 css와 유사한 StyleSheet을 통해 부여한다. 아래의 코드는 리액트 네이티브에서 간단한 텍스트 컴포넌트를 렌더링 할때 쓰이는 스타일 적용 방식을 보여준다.

Rendering part — React Native

StyleSheet — React Native
Flutter 에서 스타일링 방식은 위젯을 통해 이루어진다. 그 차이를 보여주기 위해 코드의 일부를 첨부했다. 보이다시피 padding, margin, alignment나 다른 스타일 속성값들이 위젯으로 정의되어 있다. 스타일을 적용하고싶은 위젯을 스타일 위젯으로 감싸는 방식으로 스타일을 부여한다.

Widget tree — Flutter
‘Padding’ 은 속성값과 함께 그 값을 부여할 child 위젯을 갖고있다. ‘Column’ 은 수직형 레이아웃과 기본적으로 Flex 위젯을 상속함으로써 flex 속성을 지니고, 다수의 child 위젯을 가질 수 있다.
위의 두 예시 모두 비슷한 형태의 텍스트 뷰를 렌더링한다. Flutter의 코드가 React Native 방식보다 좀더 장황해 보인다. 하지만 이부분은 지극히 개발자의 취향차이인데, 만약 웹 개발에 익숙하다면 React Native 방식이 좀 더 친근하게 보이겠다. 나의 경우, 안드로이드 개발을 했었고 스타일과 렌더링 파트는 분리하는것이 편했다. 하지만 Flutter 방식에 익숙해지는데 그리 오래 걸리지는 않았다. 특히, 이 위젯 트리라는 것이 유용하다고 느꼈을 때가 hot-reload 기능을 사용할때 였는데, UI를 변경하면 그것이 즉각적으로 나타나고 이 때 위젯들과 스타일이 어떻게 연계되었는지 뷰의 구조를 한눈에 볼 수 있는 점이 꽤 직관적이라고 생각했다.
React Native은 OS별 디버깅 필요하다.
React Native는 네이티브 Api와 밀접하게 통신하기 때문에 그 기능을 모두 사용할 수 있다.
특정 컴포넌트를 사용할 때 한쪽의 OS만 지원하는 컴포넌트라면 따로 네이티브 언어로 예외처리를 해줘야 하기 때문에, 디버깅을 할 때에도 OS별로 따로 작업을 진행해줘야 한다.
React Native 를 모바일개발 도구로 사용한지 꽤 오래 되었고 이것이 주는 장점 뿐만이 아니라 많은 한계점도 경험할 수 있었다.
Flutter는 풍부한 빌트인 위젯을 제공하여 UI작업을 굉장히 간소화 해준다. 하지만 장기적으로 봤을 때 프레임워크에 너무 의존하게 될 수도 있고, 그만큼 커스터마이징에 제한적일 수 있다. Javascript보다 비교적 덜 알려진 Dart 언어를 새롭게 배워야 하겠지만 Java에 익숙한 개발자라면 쉽게 다가올 수 있다. React Native는 Flutter보다 오래되어 보다 방대한 커뮤니티를 갖고 있고, 자바스크립트를 사용한다는 점에서 좀 더 보편 적일 수 있다.
이러한 크로스 플랫폼 프레임워크들은 모두 네이티브보다 부족한 기능들로 외부 모듈(라이브러리) 의존도가 높을 수밖에 없다. 그래서 만약 필요한 모듈이 부재할경우 각각의 네이티브 플랫폼에서 적합한 모듈을 직접 제작해야 할 경우도 발생한다. 이는 결코 단순한 작업은 아니다. 이렇듯 모든 도구들은 장단점이 있고 어떤것을 선택하느냐는 개인의 선호도에 따른 문제이기 때문에 직접 사용해보는 것을 적극 추천한다.
그래서 이러한 단점들에도 불구하고 네이티브가 아닌 크로스 플랫폼 프레임워크를 사용해야 하는것이 맞는가? 이점은 또한 상황에 따라 다르다. 이러한 React Native나 Flutter와 같은 프레임워크는 효율적으로 네이티브와 최대한 비슷한 사용자 경험을 주기 위할 뿐 근본적으로 네이티브는 아니기 때문에 메모리나 퍼포먼스 이슈에 관해서는 더 취약할 수 있다. 그래서 네이티브 만큼의 퍼포먼스를 보여주지 않을 수 있겠지만, ‘코드 재사용’(하나의 코드로 다수의 플랫폼을 동시 개발) 뿐만 아니라 개발자에게 멀티 플랫폼에 대해 상당한 유연성을 제공한다는 것은 무시할 수 없는 장점이다. 따라서, 만약 네이티브 대신 크로스 플랫폼 프레임워크를 채택할 것을 고려중이라면 단순히 코드재사용이나 비용절감의 이유 뿐만이 아니라 해당 제품의 목적과 주 기능들이 그 프레임워크를 통해 충분히 구현될 수 있는지 신중하게 알아보고 결정하는것이 바람직하다고 생각한다.
'React Native' 카테고리의 다른 글
React Native Android NativeModules 사용 (0) | 2022.08.02 |
---|