ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] 리액트 Render와 Commit
    React 2023. 10. 24. 17:36

     

    리액트에서 컴포넌트는 화면에 보이기 전에  반드시 렌더링이 된다고 합니다.

    그리고 이 렌더링 과정을 공식문서에는 아래와 같은 세 가지 단계로 설명을 하고 있습니다.

    1. 렌더링 트리거 (Triggering a render)
    2. 컴포넌트 렌더링 (Rendering the component)
    3. DOM에 커밋 (Commiting to the Dom)

    먼저 각 단계가 어떤 것을 의미하는지 알아보겠습니다.

     

    | 렌더링 트리거 (Trigger a render)

    컴포넌트가 렌더링 되는 이유는 2가지가 있다고 하는데 아래와 같습니다.

    1. 컴포넌트의 초기에 렌더링
    2. 해당 컴포넌트나 상위 컴포넌트의 상태(state)가 업데이트되었을 때

     

    1. 초기 렌더링

    앱이 시작되면 초기 렌더링을 트리거하는 것이 필요합니다. 그리고 이것은 타깃 DOM 노드와 함께 createRoot를 호출하고,

    컴포넌트와 함께 render 메서드를 호출하는 것으로 수행이 됩니다.

    import App from "./App.js";
    import { createRoot } from "react-dom/client";
    
    const root = createRoot(document.getElementById("root"));
    root.render(<App />);

    -> createRoot는 브라우저 DOM 노드 내 React 컴포넌트를 보여주는 루트를 생성

    2. 상태 업데이트에 의한 재렌더링

    컴포넌트가 초기에 렌더링이 되면 set함수를 사용해 상태(state)를 업데이트하면 추가적인 렌더링을 실행할 수 있습니다.

    컴포넌트의 상태를 업데이트하면 자동으로 렌더 큐에 추가됩니다.

     

    | 컴포넌트 렌더링(Rendeting the component)

    컴포넌트 렌더링이 트리거 된 후, 리액트는 화면에 어떤 것이 보여야 할지 알아내기 위해 컴포넌트를 호출합니다.

    -> "Rendering"은 리액트가 컴포넌트를 호출하는 것을 의미

    1. 초기 렌더링에서 리액트는 root컴포넌트를 호출
    2. 그 후의 렌더링에서는 리액트는 상태의 업데이트로 렌더링이 트리거 된 컴포넌트를 호출

     

    이런 프로세스는 재귀적으로 발생합니다. 만약 업데이트된 컴포넌트가 다른 컴포넌트를 반환하면,

    리액트는 다음에 그 컴포넌트를 렌더링 합니다. 마찬가지로 이 컴포넌트가 또 다른 컴포넌트를 반환하면,

    리액트는 그 컴포넌트를 다음으로 렌더링을 합니다.

    이는 다른 중첩된 컴포넌트가 없고 리액트가 화면에 어떤 것을 표시해 줄지 정확히 알기 전까지 계속됩니다.

    export default function Hello() {
      return (
        <div>
          <h1>Hello</h1>
          <World />
          <World />
          <World />
        </div>
      );
    }
    
    function World() {
      return <p>hello world</p>
    }

    위 코드에서는 초기 렌더링이 진행되는 동안, 리액트는 <div>, <h1>, 3개의 <p> 태그에 대한 DOM 노드를 생성을 하고,

    재 렌더링 되는 동안에는 리액트는 이전 렌더링 이후 바뀐 속성이 있으면 그 속성이 어떤 것인지 계산을 합니다.

     

    | DOM에 커밋(Commiting to the Dom)

    컴포넌트를 렌더링 한 후 리엑트는 DOM수정을 합니다.

    1. 초기 렌더링에서 리액트는 appendChild()를 사용하여 생성된 모든 DOM 노드를 화면에 표시
    2. 재 렌더링 시에는 리액트는 최근 렌더링 결과와 일치하도록 최소한의 필수 작업을 적용 (diffing 알고리즘)

     

    리액트는 렌더링 간 차이가 있는 DOM노드만 변경을 해줍니다.

    아래 예시를 보면 매초 state가 업데이트되어 리렌더링 될 때 <input>의 값이 사라지지 않는 것을 볼 수 있습니다.

    export default function App() {
      const [currentTime, setCurrentTime] = useState(new Date());
    
      useEffect(() => {
        const intervalId = setInterval(() => {
          setCurrentTime(new Date());
        }, 1000);
    
        return () => {
          clearInterval(intervalId);
        };
      }, []);
    
      return (
        <>
          <h1>{currentTime.toLocaleTimeString()}</h1>
          <input />
        </>
      );
    }

    위 코드에서 리액트는 새로운 currentTime을 가지고 <h1> 태그의 내용만 업데이트해 줍니다.

    그리고 <input>은 JSX에서 이전과 같은 위치에 나타나기 때문에 그 값을 건드리지 않습니다.

    | 브라우저 페인트 (Browser paint)

    렌더링이 끝나고 리액트가 DOM을 업데이트하면 브라우저는 화면을 다시 페인트(repaint)를 하는데

    이를 "브라우저의 렌더링"이라고 합니다.

     

     

    | 참고

    https://react.dev/learn/render-and-commit

Designed by Tistory.