React의 렌더링 프로세스


react

React는 현대적인 웹 애플리케이션 개발에서 가장 널리 사용되는 라이브러리 중 하나입니다. 그 핵심은 효율적인 렌더링 프로세스에 있습니다. 이번 포스트에서는 React의 렌더링 프로세스가 어떻게 동작하는지, 그리고 이를 이해함으로써 성능을 최적화할 수 있는 방법을 정리해보겠습니다.


React 렌더링 프로세스의 기본 개념

React의 렌더링 프로세스는 UI를 효율적으로 업데이트하기 위해 두 가지 주요 단계로 나뉩니다: **Render Phase(렌더 단계)**와 Commit Phase(커밋 단계). 이 두 단계는 React가 상태나 props의 변경을 감지하고, 이를 기반으로 UI를 업데이트하는 과정을 체계적으로 처리하는 핵심입니다. 아래에서는 각 단계의 역할과 작동 방식을 더 자세히 살펴보겠습니다.


1. Render Phase (렌더 단계)

Render Phase는 React가 **”어떻게 UI를 업데이트할지”**를 결정하는 단계입니다. 이 단계에서는 컴포넌트의 상태(state)와 props를 기반으로 새로운 Virtual DOM을 생성하고, 이전 Virtual DOM과 비교(diffing)하여 변경 사항을 계산합니다. 중요한 점은, 이 단계에서는 실제 DOM에 아무런 변경도 이루어지지 않는다는 것입니다. 모든 작업은 메모리 내에서 이루어지며, React는 이 과정을 통해 UI 업데이트를 준비합니다.

Render Phase의 주요 특징

  1. Pure and Side-Effect Free (순수하고 부작용이 없는 단계)
    • Render Phase는 순수한 계산 단계로, 이 과정에서 DOM 조작이나 브라우저와의 상호작용 같은 부작용이 발생하지 않습니다.
    • React는 컴포넌트의 render 함수나 함수형 컴포넌트를 호출하여 새로운 Virtual DOM을 생성합니다.
  2. Virtual DOM 생성
    • React는 컴포넌트의 상태와 props를 기반으로 새로운 Virtual DOM 트리를 생성합니다.
    • 이 Virtual DOM은 UI의 현재 상태를 나타내는 가벼운 데이터 구조입니다.
  3. Diffing (비교)
    • React는 이전 Virtual DOM과 새로 생성된 Virtual DOM을 비교(diffing)하여 변경된 부분을 찾습니다.
    • 이 과정에서 React는 효율적인 Reconciliation(조정) 알고리즘을 사용하여 변경 사항을 최소화합니다.
  4. “어떻게 변경할지” 결정
    • Render Phase의 결과는 “어떤 부분이 변경되었는지”와 “어떻게 변경할지”에 대한 정보입니다.
    • 이 정보는 Commit Phase에서 실제 DOM 업데이트를 수행하는 데 사용됩니다.
Render Phase의 예제
function Counter({ count }) {
  return <h1>Count: {count}</h1>;
}

// 상태가 변경되면 React는 Render Phase에서 새로운 Virtual DOM을 생성
const oldVirtualDOM = { type: "h1", props: { children: "Count: 0" } };
const newVirtualDOM = { type: "h1", props: { children: "Count: 1" } };

// React는 두 Virtual DOM을 비교하여 변경된 부분을 찾음
// 변경된 부분: "Count: 0" → "Count: 1"

Render Phase에서의 제한

  • Render Phase는 순수한 계산 단계이므로, DOM 조작이나 브라우저 API 호출 같은 부작용을 포함해서는 안 됩니다.
  • 부작용이 필요한 작업은 useEffect와 같은 React Hook을 사용하여 Commit Phase에서 처리해야 합니다.

2. Commit Phase (커밋 단계)

Commit Phase는 Render Phase에서 계산된 변경 사항을 실제 DOM에 반영하는 단계입니다. 이 단계에서는 Virtual DOM에서 계산된 결과를 기반으로 실제 DOM을 업데이트하고, 브라우저가 화면을 다시 그리도록 요청합니다. 또한, 이 단계에서 React는 부작용(Side Effects)을 처리합니다.

Commit Phase의 주요 특징

  1. DOM 업데이트
    • Render Phase에서 계산된 변경 사항을 실제 DOM에 반영합니다.
    • React는 변경된 부분만 업데이트하여 DOM 조작을 최소화합니다.
  2. 레이아웃 계산 및 페인팅
    • DOM이 업데이트되면 브라우저는 레이아웃을 다시 계산하고, 화면을 다시 그립니다(페인팅).
    • 이 과정은 브라우저의 렌더링 엔진에 의해 처리됩니다.
  3. 부작용 처리
    • Commit Phase에서는 useEffectuseLayoutEffect, 클래스 컴포넌트의 componentDidMount 및 componentDidUpdate와 같은 라이프사이클 메서드가 실행됩니다.
    • 이 단계에서 DOM 조작, API 호출, 애니메이션 시작 등 부작용을 안전하게 처리할 수 있습니다.
  4. React DevTools에서의 표시
    • Commit Phase는 React DevTools에서 “Commit”으로 표시되며, 이 단계에서 실제 DOM 변경이 이루어졌음을 확인할 수 있습니다.
Commit Phase의 예제
function Counter({ count }) {
  useEffect(() => {
    console.log("Count updated:", count);
  }, [count]);

  return <h1>Count: {count}</h1>;
}

// 상태가 변경되면 Commit Phase에서 다음 작업이 수행됨:
// 1. Virtual DOM에서 계산된 변경 사항을 실제 DOM에 반영
// 2. 브라우저가 레이아웃을 다시 계산하고 화면을 다시 그림
// 3. useEffect가 실행되어 "Count updated" 로그 출력

