정보실

웹학교

정보실

Reactjs Fiber는 React 16의 새로운 재조정 엔진입니다

본문

React Fiber Architecture 


소개 

React Fiber는 React의 핵심 알고리즘을 지속적으로 다시 구현한 것입니다. React 팀이 2 년간 연구한 결과입니다.


React Fiber의 목표는 애니메이션, 레이아웃 및 제스처와 같은 영역에 대한 적합성을 높이는 것입니다. 헤드 라인 기능은 증분 렌더링(incremental rendering)입니다. 렌더링 작업을 청크로 분할하여 여러 프레임에 분산 시키는 기능입니다.


다른 주요 기능으로는 새로운 업데이트가 들어 오면 작업을 일시 중지, 중단 또는 재사용 하는 기능이 있습니다. 다른 유형의 업데이트에 우선 순위를 할당하는 기능; 그리고 새로운 동시성 프리미티브.


https://github.com/acdlite/react-fiber-architecture 


이 문서에 대하여 


Fiber는 코드를 살펴 보는 것 만으로는 어려운 몇 가지 새로운 개념을 소개합니다. 이 문서는 React 프로젝트에서 Fiber의 구현과 함께 수행 한 메모 모음으로 시작되었습니다. 그것이 자라면서 나는 그것이 다른 사람들에게도 도움이 될 수 있다는 것을 깨달았습니다.


가능한 가장 명확한 언어를 사용하고 핵심 용어를 명시적으로 정의하여 전문 용어를 피하려고 합니다. 또한 가능한 경우 외부 리소스에 크게 연결됩니다.


본인은 React 팀에 소속되어 있지 않으며 어떠한 권한도 말하지 마십시오. 이 문서는 공식 문서가 아닙니다. React 팀 구성원에게 정확성을 검토하도록 요청했습니다.


이것은 또한 진행 중인 작업입니다. 파이버는 진행되기 전에 진행 중인 프로젝트로 상당한 리팩터링을 거칠 것입니다. 여기에 디자인을 문서화하려는 시도도 진행 중입니다. 개선과 제안은 매우 환영합니다.


필자의 목표는 이 문서를 읽은 후에는 구현 될 때 따라야 할 Fiber를 충분히 이해하고 결국 React에 기여할 수 있다는 것입니다.


전제 조건 


계속하기 전에 다음 자료를 숙지하시기 바랍니다.

  • React Components, Elements, and Instances - "구성 요소"는 종종 오버로드 된 용어입니다. 이러한 용어를 확실히 파악하는 것이 중요합니다.
  • Reconciliation-React의 조정 알고리즘에 대한 높은 수준의 설명입니다.
  • React 기본 이론 개념-구현 부담이 없는 React의 개념적 모델에 대한 설명. 이 중 일부는 처음 읽을 때는 의미가 없을 수 있습니다. 괜찮습니다. 시간이 지날수록 더 의미가 있습니다.
  • React Design Principles-일정에 관한 섹션에 특별한 주의를 기울이십시오. React Fiber의 이유를 설명하는 데 큰 도움이 됩니다.

리뷰 


아직 전제 조건 섹션을 확인하십시오.

새로운 내용을 살펴보기 전에 몇 가지 개념을 살펴 보겠습니다.


reconciliation이란 무엇입니까? 


reconciliation 

React 알고리즘은 한 트리를 다른 트리와 비교하여 변경해야 할 부분을 결정하는 데 사용합니다.


update 

React 앱을 렌더링 하는 데 사용 된 데이터 변경. 일반적으로`setState`의 결과입니다. 결국 다시 렌더링 합니다.


React API의 중심 아이디어는 업데이트가 전체 앱을 다시 렌더링 하는 것처럼 생각하는 것입니다. 이를 통해 개발자는 앱을 특정 상태에서 다른 상태 (A에서 B, B에서 C, C에서 A 등)로 효율적으로 전환하는 방법에 대해 걱정하지 않고 선언적으로 추론 할 수 있습니다.


