React Native의 작동원리를 알아보기 전에 필요한 용어들을 알아봅시다!
우선, Javascript에서 빠질 수 없는 DOM과 렌더링에 대해 알아보아요!
DOM, 한국어로 풀어 말하면 문서 객체 모델입니다. 풀어서 말해도 무슨 말인지 이해하기 어렵죠?
HTML 문서가 웹브라우저를 만나면 파싱(Parsing) 과정을 거치면서 Javascript 객체를 만들게 돼요. 여기서 파싱 과정을 렌더링이라고 하고 자바스크립트 객체를 문서 객체(Document Object)라고 해요. 웹브라우저에서는 비록 HTML문서와 동일하게 <div>
, <h1>
과 같이 나타나서 큰 차이가 없어보이지만, 문서 객체가 됨으로써 자바스크립트 관점에서 HTML 문서를 볼 수 있게 돼요. 자바스크립트 관점에서는 <div>
는 HTMLDivElement 클래스의 인스턴스, <h1>
은 HTMLHeadingElement 클래스의 인스턴스로 보여지는데요. 문서를 인식할 수 있는 모델을 만든 셈이죠. 즉, HTMLDivElement, HTMLHeadingElement와 같이 문서를 이루는 클래스들은 DOM이고, 이를 구성하는 인스턴스를 DOM 객체라고 부른답니다!
DOM은 부모와 자식을 가진 트리구조로 되어있어요. 그림으로 설명드리자면, document라는 부모 밑에 body자식이 있고, body가 부모가 되어 div라는 자식이 있고, div 밑에 h1과 ul이 있고 등등 이렇게 뻗어나가는 구조로 되어있어요. 즉, 여러 자식들을 이파리라고 생각하면 이파리들이 모이고 모여 document라는 하나의 큰 나무를 만드는 셈인거죠.
DOM은 화면이 수정될 때마다 렌더링을 시키게 되어있어요. 수정사항은 반영해줘야하니깐요! 하지만, 기존에는 수정 사항이 조금만 생기더라도 DOM을 건드려서 렌더링을 시켰기 때문에 굉장히 비효율적이었죠. 문자 하나 수정하는 것을 10번 반복하면 전체를 10번 렌더링하니까 얼마나 비효율적이에요! 이런 문제를 해결하기 위해서 React 는 수정사항들을 가상으로 반영시키고 한번에 처리하는데, 여기서 처리하는 곳을 가상DOM이라고 하고 이를 물리DOM에 한번에 적용시켜요. 이 과정을 "리액트가 렌더링한다!"라고 하고, 이를 수행하는 패키지를 렌더러(renderer)라고 해요.
React든 React Native든 둘다 React 패키지 기반으로 동작을 하고, React 패키지는 App.js나 App.tsx 파일을 가상 DOM구조로 만드는 역할을 해요. 대신, React는 모든 것이 자바스크립트로 동작해서 OS 별도로 동작해야하는 모바일앱에는 최적화된 프레임워크는 아니에요. 그렇기 때문에 네이티브 모듈이 별도로 있어서 모바일에 정형화된 React Native를 이용하면 네이티브 앱과 같이 동작하는 모바일앱을 만들 수 있어요.
즉, React 패키지만으로는 네이티브처럼 동작하는 앱을 만들 수 없는데, 여기서 네이티브 렌더러가 React 패키지로 만든 App 컴포넌트들을 모바일 UI 객체로 변환시켜서 모바일에 맞게 사용할 수 있도록 해준답니다. 이 네이티브 렌더러는 안드로이드와 iOS 환경에 맞게 별도로 구현된 네이티브 모듈 쪽에서 렌더링을 해요.
리액트 네이티브 프로젝트를 실행하면 2개의 스레드(Thread)가 동시에 동작하기 시작해요. 하나는 네이티브를 담당하는 UI 스레드, 다른 하나는 자바스크립트 코드를 실행시키는 자바스크립트(JS) 엔진 스레드에요. 이 둘은 메시지 큐 방식으로 소통하는데, 유저와 화면과의 interaction이 존재하면 UI 스레드는 JS엔진스레드로 이벤트를 전달해요. 이런 방식으로 동작하는 프레임워크를 브릿지 방식 프레임워크라고 한답니다.
자, 그럼 이제 소스코드를 보면서 어떻게 렌더링이 되는지 볼까요?
이후로도 계속 Typescript로 진행할거니깐 typescript 기준으로 말씀드릴게요. Javascript도 거의 동일하고 확장자만 조금 다를거니까 걱정마세요!
npx react-native init [프로젝트 이름] --template react-native-template-typescript
터미널에 이렇게 작성하면 typescript 템플릿의 리액트네이티브 프로젝트를 만들 수 있어요.
방금 만든 프로젝트의 root 디렉토리에 존재하는 App.tsx는 가상DOM을 생성하고 이를 네이티브로 넘겨줘요. 프로젝트를 생성하면 기본으로 나오는 UI 코드가 있을텐데 이는 가상DOM에 생성되는 것이지요!
하지만 App.tsx파일의 존재를 네이티브 모듈은 알려주지 않으면 몰라요. 그래서 index.js파일을 통해 네이티브 모듈에게 App.tsx파일의 존재를 알려주게 되고, 기본적으로 안드로이드나 iOS 네이티브 모듈 모두 index.js로부터 정보를 얻게 되어있답니다.
// index.js 코드 중 App과 연결하는 부분
AppRegistry.registerComponent(appName, () => App)