React를 매번 사용하면서 렌더링이 어떤 방식으로 동작하는지 알지 못했는데 여러 포스팅을 읽다가 Fiber라는 키워드를 발견하고 공부하게 되어서 포스팅을 작성했다. 다만 Fiber는 react v16에서 업데이트된 내용으로 사실 내가 React를 처음 사용할때부터 함께해왔던 존재였다.
Fiber 소개영상 : https://youtu.be/ZCuYPiUIONs
재조정(reconciliation)이란, React에서 매우 중요한 개념 중 하나로 UI에서 변경 사항이 발생하면 DOM 과 Virtual DOM을 비교하여 변경 사항을 식별하고 업데이트하는 과정을 뜻한다.
재조정과 렌더링은 각각 reconciler
모듈과 renderer
모듈로 분리되어 실행된다.
React v16 이전의 reconciler
모듈은 Stack Reconciler
라는 모듈이었다.
Stack Reconciler의 문제점은 virtual DOM 트리를 비교하고 변경 사항을 적용하는 과정에서 모든 작업을 동기적으로, 하나의 큰 테스크로 진행한다는 점이다. 이렇게 큰 태스크는 깊은 콜 스택을 만들게 되고 콜 스택이 모두 처리될때 까지 메인 스레드는 아무작업도 할 수 없게 된다.
일반적으로 Reconciler and Renderer 과정은 매우 빠르게 일어나기 때문에 보통의 경우라면 느끼기 어렵지만 연속적인 애니메이션과 많은 DOM조작이 필요한 경우 콜 스택이 모두 처리될때 까지 메인 스레드는 아무작업을 할 수 없게 되니 버벅임을 느낄 수 있게 된다.
React 팀은 이 현상을 해결하기 위해 증분 렌더링(Incremental Rendering)
을 고안하게 되었고 그 과정에서 Fiber Reconciler
로 reconciler
모듈이 변경되었다.
왼쪽 Stack Reconciler / 오른쪽 Fiber Reconciler
증분 렌더링(Incremental Rendering)
를 구현하기 위해서는 작업을 일시정지하고 나중에 다시 시작할 수 있어야 했다. 또 이전에 완료된 작업을 재사용하거나 필요하지 않은 경우 중단 할 수 있어야 했다. 그래서 도입된게 Fiber
이다.
Mathpresso 프론트앤드 개발자 베일리님의 CodePen
Fiber는 React에서 작업의 단위이며, JavaSrciprt 객체이다. console에서 요소를 불러와 직접 확인할 수 있다.
requestAnimationFrame
함수를 통해 우선순위가 높은 함수를 예약할 수 있다.requestIdleCallback
함수를 통해 유휴 기간동안 호출한 우선순위가 낮은 함수를 예약할 수 있다.(두 함수를 지원하지 않는 브라우저의 경우 폴리필을 제공한다.)두가지 단계로 나누어져 있다.
Fiber는current
와 workInProgress
두가지 트리를 가지고 있다.
current
트리는 현재 화면에 있는 것으로 React가 변경 하면 안정성을 보장 할 수 없기 때문에 복사본인 workInProgress
트리를 만들어서 작업하게 된다.
Render Phase는 비동기적으로 동작하며 두 fiber 트리를 비교하고 변경된 Effect들을 수집하는 작업을 한다. 리액트 scheduler로 인해 허용되는 시간 동안 작업하고 user input, animation 같은 더 급한 작업이 있다면 해당 작업에게 메인 스레드를 양보한다.
Effect는 Dom을 변경하거나 특정 생명 주기 메서드를 호출하는 것 같은 활동이다. 이러한 활동은 부작용(Side Effect)라고 부르며 다른 구성요소에 영향을 미칠 수 있으며 렌더링 중에는 실행할 수 없다.
( 예외는 존재한다. 렌더링 메소드 자체나 shouldComponentUpadte 메소드는 렌더링 단계 중에 호출된다. )
위 과정에서 React가 언제라도 workInProgress
트리 내부 변경사항을 버릴 수 있기 때문에 Dom 또는 componentDidMount 같은 생명 주기 메서드에 대한 변경사항은 렌더링 단계중에서 실행 할 수 없다.
커밋 단계에서는 렌더 단계에서 수집한 Effect와 변경된 정보를 가지고 있는 Fiber를 통해 Effect를 실행하고 Dom에 적용하는 단계를 거친다. 이 단계는 동기적으로 한번에 이루어지기 때문에 일시정지하거나 취소할 수 없다.
Commit 후에는 workInProgress
트리가 현재(current)의 트리가 된다.
Commit Phase에서 교체되는 두 트리
Reference
https://blog.mathpresso.com/react-deep-dive-fiber-88860f6edbd0
https://www.theteams.kr/teams/7792/post/70621
https://youtu.be/ZCuYPiUIONs
https://youtu.be/0ympFIwQFJw