실제로 변경 될 때마다 전체 앱을 다시 렌더링 하는 것은 가장 사소한 앱에서만 작동합니다. 실제 앱에서는 성능면에서 엄청나게 많은 비용이 듭니다. React에는 뛰어난 성능을 유지하면서 전체 앱을 다시 렌더링 하는 것처럼 보이는 최적화 기능이 있습니다. 이러한 최적화의 대부분은 조정(reconciliation)이라는 프로세스의 일부입니다.


조정은 "가상 DOM"으로 널리 이해되는 알고리즘입니다. 높은 수준의 설명은 다음과 같습니다. React 애플리케이션을 렌더링 할 때 앱을 설명하는 노드 트리가 생성되어 메모리에 저장됩니다. 그런 다음 이 트리는 렌더링 환경으로 플러시됩니다 (예 : 브라우저 응용 프로그램의 경우 DOM 작업 세트로 변환 됨). 앱이 업데이트되면 (일반적으로 setState를 통해) 새 트리가 생성됩니다. 새 트리는 이전 트리와 비교하여 렌더링 된 앱을 업데이트하는 데 필요한 작업을 계산합니다.


Fiber는 조정자의 기본 재 작성이지만 React 문서에 설명 된 고급 알고리즘은 거의 동일합니다. 핵심 사항은 다음과 같습니다.

  • 다른 컴포넌트 유형은 실질적으로 다른 트리를 생성한다고 가정합니다. React는 diff를 시도하지 않고 오래된 트리를 완전히 바꿉니다.
  • 리스트의 복사는 키를 사용하여 수행됩니다. 키는 "안정적이고 예측 가능하며 고유해야 합니다."


조정과 렌더링 


DOM은 React가 렌더링 할 수 있는 렌더링 환경 중 하나이며 다른 주요 대상은 React Native를 통한 기본 iOS 및 Android보기입니다. (이것이 "가상 DOM"이 약간 잘못된 이유입니다.)


너무 많은 대상을 지원할 수 있는 이유는 조정 및 렌더링이 별도의 단계가 되도록 React가 설계 되었기 때문입니다. 조정자는 트리의 어떤 부분이 변경되었는지 계산하는 작업을 수행합니다. 그런 다음 렌더러는 해당 정보를 사용하여 실제로 렌더링 된 앱을 업데이트합니다.


이러한 분리는 React DOM과 React Native가 React 코어에서 제공하는 동일한 조정자를 공유하면서 자체 렌더러를 사용할 수 있음을 의미합니다.


Fiber는 조정자를 다시 구현합니다. 렌더러는 새로운 아키텍처를 지원 (및 활용)하기 위해 변경해야 하지만 렌더링에는 주로 관심이 없습니다.


스케줄링 


scheduling 

작업 수행 시기를 결정하는 프로세스.


work 

수행 해야 하는 모든 계산 작업은 일반적으로 업데이트의 결과입니다 (예 : setState).


React의 Design Principles 문서는 이 주제에 대해 너무 훌륭하므로 여기에서 인용하겠습니다.


현재 구현에서 React는 트리를 재귀 적으로 안내하고 단일 틱 동안 전체 업데이트 된 트리의 렌더링 함수를 호출합니다. 그러나 앞으로는 프레임 삭제를 피하기 위해 일부 업데이트가 지연 될 수 있습니다. 


이것은 React 디자인에서 일반적인 테마입니다. 일부 인기 있는 라이브러리는 새 데이터를 사용할 수 있을 때 계산이 수행되는 "푸시"방식을 구현합니다. 그러나 React은 필요할 때까지 계산이 지연 될 수 있는 "풀 (pull)"접근 방식을 고수합니다. 


React은 일반적인 데이터 처리 라이브러리가 아닙니다. 사용자 인터페이스를 구축하기 위한 라이브러리입니다. 우리는 현재 어떤 계산이 관련이 있고 어떤 계산이 관련이 없는지 알기 위해 앱에 고유하게 위치한다고 생각합니다. 


