렌더링이란 현재 props 및 상태를 기반으로 리액트가 컴포넌트에게 UI 영역이 어떻게 보이길 원하는지 설명을 요청하는 프로세스이다.
렌더링 프로세스 동안 리액트는 컴포넌트 트리의 루트에서 시작해 업데이트가 필요하다고 표시된 모든 컴포넌트를 찾기 위해 아래로 순회한다. 플래그가 지정된 각 컴포넌트에 대해 리액트는 함수 컴포넌트의 경우 ``FunctionComponent(props)를, 클래스 컴포넌트의 경우 classComponentInstance.render() 를 호출하고 렌더 패스의 다음 단계를 위해 렌더 출력을 저장합니다.
컴포넌트 렌더 출력은 일반적으로 JSX 구문으로 작성되며 자바스크립트가 컴파일되고 배포를 위해 준비될때 React.createElement() 호출로 변환됩니다. createrElement는 의도된 UI의 구조를 설명하는 일반 자바스크립트 객체인 React 요소를 반환한다.
return <MyComponent a={42} b="testing">Text here</MyComponent>
// JSX 구문
return React.createElement(MyComponent, {a: 42, b: "testing"}, "Text Here")
// 위와 같은 호출로 변환
{type: MyComponent, props: {a: 42, b: "testing"}, children: ["Text Here"]}
// 위와 같은 요소 객체가 된다.
let elements = MyComponent({...props, children})
// 내부적으로는 리액트가 실제 함수를 호출해 렌더링 한다.
return <button onClick={() => {}}>Click Me</button>
// HTML 처럼 보이는 "호스트 컴포넌트"의 경우
React.createElement("button", {onClick}, "Click Me")
// 위와 같이 호출되어
{type: "button", props: {onClick}, children: ["Click me"]}
컴포넌트 트리 전체에서 렌더 출력을 수집한 후 리액트는 새로운 객체 트리(흔히 “가상 DOM”(리액트 개발진들은 슬슬 가상돔이라는 단어를 탈피하려 함)이라고 함)와 비교해 실제 돔을 현재 원하는 출력과 같이 보이게 하기 위해 적용해야 할 모든 변경 사항 목록을 수집한다. 비교 및 계산 프로세스는 “재조정(reconciliation)”으로 알려져 있다.
그런 다음 리액트는 계산된 모든 변경 사항을 하나의 동기 시퀸스로 돔에 적용한다.
참고 : 리액트팀은 최근 몇 년간 “가상 DOM”이라는 요어를 멀리했다. Dan Abramov는 다음과 같이 말했다.
저는 위락 “가상 DOM”이라는 용어를 폐기할 수 있길 바랍니다. 2013년에는 지금과 달리 이렇게 이야기 하지 않으면 사람들은 리액트가 모든 렌더에서 DOM 노드를 생성한다고 생각했기 때문에 의미가 있었습니다. 그러나 오늘날 사람들은 이런 가정을 거의 하지 않스빈다. “가상 DOM”은 일부 DOM 문제에 대한 해결 방법처럼 들리지만 리액트는 그런 것이 아닙니다. 리액트는 “값 UI”입니다. 그것의 핵심 원칙은 UI가 문자열이나 배열과 마찬가지로 값이라는 것입니다. 변수에 저장하고, 전달하고, 자바스크립트 제어 흐름에서 사용할 수 있습니다. 그 표현가능함이 요점입니다. DOM에 변경 사항을 적용하는 것을 피하기 위한 비교 같은 것이 아닙니다. 항상 DOM을 나타내는 것도 아닙니다. 예를 들어 <Message recipientId={10} /> 는 DOM이 아닙니다. 개념적으로 이는 지연 함수 호출 Message.bind(null, { recipientId: 10})를 나타냅니다.
⇒ 값 UI라는 개념 알아보기
리액트 팀은 이 작업을 개념적으로 다음과 같은 두 단계로 나눕니.
리액트는 커밋 단계에서 DOM을 업데이트한 후 요청된 DOM 요소 및 컴포넌트 인스턴슬ㄹ 가리키도록 모든 참조를 적절하게 업데이트 합니다. 그 다음 componentDidMount 및 componentDidUpdate 클래스 라이프 사이클 메서드와 useLayoutEffect 훅을 동기적으로 실행합니다.