본문 바로가기
Front-End/React

[React] React Fiber Reconciler

by SeanK 2023. 6. 16.

안녕하세요 :) 오늘은 React는 어떻게 ui의 변화를 감지하고 화면을 렌더링 하는지 조금 더 깊이 공부하기 위해 Fiber Reconciler에 대해 공부해 보았습니다. Fiber Reconciler을 이해하기 이전에 미리 알아두어야 할 내용이 있어 먼저 정리하고 가도록 하겠습니다.

Diffing

리엑트가 가상 dom 트리를 이용해 효율적인 dom tree 리렌더링을 지원한다는 사실은 조금만 공부해 보신 분들이라도 다들 알고 있는 내용일 겁니다. 여기서 가상 dom 트리와 실제 dom 트리를 "비교한다"는 개념을 diffing이라고 합니다. 즉 두 개의 차이를 알아낸다는 의미로 사용됩니다.

Reconciler

Reconciler는 리엑트에서 diffing을 위해 사용하는 "알고리즘"입니다. 가상의 트리와 실제 트리를 비교한는 일은 사실 매우 비싼 작업입니다. 만약 처음 노드부터 끝까지 모든 노드를 비교한다면 시간복잡도 O(n3) 수준의 비용을 감당해야 합니다. 따라서 리엑트 개발자들은 약간의 트릭을 이용해 비용을 O(n)까지 낮추었습니다. 아래 두 개의 가정을 전재로 휴리스틱 한 접근법을 택했기 때문입니다.

Two elements of different types will produce different trees.
- 두개의 다른 타입의 엘리먼트는 다른 트리를 가진다.
The developer can hint at which child elements may be stable across different renders with a key prop
- 개발자는 어떤 엘리먼트가 계속 남아있는지 아닌지를 key prop으로 힌트를 줄 것이다.

그리고 리엑트는 버전을 업그레이드하며 성능이 더 좋은 reconciler를 고안해 냈습니다. 버전 16 이전까지 사용했던 reconciler가 stack reconciler이며 이후에 나온 reconciler가 오늘의 주제인 fiber reconciler입니다.

Stack reconciler

stack reconciler는 fiber reconciler 이전까지 사용된 reconciler입니다. 이름이 stack인 이유는 작동 방식이 stack 구조로 동작했기 때문입니다. 아이템을 추가하고 제거할 수 있었지만 스택이 비워질 때까지 동기적으로 동작했습니다. 중간에 작업을 중단하거나 순서를 변경할 수 없었죠.

 

위의 "동기성"은 stack reconciler의 가장 큰 단점이었습니다. 예를 들어 텍스트 필드가 있다고 가정해 보겠습니다. 만약 하나의 텍스트 필드만 있다면 stack reconciler로도 기능상에 문제가 없을 겁니다. 하지만 백그라운드에 네트워크 요청이 이루어지고 있고 네트워크 리스폰스에 따라 다른 엘리먼트가 렌더링 되는 상황이라면, 텍스트 필드에 문자를 입력하면 사용자는 딜레이를 느끼게 될 것입니다. 왜냐하면 stack reconciler는 네트워크 요청에 따른 엘리먼트 렌더링 작업을 하고 있는 도중이기 때문입니다.

Fiber reconciler

stack reconciler의 단점을 이해한다면 fiber reconciler가 왜 고안되었는지, 어떤 장점을 가지고 있는지 이해가 쉽게 되실 겁니다. 여기서 fiber란 dom 트리의 노드를 뜻하는 fiber에서 따온 단어로 리엑트의 데이터 스트럭쳐 혹은 아키텍쳐를 뜻합니다. fiber reconciler는 아래와 같은 기능을 가지고 있습니다.

  • 향상된 에러 핸들링과 에러 복구
  • dom 노드 컨테이너 내 subtree 랜더링
  • fragments 혹은 strings와 같은 새로운 타입의 render 리턴 지원
  • 렌더 함수로부터 다수의 엘리먼트 리턴

위 내용이 살짝 이해하기 어려우시다면 한가지만 이해하셔도 될 듯합니다. fiber reconciler의 핵심은 "비동기적"으로 리렌더링을 지원한다는 점입니다.

Fiber reconciler 동작 원리

사실 fiber를 들여다보면 몇개의 프로퍼티를 가진 자바스크립트 객체입니다. 그리고 각각의 fiber는 수행해야 할 일의 단위이기도 하죠. 리엑트는 fiber를 모두 수행하고 finishwork()와 같은 함수를 호출해 작업을 마무리합니다. 그러고 나서 리엑트는 수행된 일의 결과를 dom에 적용해 시각적 변화를 일으킵니다. 위 과정을 render phase와 commit phase로 크게 두 가지로 나눌 수 있습니다.

Render phase

render phase는 비동기적입니다. 이 과정에서 리엑트는 유저에게 보이지않는 화면 뒤편에서 모든 비동기적 일들을 수행합니다. 리엑트는 업무의 우선순위를 정하게 되는데 우선순위가 아닌 일은 멈추거나 심지어 더 이상 필요하지 않을 때 버려버리기도 합니다. 이 과정에서 beginWork()나 completeWork()와 같은 함수를 호출하게 됩니다.

Commit phase

render 단계가 끝나면 이제 실재로 업데이트 된 트리를 화면에 적용하는 단계로 넘어가게 됩니다. 이 단계는 commitWork() 함수를 호출하며 시작되고 동기적이며 도중에 그만둘 수 없습니다.

 

리엑트가 fiber를 처리할때는 1. 바로 해당 일을 처리하거나 2. 미래에 처리하도록 던져두게 됩니다. time-slicing이라고 하는 기능으로 일을 청크로 나누어 처리하게 되죠. 만약 애니메이션과 같이 매우 우선적으로 처리해야 하는 일이라면 가급적 빨리 일을 처리하고 네트워크 요청과 같이 중요도가 낮은 작업은 후순위로 미루게 됩니다. 이때 requestAnimationFrame()과 requestIdleCallback() 함수를 이용합니다.

requestAnimationFrame()

우선 순위가 높은 업무의 경우 다음 애니메이션 프레임에 호출되도록 합니다.

requestIdleCallback()

업무가 없어지면 실행하도록 우선순위가 낮은 업무를 스케줄링 합니다.

Fiber 트리

Fiber 트리는 current tree라고 불리는 현재 화면에 표시되는 트리와 workInProgress tree라고 불리는 현재 작업 중인 트리로 나뉩니다. current 트리는 화면에 이미 표시가 되기 때문에 리엑트는 해당 트리를 변형시키지 않습니다. 대신 workInProgress 트리에 Fiber reconsiler가 작업한 내용을 업데이트하고 맨 마지막에 포인터만 스왑 하면 workInProgress는 current 트리가 되고 current 트리는 workInProgress 트리가 됩니다.

 

 

참조:

https://flexiple.com/react/react-fiber/

 

Introduction to React Fiber

In this blog, we look at what react fiber is, we further dive into its purpose, working, features and finally we look at a few FAQs.

flexiple.com

https://www.geeksforgeeks.org/what-is-react-fiber/

 

What is “React Fiber”? - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org