React-Native

react-native 작동원리

hyriver(강화영) 2026. 2. 6. 21:42

 

대충 GPT로 뽑은 이미지

 

 

리액트 네이티브는 3개의 스레드로 작동한다.

 

1. javaScript thread

2. shadow thread

3. main thread

 

이렇게 세가지 스레드로 분리된 이유는 각각 다른 작업을 하면서 부드러운 화면처리가 가능하도록 만든다. 화면을 그리면서 js계산을 하고, 레이아웃도 가능하도록 할 수 있다.

 

 

JavaScript thread

- js thread에서는 우리가 작성한 리액트 코드가 실행된다. 리액트 코드가 실행된다는 것은 화면을 그리는게 아니라 컴포넌트 함수가 호출되고 JSX가 계산된다는 뜻이다. 컴포넌트 렌더링(JSX 계산), state/props 계산, 비즈니스 로직, api 응답처리, 애니메이션 계산 등이 수행된다.

- 리액트 네이티브에서는 Hermes라는 자바스크립트 엔진을 사용한다. 일반적으로 js는 앱 실행 후 js를 파싱하고 실행되는데, hermes는 빌드 시 js를 바이트 코드로 변환하고, 앱 실행 시 바로 실행된다. 그래서 앱의 시작속도가 빠르고 메모리 사용도 적다. 또한 웹 api와 DOM이 없어서 가볍다.

- js thread는 싱글 스레드다. 동시에 하나의 작업만 처리하며 큐에 쌓인 일을 순서대로 처리한다. 블로킹되면, 버튼을 눌렀을 때 반응이 없거나 스크롤이 끊기거나 애니메이션이 끊긴다. js 스레드는 상태계산, 이벤트 처리 등의 짧고 빠른 계산용으로 되었기때문에 큰 데이터를 반복처리하거나 자주 반복되는 무거운 작업을 시키면 안된다.

 

 

Bridge vs JSI

- 네이티브(main, shadow)로 넘어가기 전, bridge에 대해 알아보자. JS코드와 네이티브 코드는 다른 언어이기때문에 bridge(JSI)를 통해 변환하는 작업을 해야한다.네이티브로 변환하는 작업이다. 예전에는 bridge였는데, 최근에는 JSI로 변경되었다(0.76부터).

- Bridge : 브릿지는 JSON으로 변환해서 함수를 호출한다. 이런 직렬화/파싱을 하면 큰 객체, 배열, 스크롤 등의 빈번한 호출에서는 더 느려지며 요청을 보내고 응답을 기다려야하는 비동기 처리만 가능하다. 이 문제를 해결하기 위해 나온것이 JSI이다.

- JSI : jsi는 앞서 말한 hermes 엔진을 사용하는데 이는 네이티브와 동일한 C++언어로 작성되어있다. 그래서 따로 변환할 필요 없이 네이티브 함수를 직접 호출하여 사용한다. 또한 비동기는 물론 동기 처리까지 가능하여 즉시 결과 사용이 가능하다(ex. 레이아웃, 애니메이션 프레임 계산 등). 그래서 라이브러리를 사용하게될 때도 JSI 기반의 라이브러리를 사용하는 것이 효율적이다.

- JS에서 처리하는 게 많아지면 JSI의 수행도 많아진다. 그래서 js에서 처리해야하는 것, 네이티브에서 처리해야하는 것을 구분짓고 판단할 수 있어야한다. 

 

 

Shadow thread(백그라운드 스레드)

- 레이아웃 계산, flexbox 처리 등 화면을 그리기전 계산하는 역할이다. 화면을 그리는 메인 스레드를 도와준다고 생각하면 쉽다.

- 리액트 네이티브에서는 css방식과 유사하지만 css엔진이 아닌 Yoga라는 크로스 플랫폼 레이아웃 엔진을 사용한다. ios는 UIkit, android는 View System으로 레이아웃을 계산한다. 이들은 css를 모르기 때문에 공통으로 레이아웃을 계산하기 위해서 Yoga를 사용한다.

 

 

Main thread

- 실제로 화면을 그리는 작업으로 화면그리기, 터치/스크롤, 애니메이션 등을 수행한다.

- 너무 많은 레이아웃작업, 무거운 네이티브 연산 시 블로킹되는데, 이때 화면이 멈추거나 스크롤이 안되거나 터치 반응이 없다. 이 경우 백그라운드 스레드로 분리하거나 리렌더를 줄이는 작업을 해야한다.

 

 

 

리액트 네이티브 작동원리를 왜 알아야할까

 

리액트 네이티브 작업을 하면서 스크롤이 버벅이거나 터치 반응이 느리거나 하는 등의 현상이 일어나기 마련이다. 이때 js스레드와 백그라운드 스레드, 메인 스레드 각각의 역할을 알고 구분지어 판단할 수 있어야한다.

예를 들어 onScroll에서 setState를 사용하게 될 경우 초당 수십번의 렌더링 작업을 js 스레드에서 하게된다. js 스레드 과부화는 애니메이션이나 스크롤이 끊겨보이게 만든다. 이럴 경우 js 스레드가 아닌 메인스레드를 타는 Reanimated를 사용하거나 ref, throttle 등으로 불필요한 렌더링을 줄여야 한다는 것을 알고 적용시킬줄 알아야한다.