화면이 오프 스크린인 경우 관련된 로직을 지연 시킬 수 있습니다. 데이터가 프레임 속도보다 빠르게 도착하면 업데이트를 통합하고 배치 할 수 있습니다. 프레임 드롭을 피하기 위해 덜 중요한 백그라운드 작업 (예 : 네트워크에서 로드 된 새 내용 렌더링)보다 사용자 상호 작용 (예 : 단추 클릭으로 인한 애니메이션)에서 발생하는 작업의 우선 순위를 지정할 수 있습니다. 


핵심 사항은 다음과 같습니다.

  • UI에서는 모든 업데이트를 즉시 적용 할 필요는 없습니다. 실제로 그렇게 하면 낭비가 발생하여 프레임이 떨어지고 사용자 경험이 저하 될 수 있습니다.
  • 업데이트 유형마다 우선 순위가 다릅니다. 애니메이션 업데이트는 데이터 저장소 업데이트보다 더 빨리 완료해야 합니다.
  • 푸시 기반 접근 방식을 사용하려면 앱 (사용자, 프로그래머)이 작업 예약 방법을 결정해야 합니다. 풀 기반 접근 방식을 사용하면 프레임 워크 (React)가 현명하고 결정을 내릴 수 있습니다.

React는 현재 중요한 방식으로 스케줄링을 활용하지 않습니다. 업데이트하면 전체 하위 트리가 즉시 다시 렌더링 됩니다. 스케줄링을 활용하기 위한 React의 핵심 알고리즘을 정밀 검사하는 것이 Fiber의 원동력입니다.


이제 우리는 Fiber의 구현으로 뛰어들 준비가 되었습니다. 다음 섹션은 지금까지 설명한 내용보다 기술적 인 내용입니다. 계속하기 전에 이전 자료에 익숙한 지 확인하십시오.


fiber 란? 


우리는 React Fiber 아키텍처의 핵심을 논의하려고 합니다. Fiber는 응용 프로그램 개발자가 일반적으로 생각하는 것보다 훨씬 낮은 수준의 추상화입니다. 당신이 그것을 이해하려는 시도에 좌절감을 느낀다면 실망하지 마십시오. 계속 노력하면 결국 이해가 될 것입니다. (마지막으로 받으면 이 섹션을 개선하는 방법을 제안하십시오.)


Fiber의 기본 목표는 React가 스케줄링을 활용할 수 있도록 하는 것입니다. 구체적으로, 우리는

  • 작업을 일시 중지하고 나중에 다시 오십시오.
  • 다른 유형의 작업에 우선 순위를 부여하십시오.
  • 이전에 완료 한 작업을 재사용 하십시오.
  • 더 이상 필요하지 않으면 작업을 중단하십시오.

이 작업을 수행하려면 먼저 작업을 단위로 분류 할 수 있는 방법이 필요합니다. 어떤 의미에서, 그것은 섬유입니다. 섬유는 작업 단위를 나타냅니다.


더 나아가서, React 컴포넌트를 데이터의 함수로 개념으로 돌아가 보자.


v = f(d)

React 앱을 렌더링 하는 것은 본문에 다른 함수에 대한 호출 등이 포함 된 함수를 호출하는 것과 유사합니다. 이 비유는 섬유에 대해 생각할 때 유용합니다.


컴퓨터가 일반적으로 프로그램의 실행을 추적하는 방법은 콜 스택을 사용하는 것입니다. 함수가 실행되면 새로운 스택 프레임이 스택에 추가됩니다. 이 스택 프레임은 해당 기능에 의해 수행되는 작업을 나타냅니다.


UI를 다룰 때 문제는 한 번에 너무 많은 작업이 실행되면 애니메이션이 프레임을 떨어 뜨리고 고르지 않게 보일 수 있다는 것입니다. 또한 최신 업데이트로 대체 된 작업 중 일부는 불필요 할 수 있습니다. UI 구성 요소와 기능 간의 비교가 실패하는 경우가 있습니다. 구성 요소는 일반적으로 기능보다 더 구체적인 문제가 있기 때문입니다.


