리엑트가 프레임워크 뒤에서 렌더링 될 때 진행되는 과정은 뭘까? 박스안에 든 과정에 대해서 알아보기 위해서 리엑트의 랜더링 과정, 재조정에 대해서 공부해 보았다.
💡컴포넌트에서 반환된 JSX는 어떻게 DOM에 그려지는 걸까
💡컴포넌트가 수정되고 삭제될 때는 어떻게 최적화가 되길래 reconciliation 이라고 하는 걸까?
리엑트는 상태가 변경되면 돔이 랜더링된다는 규칙으로 동작하는 프레임워크이다. 상태기반 프레임워크이다. 그 중 랜더링된다의 과정에서 어떤 단계로 진행되는지 알아보겠다.
첫번째로 어떠한 내용을 랜더링 할 지 결정하는 Element객체를 생성하게 된다.
두번째로는 생성(또는 변경)된 Element객체 새롭게 반영하는 Render 순서를 거치게 된다.
마지막으로 이렇게 변경된 내용을 dom에 반영하는 Commit 과정을 진행한다.
이렇게 크게 세 순서로 랜더링이 된다. 1,2의 순서는 같은 레벨로 볼 수도 있지만, Render의 과정이 이해할 부분이 많아서 나누어서 정리해 보기로 했다.
React.createElement
를 호출하는 과정의 구현체라고 할 수 있다. 즉 ReactElement
를 반환하게 되는데.여기서 정말 많은 일들이 생긴다. Reconciliation 과정도 render에서 발생된다.
일단 Render! 라고 하면 화면에 그리는 작업일 것 같지만. 트리를 구성하는 과정에 가깝다고 이해했다. 컴포넌트를 순회하면서 Root에 추가하면서 트리를 만들어 나가는 과정이다.
그런데 그냥 쭉 추가하게 되면 모든 Element 순회가 끝날 때 까지 메인스레드를 점유하는 이슈가 발생한다.
그래서 이런 부분을 해소하기 위해서 React v16에서는 Schedular Package를 사용해서 작업을 비동기로 처리한다. (이전 버전은 requestIdleCallback)
이렇게 메인 스레드 점유에 대한 부분은 해결했지만, React team에서는 비동기 작업들이 스택에 들어가기 위해 큐에서 오래 대기해야 하는 버벅거리는 이슈를 해결하고자 한다
사실 이런 부분은 javascript가 싱글스레드로 동작하기 때문에 발생하는 이슈이기 때문에 React 자체의 문제는 아니지만 Facebook팀에서는 이런 문제를 해결해보려고 시도했다고 한다.
Facebook Fiber 영상
그래서 도입한 개념이 FIBER이다.
💡rendering 작업을 chunk로 나누어서 작업하도록 함
💡컴포넌트를 업데이트 하는 과정에서 우선순위가 더 높은 것을 먼저 작업하도록 하자
이렇게 두가지를 수행하는 FIBER를 도입하고자 하였다.
우선 Fiber Tree는 형제,자매 부모 노드를 알고있는 트리이다. Fiber Tree는 부모노드로 시작해서 다시 부모노드에 도착했을 때 순회가 완료되는 것으로 하는데, 완성된 fiber tree는 nextUnitOfWork(커밋단위)가된다.
reconciliation은 working progress tree와 이전에 저장해 두었던 트리를 비교하면서 변경된 지점들이 있는지 확인하고 그 변경점들을 태그해서 변경된 부분만 적용되도록 조정하는 것을 말한다.
이전의 트리와 비교하면서 fiber tree에 수정 추가에 대한 태그를 달아준게 되고. 삭제는 새로운 fiber tree에는 없기 때문에 삭제되는 Element를 배열로 관리한다.
render된 하나의 Fiber Tree는 하나의 unit으로 모두 생성되야 커밋이 될 수 있다.
Schedular에서 priority level 을 결정하고
하위 순위의 작업은 requestIdleCallback이 수행하는 방식으로 우선순위가 높은 것을 먼저 수행하게 된다.
Render 과정
- Fiber Tree(Work in progress tree)를 만들고 변경된 점을 태그로 표시해 두는 과정
- 따로 DOM에 반영되지 않는다.
- 중간에 중지 될 수 있음
- 이전에 tree와 비교해서 reconciliation 이 발생
Fiber tree를 dom 에 커밋(반영)하고 그 정보를 저장하는 단계이다. 해당 단계에서 dom tree에 반영되므로 UI를 일관적으로 유지하기 위해서 중간에 interrupt 될 수 없다.