개발/React

[중급반] Step 1-1. React 렌더링 원리 및 Reconciliation 이해

ophelisis 2025. 12. 15. 13:52
반응형

안녕하세요! React 개발을 중급 수준으로 끌어올리려면 단순히 코드를 작성하는 것을 넘어, **"컴포넌트는 언제, 왜, 그리고 어떻게 다시 그려지는가"**에 대한 근본적인 질문에 답할 수 있어야 합니다.

성능 최적화의 90%는 바로 이 React의 렌더링 작동 원리를 이해하는 데 달려 있습니다. 복잡해 보이는 Virtual DOMReconciliation(재조정) 과정을 명쾌하게 정리해 드립니다.


1. 🖥️ 왜 'Virtual DOM'을 사용하는가?

1-1. Real DOM의 느린 업데이트

웹 브라우저의 화면 구조인 **Real DOM (Document Object Model)**을 직접 조작하는 것은 굉장히 비효율적입니다. DOM의 작은 변화라도 브라우저는 전체 레이아웃을 다시 계산(Reflow)하고 화면을 다시 그리는(Repaint) 무거운 작업을 수행해야 합니다. 웹사이트의 복잡도가 높아질수록 이 작업은 성능 병목 현상을 유발합니다.

1-2. Virtual DOM: 메모리 속 청사진

React는 이 문제를 해결하기 위해 **Virtual DOM(가상 돔)**을 사용합니다.

  • 정의: Real DOM을 그대로 본떠서 메모리상에 JavaScript 객체 형태로 만들어 둔 복사본이자, 일종의 미래 청사진입니다.
  • 작동 방식: 컴포넌트의 상태(State)나 속성(Props)이 변경될 때, React는 Real DOM을 직접 건드리지 않고, 업데이트된 내용을 이 Virtual DOM에 먼저 반영합니다.

2. 🔍 Reconciliation: 최소한의 변경만 적용하는 마법

Reconciliation은 React가 이전 Virtual DOM새로 업데이트된 Virtual DOM을 비교하여(Diffing), 실제로 Real DOM에 반영해야 할 최소한의 변경 목록을 찾아내는 과정입니다.

2-1. Diffing Algorithm (비교 알고리즘)

React는 다음과 같은 두 가지 핵심 원칙을 기반으로 비교 작업을 극도로 효율적으로 수행합니다.

  1. 다른 타입의 엘리먼트:
    • 타입이 다르면 (예: <div>가 <span>으로): React는 효율성을 위해 자비를 베풀지 않습니다. 이전 트리를 완전히 파괴하고, 새 트리를 처음부터 끝까지 재구성합니다. (내부에 있던 모든 State도 손실됩니다.)
    • 타입이 같으면: 같은 컴포넌트 인스턴스를 유지한 채, 변경된 **속성(Props)**만 업데이트합니다.
  2. 배열 및 리스트 항목 비교: Key Prop의 중요성
    • 리스트(배열)를 렌더링할 때 React는 key 속성을 사용해 각 항목을 식별합니다. Key는 항목의 고유 식별자(ID) 역할을 합니다.
    • Key 사용 시: 항목의 순서가 바뀌거나 중간에 추가/삭제되어도, React는 Key를 보고 변경된 해당 항목만 정확히 찾아서 업데이트합니다.
    • Key 미사용 또는 index 사용 시: React는 순서대로 비교하며, 비효율적인 전체 재렌더링이 발생하여 성능 저하와 State 오류를 유발할 수 있습니다. (Key는 데이터의 고유 ID를 사용해야 합니다!)

3. 📉 리렌더링의 전파와 성능 최적화의 필요성

중급 개발자가 반드시 알아야 할 가장 중요한 원칙은 리렌더링의 전파입니다.

  • 리렌더링의 원인:
    1. 컴포넌트 자신의 State가 변경될 때
    2. 부모 컴포넌트가 리렌더링 될 때
    3. 해당 컴포넌트가 구독하고 있는 Context 값이 변경될 때
  • 불필요한 리렌더링: 부모 컴포넌트가 리렌더링되면, 설령 자식 컴포넌트가 받은 Props 값이 단 하나도 변경되지 않았더라도, 기본적으로 모든 자식 컴포넌트는 함께 리렌더링됩니다.
JavaScript
 
function Parent() {
  const [data, setData] = useState(1); // 이 상태가 변하면 Parent가 리렌더링됨
  
  return (
    <div>
      {/* data가 변해도 props가 바뀌지 않은 ChildB는 사실 리렌더링될 필요가 없음 */}
      <ChildA data={data} /> 
      <ChildB /> 
    </div>
  );
}
// ☝️ 이 ChildB의 불필요한 리렌더링을 막는 것이 바로 성능 최적화의 핵심 목표가 됩니다.

이러한 **'불필요한 리렌더링의 전파'**를 차단하고, 정말 필요한 컴포넌트만 업데이트되도록 만드는 것이 다음 단계에서 배울 **React.memo, useCallback, useMemo**의 역할입니다.


🛠️ 1-1 실습 및 목표

  1. React DevTools 설치: 크롬/엣지 웹 스토어에서 React Developer Tools를 설치합니다.
  2. 렌더링 추적: 테스트 앱을 열고 DevTools의 Components 탭에서 톱니바퀴 설정으로 들어가 "Highlight updates when components render" 옵션을 활성화하세요.
  3. 원인 진단: 부모 컴포넌트의 State를 변경하면서, Props가 변하지 않은 자식 컴포넌트까지 노란색으로 빛나며 리렌더링되는 현상을 직접 관찰하고 원인을 분석하세요.
반응형