Commit Phase에서의 주요 작업

  • DOM 업데이트: 변경된 Virtual DOM을 실제 DOM에 반영.
  • 부작용 처리: useEffect와 같은 Hook을 통해 부작용 실행.
  • 브라우저 렌더링: DOM 변경 후 레이아웃 계산 및 화면 페인팅.

React 렌더링 프로세스의 전체 흐름

React의 렌더링 프로세스는 다음과 같은 순서로 진행됩니다:

  1. 상태 또는 props 변경
    • 상태(state)나 props가 변경되면 React는 렌더링을 트리거합니다.
  2. Render Phase
    • React는 새로운 Virtual DOM을 생성하고, 이전 Virtual DOM과 비교하여 변경 사항을 계산합니다.
    • 이 단계에서는 실제 DOM에 아무런 변경도 이루어지지 않습니다.
  3. Commit Phase
    • Render Phase에서 계산된 변경 사항을 실제 DOM에 반영합니다.
    • DOM 업데이트, 레이아웃 계산, 화면 페인팅, 부작용 처리 등이 이루어집니다.
  4. 브라우저 렌더링
    • 브라우저는 DOM 변경 사항을 기반으로 레이아웃을 다시 계산하고, 화면을 다시 그립니다.

React의 렌더링 트리거

React는 특정 조건에서 렌더링을 트리거합니다. 주요 트리거 조건은 다음과 같습니다:

  1. 상태(State) 변경
    • useState로 관리되는 상태가 변경되면 해당 컴포넌트와 자식 컴포넌트가 다시 렌더링됩니다.
  2. Props 변경
    • 부모 컴포넌트에서 전달된 props가 변경되면 해당 컴포넌트가 다시 렌더링됩니다.
  3. Context 변경
    • useContext로 구독한 값이 변경되면 관련된 모든 컴포넌트가 다시 렌더링됩니다.

React의 Virtual DOM과 Reconciliation

React의 렌더링 프로세스에서 중요한 역할을 하는 것이 바로 Virtual DOMReconciliation(조정) 입니다.

Virtual DOM

Virtual DOM은 React가 UI를 효율적으로 관리하기 위해 사용하는 가상의 DOM 구조입니다. React는 실제 DOM 대신 Virtual DOM을 사용하여 변경 사항을 계산하고, 이를 통해 성능을 최적화합니다.

Virtual DOM에 대한 자세한 내용은 이전 포스트에서 다뤘으니, 더 깊이 알고 싶다면 이전 포스트를 참고해주세요. 여기서는 간단히 핵심만 정리하겠습니다.

Virtual DOM의 핵심

  • 가벼운 구조: 실제 DOM보다 훨씬 가볍고, 빠르게 생성 및 업데이트할 수 있습니다.
  • 메모리 내에서 작동: Virtual DOM은 브라우저와 직접 상호작용하지 않고, 메모리 내에서만 작동합니다.
  • 변경 사항 계산: React는 Virtual DOM을 사용하여 UI의 변경 사항을 계산하고, 필요한 부분만 실제 DOM에 반영합니다.

Reconciliation

Reconciliation은 React가 Virtual DOM을 사용하여 UI의 변경 사항을 효율적으로 처리하는 과정을 의미합니다. React는 상태나 props가 변경될 때마다 새로운 Virtual DOM을 생성하고, 이전 Virtual DOM과 새로운 Virtual DOM을 비교(diffing)하여 변경된 부분만 실제 DOM에 반영합니다.

Reconciliation의 주요 과정

  1. Diffing (비교)
    • React는 이전 Virtual DOM과 새로운 Virtual DOM을 비교하여 변경된 부분을 찾습니다.
    • React의 Diffing 알고리즘은 효율적으로 설계되어, 변경 사항을 빠르게 계산할 수 있습니다.
    • 예를 들어, 같은 레벨의 노드끼리만 비교하고, 다른 레벨의 노드는 비교하지 않습니다.
  2. Patch (패치)
    • Diffing 과정에서 발견된 변경 사항만 실제 DOM에 반영합니다.
    • React는 변경된 부분만 업데이트하기 때문에 전체 DOM을 다시 렌더링하지 않아도 됩니다.

Reconciliation의 특징

  • 최소한의 DOM 업데이트: 변경된 부분만 실제 DOM에 반영하여 성능을 최적화합니다.
  • 효율적인 알고리즘: React의 Diffing 알고리즘은 O(n) 복잡도로 설계되어, 매우 빠르게 변경 사항을 계산할 수 있습니다.
  • 컴포넌트 기반 업데이트: React는 컴포넌트 단위로 변경 사항을 추적하고, 필요한 컴포넌트만 업데이트합니다.


결론

React 렌더링 프로세스를 이해해야 하는 이유

React의 렌더링 프로세스를 이해하면 다음과 같은 이점을 얻을 수 있습니다:

  • 불필요한 렌더링을 방지하여 성능을 최적화할 수 있습니다.
  • Virtual DOM과 Reconciliation의 작동 방식을 이해하여 React의 효율성을 활용할 수 있습니다.
  • 상태 관리와 컴포넌트 설계를 더 효과적으로 할 수 있습니다.

React는 기본적으로 효율적인 렌더링을 제공하지만, 개발자가 렌더링 프로세스를 이해하고 최적화 기법을 적용하면 더욱 빠르고 사용자 친화적인 애플리케이션을 만들 수 있습니다. React를 제대로 활용하기 위해서는 렌더링 프로세스의 원리를 깊이 이해하는 것이 필수적입니다

jeewoo jung 아바타