
컴포넌트가 화면에 표시 되기 전에 리액트로 렌더링되어야 한다. 이 프로세스의 단계를 이해하면 코드가 어떻게 실행되고 동작을 설명하는지 생각하는 데 도움된다.

컴포넌트가 주방에서 요리사가 되어 재료로 맛있는 요리를 만들고 있다고 상상해봐라. 이 시나리오에서 리액트는 고객의 요청을 접수하고 주문을 전달하는 웨이터이다. UI를 요청하고 제공하는 프로세스는 세 단계로 구성된다.
컴포넌트가 렌더링되는 데는 두 가지 이유가 있다.
앱이 시작되면 초기 렌더링을 트리거해야한다. 프레임워크와 샌드박스는 때때로 이 코드를 숨기지만, 이는 대상 DOM 노드로 createRoot를 호출한 다음 컴포넌트로 render 메서드를 호출하여 수행된다.
// index.js
import Image from './Image.js';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'))
root.render(<Image />);
// Image.js
export default function Image() {
return (
<img
src="https://i.imgur.com/ZF6s192.jpg"
alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals"
/>
);
}
root.render() 호출을 주석 처리하여 컴포넌트가 사라지는 것을 확인해라
컴포넌트가 처음 렌더링되면 set function를 사용하여 해당 상태를 업데이트하여 추가 렌더링을 트리거할 수 있다. 컴포넌트의 상태를 업데이트하면 렌더링이 자동으로 대기열에 추가된다.(식당 손님이 갈증이나 배고픈 상태에 따라 차, 디저트 등을 먼저 주문한 후 주문하는 모습을 상상해보아라.)
렌더링을 트리거한 뒤 리액트는 컴포넌트를 호출하여 화면에 표시할 내용을 파악한다. “렌더링”은 리액트가 컴포넌트를 호출하는 것이다.
이 프로세스는 재귀적이다. 업데이트된 컴포넌트가 다른 컴포넌트를 반환하면 리액트는 해당 컴포넌트를 다음에 렌더링하고 해당 컴포넌트도 무언가를 반환하면 해당 컴포넌트를 다음에 렌더링하는 식이다. 더 이상 중첩된 컴포넌트가 없고 리액트가 화면에 표시해야할 내용을 정확히 알 때까지 프로세스가 계속된다.
예제에서 리액트는 Gallery() 와Image() 를 여러 번 호출한다.
// Gallery.js
export default function Gallery() {
return (
<section>
<h1>Inspiring Sculptures</h1>
<Image />
<Image />
<Image />
</section>
);
}
function Image() {
return (
<img
src="https://i.imgur.com/ZF6s192.jpg"
alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals"
/>
);
}
// index.js
import Gallery from './Gallery.js';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'))
root.render(<Gallery />);
<section>, <h1>, 3개의 <img> 태그에 대한 DOM 노드를 생성한다.렌더링은 항상 순수한 계산이어야 한다.
그렇지 않으면 코드베이스가 복잡해지면서 혼란스러운 버그와 예측할 수 없는 동작이 발생할 수 있다. “Strict Mode”로 개발할 때 리액트는 각 컴포넌트를 두번 호출하므로 불순한 함수로 인한 실수를 표면화하는 데 도움이 될 수 있다.
💡 DEEO DIVE성능 최적화
업데이트된 컴포넌트 내에 중첩된 모든 컴포넌트를 렌더링하는 기본 동작은 업데이트된 컴포넌트가 트리에서 매우 높은 경우 성능에 적합하지 않는다. 성능 문제가 발생한 경우 Performance에 설명된 문제 해결을 위한 여러 가지 성택 방법이 있다. 너무 일찍 최적화 하지 말아라.
컴포넌트를 렌더링(호출)한 뒤 리액트는 DOM을 수정한다.
리액트는 렌더링 간에 차이가 있는 경우에만 DOM 노드를 변경한다. 예를 들어, 매초 부모로부터 전달된 다른 props로 다시 렌더링하는 컴포넌트가 있다. <input> 에 일부 텍스트를 추가하여 해당 value 를 업데이트할 수 있지만 컴포넌트가 다시 렌더링될 때 텍스트가 사라지지 않는 방법을 확인해라.
export default function Clock({ time }) {
return (
<>
<h1>{time}</h1>
<input />
</>
);
}
이는 마지막 단계에서 리액트가 <h1> 의 내용만 새로운 time으로 업데이트하기 때문에 작동한다. <input> 이 지난번과 같은 위치에 JSX에 나타나는 것을 확인하므로 리액트는 <input> 이나 그 value 를 건드리지 않는다.
렌더링이 완료되고 리액트가 DOM을 업데이트한 후 브라우저는 화면을 다시 페인팅한다. 이 프로세스를 “브라우저 렌더링”이라고 하지만 문서전체에서 혼동을 피하기 위해 “페인팅”이라고 부르겠다.