컴포넌트는 화면에 표시되기 전에 리액트에 의해 반드시 렌더링되어야 합니다.
이 프로세스를 이해하면 작성한 코드가 어떻게 실행될지 생각하고, 실행 동작을 설명하는 데 도움이 될 것입니다.
다음의 것들을 알게 됩니다.
- 리액트에서 렌더링은 무엇을 의미하는지
- 리액트는 언제 그리고 왜 컴포넌트를 렌더링하는지
- 화면에 컴포넌트를 표시하는 단계
- 렌더링은 왜 항상 DOM 업데이트를 발생시키지 않는지
컴포넌트를 요리라고 생각해 보겠습니다. 그리고 이때 리액트는 고객으로부터 주문받고 요리를 가져다주는 웨이터라고 생각해 보겠습니다. 이 프로세스는 다음의 세 단계를 가집니다.
- 렌더링을 트리거합니다. (주방으로 고객의 주문을 전달합니다.)
- 컴포넌트를 렌더링합니다. (주방에서 요리를 준비합니다.)
- DOM에 커밋합니다. (테이블에 요리를 놓습니다.)
단계 1: 렌더링을 트리거합니다.
컴포넌트는 다음의 두 가지 경우에 렌더링합니다.
- 컴포넌트의 초기에 렌더링합니다.
- 컴포넌트 자신이나 조상 컴포넌트 중 하나가 가지고 있는 state가 업데이트되었을 때 렌더링합니다.
초기 렌더링
앱이 시작되면 초기 렌더링을 트리거해야 합니다. 이것은 타겟 DOM 노드와 함께 createRoot
를 호출한 다음, 컴포넌트와 함께 render
메소드를 호출하는 것으로 수행됩니다.
import App from "./App.js";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
root.render(<App />);
state 업데이트 시 발생하는 리렌더링
컴포넌트가 초기에 렌더링되고 나면, set
함수를 이용해 state를 업데이트하는 것으로 추가 렌더링을 트리거할 수 있습니다. 컴포넌트의 state를 업데이트하면 자동으로 렌더링이 대기열에 추가됩니다.
단계 2: 리액트가 컴포넌트를 렌더링합니다.
렌더링을 트리거한 이후에, 리액트는 무엇을 화면에 표시할지 알아내기 위해 컴포넌트를 호출합니다. “렌더링”은 리액트가 컴포넌트를 호출하는 것입니다.
- 초기 렌더링에서 리액트는 루트 컴포넌트를 호출합니다.
- 이후의 렌더링에서 리액트는 상태가 업데이트되어 렌더링을 트리거한 컴포넌트를 호출합니다.
이 프로세스는 반복적입니다. 업데이트된 컴포넌트가 어떤 다른 컴포넌트를 반환하고 있다면, 리액트는 그 컴포넌트를 다음으로 렌더링합니다. 그리고 그 컴포넌트가 또 어떤 다른 컴포넌트를 반환하고 있다면, 리액트는 그 컴포넌트를 다음으로 렌더링합니다. 이 프로세스는 더 이상 중첩된 컴포넌트가 없고, 리액트가 화면에 무엇이 표시되어야 하는지 정확히 알 때까지 계속됩니다.
다음의 예시에서 리액트는 Article
함수를 호출하고, Paragraph
함수를 여러 번 호출할 것입니다.
- 초기 렌더링을 하는 동안, 리액트는
<article>
,<h1>
, 그리고 세 개의<p>
태그에 대한 DOM 노드를 생성합니다. - 리렌더링을 하는 동안, 리액트는 이전 렌더링 이후 변경된 속성이 있다면 그것이 어떤 속성인지 계산합니다. 그런데, 다음 단계인 커밋 단계가 될 때까지 그 정보를 가지고 아무 일도 하지는 않습니다.
단계 3: 리액트가 DOM에 변경 사항을 커밋합니다.
컴포넌트를 렌더링(호출)한 이후에, 리액트는 DOM을 수정합니다.
- 초기 렌더링에서 리액트는
appendChild
DOM API를 사용하여 생성한 모든 DOM 노드를 화면에 표시합니다. - 리렌더링에서 리액트는 DOM이 최신 렌더링 결과와 일치하도록 렌더링 중에 계산한 최소한의 필수 작업을 적용합니다.
리액트는 렌더링 간에 차이가 있는 DOM 노드만을 변경합니다. 예를 들어, 매초 state가 업데이트되어 리렌더링하는 컴포넌트가 있습니다. <input>
에 어떤 텍스트를 추가하여 그것의 값을 업데이트할 수 있지만, 컴포넌트가 리렌더링될 때 그 텍스트가 사라지지 않는 것에 주목해 주세요.
이 단계에서 리액트는 새로운 time
을 가지고 <h1>
의 내용만 업데이트하기 때문에 이처럼 동작합니다. <input>
이 JSX에서 지난번과 같은 위치에 나타나는 것을 확인하기 때문에, 리액트는 <input>
또는 그 값을 건드리지 않습니다.
에필로그: 브라우저가 패인트합니다.
렌더링이 끝난 이후에 리액트는 DOM을 업데이트하고, 브라우저는 화면을 리패인트합니다. 이 프로세스는 “브라우저 렌더링”이라고 합니다.