최신 브라우저 (및 React Native)는이 정확한 문제를 해결하는 데 도움이 되는 API를 구현합니다. requestIdleCallback은 유휴 기간 동안 낮은 우선 순위 함수가 호출되도록 예약하고 requestAnimationFrame은 다음 애니메이션 프레임에서 우선 순위가 높은 함수가 호출되도록 예약합니다. 문제는 이러한 API를 사용하려면 렌더링 작업을 증분 단위로 나누는 방법이 필요하다는 것입니다. 호출 스택에만 의존하는 경우 스택이 비워 질 때까지 계속 작동합니다.


UI 렌더링에 최적화되도록 호출 스택의 동작을 사용자 정의 할 수 있다면 좋지 않을까요? 콜 스택을 마음대로 중단하고 스택 프레임을 수동으로 조작 할 수 있다면 좋지 않을까요?


이것이 React Fiber의 목적입니다. 파이버는 스택을 다시 구현하여 React 구성 요소에 특화되어 있습니다. 단일 파이버를 가상 스택 프레임으로 생각할 수 있습니다.


스택을 다시 구현하면 스택 프레임을 메모리에 유지하고 원하는 대로 (그리고 언제든지) 실행할 수 있다는 장점이 있습니다. 이것은 우리가 일정에 대한 목표를 달성하는 데 중요합니다.


스케줄링 외에도 스택 프레임을 수동으로 처리하면 동시성 및 오류 경계와 같은 기능의 잠재력이 발휘됩니다. 다음 섹션에서 이러한 주제를 다룰 것입니다.


다음 섹션에서는 fiber의 구조를 자세히 살펴 보겠습니다.


fiber의 구조 


참고 : 구현 세부 사항에 대해 보다 구체적으로 설명하면 변경 될 수 있는 가능성이 증가합니다. 실수나 오래된 정보가 발견되면 PR을 제출하십시오.


구체적으로 말하면 fiber는 구성 요소, 입력 및 출력에 대한 정보를 포함하는 JavaScript 객체입니다.


fiber는 스택 프레임에 해당하지만 구성 요소의 인스턴스에도 해당합니다.


다음은 fiber에 속하는 중요한 필드 중 일부입니다. (이 목록은 전체가 아닙니다.)


type and key 


파이버의 유형과 키는 React 요소와 동일한 용도로 사용됩니다. 실제로, 요소에서 파이버가 작성되면 이 두 필드가 직접 복사 됩니다.


파이버의 유형은 해당 구성 요소를 설명합니다. 복합 컴포넌트의 경우 유형은 함수 또는 클래스 컴포넌트 자체입니다. 호스트 구성 요소 (div, span 등)의 경우 유형은 문자열입니다.


개념적으로, 유형은 스택 프레임에 의해 실행이 추적 되는 함수 (v = f (d)에서와 같이)입니다.


유형과 함께 키는 조정 중에 섬유를 재사용 할 수 있는지 여부를 결정하는 데 사용됩니다.


child and sibling 


이 필드는 다른 fiber를 가리키며 fiber의 재귀 트리 구조를 설명합니다.


자식 파이버는 컴포넌트의 render 메소드에 의해 리턴 된 값에 해당합니다. 다음 예제에서


function Parent() {
  return <Child />
}


부모의 자식 fiber는 자식에 해당합니다.


형제 필드는 render가 여러 자식 (Fibre의 새로운 기능)을 반환하는 경우를 설명합니다.


function Parent() {
  return [<Child1 />, <Child2 />]
}


아이 fiber는 머리가 첫 번째 아이인 단일 연결리스트를 형성합니다. 따라서 이 예에서 Parent의 자식은 Child1이고 Child1의 형제는 Child2입니다.


우리의 기능 비유로 돌아가서, 어린이 fiber를 꼬리라고 불리는 기능이라고 생각할 수 있습니다.


return 


리턴 파이버는 현재 파이버를 처리 한 후 프로그램이 리턴해야 하는 파이버입니다. 개념적으로 스택 프레임의 반환 주소와 같습니다. 모체 파이버로 생각할 수도 있습니다.


