React의 Fiber 아키텍처에 대한 심층 분석으로, reconciliation 프로세스, 이점 및 애플리케이션 성능 개선 방법을 설명합니다.
React Fiber 아키텍처: Reconciliation 프로세스 이해
React는 컴포넌트 기반 아키텍처와 선언적 프로그래밍 모델을 통해 프론트엔드 개발에 혁명을 일으켰습니다. React 효율성의 핵심은 reconciliation 프로세스입니다. reconciliation은 React가 컴포넌트 트리의 변경 사항을 반영하기 위해 실제 DOM을 업데이트하는 메커니즘입니다. 이 프로세스는 상당한 발전을 거쳐 Fiber 아키텍처로 정점을 찍었습니다. 이 기사에서는 React Fiber와 reconciliation에 미치는 영향에 대한 포괄적인 이해를 제공합니다.
Reconciliation이란 무엇입니까?
Reconciliation은 React가 이전 가상 DOM과 새 가상 DOM을 비교하고 실제 DOM을 업데이트하는 데 필요한 최소 변경 사항 집합을 결정하는 데 사용하는 알고리즘입니다. 가상 DOM은 UI의 메모리 내 표현입니다. 컴포넌트의 상태가 변경되면 React는 새 가상 DOM 트리를 만듭니다. React는 느린 프로세스인 실제 DOM을 직접 조작하는 대신 새 가상 DOM 트리를 이전 가상 DOM 트리와 비교하여 차이점을 식별합니다. 이 프로세스를 diffing이라고 합니다.
reconciliation 프로세스는 두 가지 주요 가정을 따릅니다.
- 다른 유형의 요소는 다른 트리를 생성합니다.
- 개발자는
key
prop을 사용하여 서로 다른 렌더링에서 안정적일 수 있는 하위 요소를 힌트할 수 있습니다.
기존 Reconciliation (Fiber 이전)
React의 초기 구현에서 reconciliation 프로세스는 동기식이고 나눌 수 없었습니다. 즉, React가 가상 DOM을 비교하고 실제 DOM을 업데이트하는 프로세스를 시작하면 중단할 수 없었습니다. 이로 인해 특히 큰 컴포넌트 트리가 있는 복잡한 애플리케이션에서 성능 문제가 발생할 수 있습니다. 컴포넌트 업데이트에 시간이 오래 걸리면 브라우저가 응답하지 않아 사용자 경험이 저하됩니다. 이를 종종 "jank" 문제라고 합니다.
제품 카탈로그를 표시하는 복잡한 전자 상거래 웹사이트를 상상해 보십시오. 사용자가 필터와 상호 작용하여 카탈로그의 재 렌더링을 트리거하는 경우 동기식 reconciliation 프로세스는 기본 스레드를 차단하여 전체 카탈로그가 다시 렌더링될 때까지 UI가 응답하지 않을 수 있습니다. 이로 인해 몇 초가 걸릴 수 있으며 사용자에게 불만을 야기할 수 있습니다.
React Fiber 소개
React Fiber는 React 16에 도입된 React reconciliation 알고리즘의 완전한 재작성입니다. 주요 목표는 특히 복잡한 시나리오에서 React 애플리케이션의 응답성과 인지된 성능을 개선하는 것입니다. Fiber는 reconciliation 프로세스를 더 작고 중단 가능한 작업 단위로 분해하여 이를 달성합니다.
React Fiber의 핵심 개념은 다음과 같습니다.
- Fibers: fiber는 작업 단위를 나타내는 JavaScript 객체입니다. 컴포넌트, 해당 입력 및 출력에 대한 정보를 보유합니다. 각 React 컴포넌트에는 해당 fiber가 있습니다.
- WorkLoop: 작업 루프는 fiber 트리를 반복하고 각 fiber에 필요한 작업을 수행하는 루프입니다.
- Scheduling: 스케줄러는 우선 순위에 따라 작업 단위를 시작, 일시 중지, 재개 또는 중단할 시기를 결정합니다.
Fiber 아키텍처의 이점
Fiber 아키텍처는 다음과 같은 몇 가지 중요한 이점을 제공합니다.
- Interruptible Reconciliation: Fiber를 사용하면 React가 reconciliation 프로세스를 일시 중지하고 재개할 수 있으므로 장기 실행 작업이 기본 스레드를 차단하는 것을 방지할 수 있습니다. 이를 통해 복잡한 업데이트 중에도 UI가 응답성을 유지합니다.
- Priority-Based Updates: Fiber를 사용하면 React가 다양한 유형의 업데이트에 우선 순위를 지정할 수 있습니다. 예를 들어, 타이핑 또는 클릭과 같은 사용자 상호 작용은 데이터 가져오기와 같은 백그라운드 작업보다 높은 우선 순위를 가질 수 있습니다. 이렇게 하면 가장 중요한 업데이트가 먼저 처리됩니다.
- Asynchronous Rendering: Fiber를 사용하면 React가 비동기적으로 렌더링을 수행할 수 있습니다. 즉, React는 컴포넌트 렌더링을 시작한 다음 브라우저가 사용자 입력 또는 애니메이션과 같은 다른 작업을 처리하도록 일시 중지할 수 있습니다. 이렇게 하면 애플리케이션의 전반적인 성능과 응답성이 향상됩니다.
- Improved Error Handling: Fiber는 reconciliation 프로세스 중에 더 나은 오류 처리를 제공합니다. 렌더링 중에 오류가 발생하면 React는 더 정상적으로 복구하고 전체 애플리케이션이 충돌하는 것을 방지할 수 있습니다.
협업 문서 편집 애플리케이션을 고려해 보십시오. Fiber를 사용하면 다른 사용자가 만든 편집 내용을 다양한 우선 순위로 처리할 수 있습니다. 현재 사용자의 실시간 입력은 즉각적인 피드백을 보장하는 가장 높은 우선 순위를 얻습니다. 다른 사용자의 업데이트 또는 백그라운드 자동 저장은 활성 사용자의 경험에 대한 중단을 최소화하면서 낮은 우선 순위로 처리할 수 있습니다.
Fiber 구조 이해
각 React 컴포넌트는 Fiber 노드로 표시됩니다. Fiber 노드는 컴포넌트 유형, props, 상태 및 트리에서 다른 Fiber 노드와의 관계에 대한 정보를 보유합니다. 다음은 Fiber 노드의 몇 가지 중요한 속성입니다.
- type: 컴포넌트의 유형(예: 함수 컴포넌트, 클래스 컴포넌트, DOM 요소).
- key: 컴포넌트에 전달된 key prop.
- props: 컴포넌트에 전달된 props.
- stateNode: 컴포넌트의 인스턴스(클래스 컴포넌트의 경우) 또는 null(함수 컴포넌트의 경우).
- child: 첫 번째 자식 Fiber 노드에 대한 포인터.
- sibling: 다음 형제 Fiber 노드에 대한 포인터.
- return: 부모 Fiber 노드에 대한 포인터.
- alternate: 컴포넌트의 이전 상태를 나타내는 Fiber 노드에 대한 포인터.
- effectTag: DOM에서 수행해야 하는 업데이트 유형을 나타내는 플래그.
alternate
속성은 특히 중요합니다. 이를 통해 React는 컴포넌트의 이전 및 현재 상태를 추적할 수 있습니다. reconciliation 프로세스 중에 React는 현재 Fiber 노드를 해당 alternate
와 비교하여 DOM에 적용해야 하는 변경 사항을 결정합니다.
WorkLoop 알고리즘
작업 루프는 Fiber 아키텍처의 핵심입니다. fiber 트리를 트래버스하고 각 fiber에 필요한 작업을 수행하는 역할을 합니다. 작업 루프는 fiber를 한 번에 하나씩 처리하는 재귀 함수로 구현됩니다.
작업 루프는 두 가지 주요 단계로 구성됩니다.
- The Render Phase: 렌더링 단계에서 React는 fiber 트리를 트래버스하고 DOM에 적용해야 하는 변경 사항을 결정합니다. 이 단계는 중단 가능합니다. 즉, React는 언제든지 일시 중지하고 재개할 수 있습니다.
- The Commit Phase: 커밋 단계에서 React는 DOM에 변경 사항을 적용합니다. 이 단계는 중단할 수 없습니다. 즉, React는 시작하면 완료해야 합니다.
The Render Phase in Detail
렌더링 단계는 두 개의 하위 단계로 더 나눌 수 있습니다.
- beginWork:
beginWork
함수는 현재 Fiber 노드를 처리하고 자식 Fiber 노드를 만드는 역할을 합니다. 컴포넌트를 업데이트해야 하는지 여부를 결정하고, 그렇다면 자식에 대한 새 Fiber 노드를 만듭니다. - completeWork:
completeWork
함수는 자식이 처리된 후 현재 Fiber 노드를 처리하는 역할을 합니다. DOM을 업데이트하고 컴포넌트의 레이아웃을 계산합니다.
beginWork
함수는 다음 작업을 수행합니다.
- 컴포넌트를 업데이트해야 하는지 확인합니다.
- 컴포넌트를 업데이트해야 하는 경우 새 props와 상태를 이전 props와 상태와 비교하여 적용해야 하는 변경 사항을 결정합니다.
- 컴포넌트 자식에 대한 새 Fiber 노드를 만듭니다.
- Fiber 노드에서
effectTag
속성을 설정하여 DOM에서 수행해야 하는 업데이트 유형을 나타냅니다.
completeWork
함수는 다음 작업을 수행합니다.
beginWork
함수 중에 결정된 변경 사항으로 DOM을 업데이트합니다.- 컴포넌트의 레이아웃을 계산합니다.
- 커밋 단계 후에 수행해야 하는 side effect를 수집합니다.
The Commit Phase in Detail
커밋 단계는 DOM에 변경 사항을 적용하는 역할을 합니다. 이 단계는 중단할 수 없습니다. 즉, React는 시작하면 완료해야 합니다. 커밋 단계는 세 개의 하위 단계로 구성됩니다.
- beforeMutation: 이 단계는 DOM이 변경되기 전에 실행됩니다. DOM 업데이트 준비와 같은 작업을 수행하는 데 사용됩니다.
- mutation: 이 단계는 실제 DOM 변경이 수행되는 단계입니다. React는 Fiber 노드의
effectTag
속성을 기반으로 DOM을 업데이트합니다. - layout: 이 단계는 DOM이 변경된 후에 실행됩니다. 컴포넌트 레이아웃 업데이트 및 라이프사이클 메서드 실행과 같은 작업을 수행하는 데 사용됩니다.
실제 예제 및 코드 스니펫
간단한 예제로 Fiber reconciliation 프로세스를 설명해 보겠습니다. 항목 목록을 표시하는 컴포넌트를 고려해 보십시오.
```javascript function ItemList({ items }) { return (-
{items.map(item => (
- {item.name} ))}
items
prop이 변경되면 React는 목록을 reconciliation하고 DOM을 적절하게 업데이트해야 합니다. Fiber는 이를 다음과 같이 처리합니다.
- Render Phase:
beginWork
함수는 새items
배열을 이전items
배열과 비교합니다. 추가, 제거 또는 업데이트된 항목을 식별합니다. - 추가된 항목에 대한 새 Fiber 노드가 생성되고
effectTag
가 설정되어 이러한 항목을 DOM에 삽입해야 함을 나타냅니다. - 제거된 항목에 대한 Fiber 노드는 삭제될 것으로 표시됩니다.
- 업데이트된 항목에 대한 Fiber 노드는 새 데이터로 업데이트됩니다.
- Commit Phase: 그런 다음
commit
단계는 이러한 변경 사항을 실제 DOM에 적용합니다. 추가된 항목이 삽입되고, 제거된 항목이 삭제되고, 업데이트된 항목이 수정됩니다.
key
prop의 사용은 효율적인 reconciliation에 매우 중요합니다. key
prop이 없으면 React는 items
배열이 변경될 때마다 전체 목록을 다시 렌더링해야 합니다. key
prop을 사용하면 React는 추가, 제거 또는 업데이트된 항목을 빠르게 식별하고 해당 항목만 업데이트할 수 있습니다.
예를 들어 쇼핑 카트에서 항목의 순서가 변경되는 시나리오를 상상해 보십시오. 각 항목에 고유한 key
(예: 제품 ID)가 있는 경우 React는 전체를 다시 렌더링하지 않고도 DOM에서 항목의 순서를 효율적으로 다시 지정할 수 있습니다. 이렇게 하면 특히 큰 목록의 경우 성능이 크게 향상됩니다.
Scheduling 및 Prioritization
Fiber의 주요 이점 중 하나는 업데이트를 예약하고 우선 순위를 지정하는 기능입니다. React는 스케줄러를 사용하여 우선 순위에 따라 작업 단위를 시작, 일시 중지, 재개 또는 중단할 시기를 결정합니다. 이를 통해 React는 사용자 상호 작용의 우선 순위를 지정하고 복잡한 업데이트 중에도 UI가 응답성을 유지하도록 할 수 있습니다.
React는 다양한 우선 순위로 업데이트를 예약하기 위한 몇 가지 API를 제공합니다.
React.render
: 기본 우선 순위로 업데이트를 예약합니다.ReactDOM.unstable_deferredUpdates
: 낮은 우선 순위로 업데이트를 예약합니다.ReactDOM.unstable_runWithPriority
: 업데이트의 우선 순위를 명시적으로 지정할 수 있습니다.
예를 들어 ReactDOM.unstable_deferredUpdates
를 사용하여 분석 추적 또는 백그라운드 데이터 가져오기와 같이 사용자 경험에 중요하지 않은 업데이트를 예약할 수 있습니다.
Error Handling with Fiber
Fiber는 reconciliation 프로세스 중에 향상된 오류 처리를 제공합니다. 렌더링 중에 오류가 발생하면 React는 오류를 catch하고 전체 애플리케이션이 충돌하는 것을 방지할 수 있습니다. React는 오류 경계를 사용하여 오류를 제어된 방식으로 처리합니다.
오류 경계는 하위 컴포넌트 트리에서 JavaScript 오류가 발생하는 모든 위치에서 오류를 catch하고 오류를 기록하고 충돌된 컴포넌트 트리 대신 대체 UI를 표시하는 컴포넌트입니다. 오류 경계는 렌더링 중, 라이프사이클 메서드에서 및 아래 전체 트리의 생성자에서 오류를 catch합니다.
```javascript class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can also log the error to an error reporting service logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // You can render any custom fallback UI returnSomething went wrong.
; } return this.props.children; } } ```오류가 발생할 수 있는 컴포넌트를 래핑하는 데 오류 경계를 사용할 수 있습니다. 이렇게 하면 일부 컴포넌트가 실패하더라도 애플리케이션이 안정적으로 유지됩니다.
```javascriptDebugging Fiber
Fiber를 사용하는 React 애플리케이션을 디버깅하는 것은 어려울 수 있지만 도움이 될 수 있는 몇 가지 도구와 기술이 있습니다. React DevTools 브라우저 확장은 컴포넌트 트리 검사, 성능 프로파일링 및 오류 디버깅을 위한 강력한 도구 세트를 제공합니다.
React Profiler를 사용하면 애플리케이션의 성능을 기록하고 병목 현상을 식별할 수 있습니다. Profiler를 사용하여 각 컴포넌트가 렌더링하는 데 걸리는 시간을 확인하고 성능 문제를 일으키는 컴포넌트를 식별할 수 있습니다.
React DevTools는 각 컴포넌트의 props, 상태 및 Fiber 노드를 검사할 수 있는 컴포넌트 트리 보기도 제공합니다. 이는 컴포넌트 트리가 구성되는 방식과 reconciliation 프로세스가 작동하는 방식을 이해하는 데 도움이 될 수 있습니다.
결론
React Fiber 아키텍처는 기존 reconciliation 프로세스에 비해 상당한 개선을 나타냅니다. Fiber는 reconciliation 프로세스를 더 작고 중단 가능한 작업 단위로 분해하여 React가 특히 복잡한 시나리오에서 애플리케이션의 응답성과 인지된 성능을 개선할 수 있도록 합니다.
Fibers, 작업 루프 및 스케줄링과 같은 Fiber의 핵심 개념을 이해하는 것은 고성능 React 애플리케이션을 구축하는 데 필수적입니다. Fiber의 기능을 활용하여 더 응답성이 뛰어나고 복원력이 뛰어나며 더 나은 사용자 경험을 제공하는 UI를 만들 수 있습니다.
React가 계속 발전함에 따라 Fiber는 아키텍처의 기본 부분으로 유지됩니다. Fiber의 최신 개발 사항을 최신 상태로 유지하면 React 애플리케이션이 제공하는 성능 이점을 최대한 활용할 수 있습니다.
다음은 몇 가지 주요 사항입니다.
- React Fiber는 React reconciliation 알고리즘의 완전한 재작성입니다.
- Fiber를 사용하면 React가 reconciliation 프로세스를 일시 중지하고 재개할 수 있으므로 장기 실행 작업이 기본 스레드를 차단하는 것을 방지할 수 있습니다.
- Fiber를 사용하면 React가 다양한 유형의 업데이트에 우선 순위를 지정할 수 있습니다.
- Fiber는 reconciliation 프로세스 중에 더 나은 오류 처리를 제공합니다.
key
prop은 효율적인 reconciliation에 매우 중요합니다.- React DevTools 브라우저 확장은 Fiber 애플리케이션을 디버깅하기 위한 강력한 도구 세트를 제공합니다.
React Fiber를 수용하고 그 원칙을 이해함으로써 전 세계의 개발자는 위치나 프로젝트의 복잡성에 관계없이 더 나은 성능과 사용자 친화적인 웹 애플리케이션을 구축할 수 있습니다.