프론트엔드/React

[React] Rendering (렌더링 동작원리)(2)

zero2-pooh 2023. 6. 10. 17:26

리액트 렌더링의 동작원리에 대해 포스팅 중인데.. 아니 너무 많다..^^ 뭐가 너무 많아.. 양파 같아 정말😞

여태 리액트에 대해 아무것도 모르고 있었구나 라는 생각이 많이 든다. 그런 의미에서 반성하며 다시 포스팅 끄적여야지

 

이번 포스팅은 지난번에 적은 렌더링 동작원리(1)에 이은 2편을 적을 예정이다.

 


📄 목차

1. 재귀적 처리

2. key diff

3. Fibers

3-1. Fiber의 구조


1. 재귀적 처리

- DOM 노드의 자식들을 재귀적으로 처리할 때, React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경된 부분을 갱신한다.

아래 코드들은 react 문서에서 가져왔다.

 

// 전 DOM
<ul>
  <li>first</li>
  <li>second</li>
</ul>

// 후 DOM
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

위에서부터 비교하다가 새로운 트리에서 third가 생겼으므로

마지막인 <li>third</li>  만 돔트리에 추가한다. 

 

❗️하지만 위와 같이 단순하게 구현하면, 리스트의 맨 앞에 엘리먼트를 추가하는 경우 성능이 좋지 않다. 


 

2. key diff

위의 문제를 해결하기 위해, React는 key 속성을 지원한다.

자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인한다.

예를 들어, 위 비효율적인 예시에 key를 추가하여 트리의 변환 작업이 효율적으로 수행되도록 수정할 수 있다.

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

~~ 이렇게 react는 key='2014'인 엘리먼트가 추가되었고 key='2015'와 key='2016'인 엘리먼트는 이제 이동하기만 하면 된다는 것을 알게 된다. 

 

다만❗️이 key는 (같은 부모 안에서) 고유하면서 불변하는 값으로 설정해야 한다. 

 


3. Fibers (React v16부터는 Fiber)

❓Fiber 란?

- Fiber는 React v16에서 리액트의 핵심 알고리즘을 재구성한 새 재조정(Reconciliation) 엔진이다.

React Fiber의 목표는 애니메이션, 레이아웃, 제스처, 중단 또는 재사용 기능과 같은 영역에 대한 적합성을 높이고 다양한 유형의 업데이트에 우선순위를 지정하는 것이다.

 

✔️Virtual DOM의 전체과정도 재조정(Reconciliation)이라 한다.

 

💡핵심 기능
- 랜더링을 증분 하는 것. 즉 랜더링 작업을 여러 덩어리로 나누어 여러 프레임에 분산하는 기능. 

Fiber의 주요 목표는 다음과 같다.

 

1. 중단 가능한 작업을 덩어리로 나누기
2. 진행 중인 작업의 우선순위를 지정하고, 리베이스하고 재사용
3. 리액트의 레이아웃을 지원하기 위해 부모와 자식 간에 yield back and forth
4. render()로부터 다수 엘리먼트들을 반환
5. 에러 바운더리에 대한 더 나은 지원

 

 

➕그리고 구체적으로는 다음과 같은 일을 할 수 있어야 한다.

 

- 일을 잠시 멈추고 나중에 다시 돌아오기

- 다른 유형의 일에 우선권 부여하기

- 이전에 완성한 작업을 재사용하기

- 더 이상 필요하지 않은 작업을 중단하기

 

이것들을 하기 위해선, 먼저 단위별로 세분화해야 하며, 이 과정 자체가 Fiber라고 할 수 있다.

Fiber는 이처럼 작업의 한 단위(unit of work)를 나타낸다.

 

 


컴퓨터가 프로그램 실행을 추적할 때 일반적으로 Call Stack을 사용한다. 함수가 실행되면 스택에 새 stack frame이 추가된다.

(stack frame은 해당 함수에 의해 수행되는 작업을 의미한다).

 

- UI 렌더링에 최적화되도록 Call Stack의 동작을 사용자 지정할 수 있다면 좋지 않을까?

- Call Stack과 stack 프레임을 조작할 수 있다면 좋지 않을까?

 

그것이 Fiber의 목적이다.

Fiber는 리액트 컴포넌트에 특화된 stack의 재구성이다. 하나의 Fiber를 virtaul stack frame으로 간주할 수 있다.

stack을 재구성함으로써 얻는 이점은 stack frame을 메모리에 보관하고 원하는 경우 언제든지 실행할 수 있다는 것이다.

이는 스케줄링 목표를 달성하는 데 매우 중요하다.

 

stack frame을 수동으로 처리하면 스케줄링뿐만 아니라 concurrency 및 error boundary와 같은 기능들에 대한 잠재력을 확보할 수 있다. 

 


3-1. Fiber의 구조

Fiber는 컴포넌트 및 컴포넌트의 입력과 출력에 대한 정보를 포함한 자바스크립트 객체이다.

Fiber는 stack frame이기도 하지만, 컴포넌트의 인스턴스이기도 하다.

Fiber에 속하는 중요한 field들은 다음과 같다.

 

 

'type'과 'key'

Fiber의 type과 key는 리액트 요소에 그것들과 비슷하다. 

type 및 key는 재조정 시에 fiber가 재사용될 수 있는지 판단할 때 사용된다.

 

 

 

참고 

https://narup.tistory.com/272

https://www.nextree.io/riaegteu-rendeoring-mic-coejeoghwa/
https://eastflag.co.kr/react/script-tag/react-element/

https://ko.legacy.reactjs.org/docs/rendering-elements.html#gatsby-focus-wrapper

https://programming119.tistory.com/240

https://velog.io/@jangws/React-Fiber