파이버에 여러 개의 파이버 파이버가 있는 경우 각 파이버 파이버의 파이버 파이버가 상위입니다. 이전 섹션의 예에서 Child1 및 Child2의 리턴 파이버는 Parent입니다.


pendingProps and memoizedProps 


개념적으로 props은 함수의 인수입니다. 파이버의 보류중인 props은 실행 시작시 설정되고 memoizedProps는 마지막에 설정됩니다.


수신 보류중인 Props가 memoizedProps와 같으면 fiber의 이전 출력을 재사용 할 수 있다는 신호를 보내 불필요한 작업을 방지합니다.


pendingWorkPriority 


fiber로 표시되는 작업의 우선 순위를 나타내는 숫자입니다. ReactPriorityLevel 모듈은 다양한 우선 순위 레벨과 이들이 나타내는 것을 나열합니다.

NoWork(0)를 제외하고 숫자가 클수록 우선 순위가 낮습니다. 예를 들어, 다음 기능을 사용하여 fiber의 우선 순위가 주어진 수준 이상인지 확인할 수 있습니다.


function matchesPriority(fiber, priority) {
  return fiber.pendingWorkPriority !== 0 &&
         fiber.pendingWorkPriority <= priority
}


이 함수는 예시 용입니다. 실제로 React Fiber 코드베이스의 일부가 아닙니다.


스케줄러는 우선 순위 필드를 사용하여 수행 할 다음 작업 단위를 검색합니다. 이 알고리즘은 다음 섹션에서 논의 될 것입니다.


alternate 


flush 

fiber를 플러시 하려면 출력을 화면에 렌더링 해야 합니다.


work-in-progress 


아직 완성되지 않은 섬유; 개념적으로 스택 프레임은 아직 반환 되지 않았습니다.


구성 요소 인스턴스에는 현재 최대 2 개의 광섬유가 있습니다 : 현재, 플러시 된 섬유 및 진행 중인 작업 섬유.


현재 fiber의 대안은 진행 중인 작업이고 진행 중인 대안의 대안은 현재 fiber입니다.


fiber의 대체물은 cloneFiber라는 함수를 사용하여 느리게 생성됩니다. cloneFiber는 항상 새 객체를 생성하지 않고 파이버의 대체물이 있는 경우 재사용을 시도하여 할당을 최소화합니다.


대체 필드를 구현 세부 사항으로 생각해야 하지만 코드베이스에서 자주 팝업 되어 여기에서 논의 할 가치가 있습니다.


output 


host component 


React 애플리케이션의 리프 노드 렌더링 환경에 따라 다릅니다 (예 : 브라우저 앱에서`div`,`span` 등). JSX에서는 소문자 태그 이름을 사용하여 표시됩니다.


개념적으로 섬유의 출력은 함수의 반환 값입니다.


모든 파이버에는 결국 출력이 있지만 호스트 구성 요소에 의해 리프 노드에서만 출력이 생성됩니다. 그런 다음 출력이 트리 위로 전송됩니다.


결과는 렌더링 환경에 대한 변경 사항을 플러시 할 수 있도록 결국 렌더러에 제공됩니다. 출력 생성 및 업데이트 방법을 정의하는 것은 렌더러의 책임입니다.


미래 섹션 


그게 전부입니다. 그러나 이 문서는 아직 완성되지 않았습니다. 다음 섹션에서는 업데이트 수명 주기 동안 사용되는 알고리즘에 대해 설명합니다. 다루어야 할 주제는 다음과 같습니다.

  • 스케줄러가 수행 할 다음 작업 단위를 찾는 방법
  • 파이버 트리를 통해 우선 순위를 추적하고 전파하는 방법
  • 스케줄러가 작업 일시 정지 및 재개시기를 아는 방법
  • 작업이 세척되고 완료된 것으로 표시되는 방법
  • 부작용 (예 : 수명 주기 방법)의 작동 방식
  • 코 루틴이란 무엇이며 컨텍스트 및 레이아웃과 같은 기능을 구현하는 데 어떻게 사용할 수 있습니까?

관련 비디오 








  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 9회 ]  작성일19-09-08 23:02

웹학교