2023.01.27 엘리먼트 렌더링
Elements are the smallest buliding blocks of React Apps.
엘리먼트는 React 앱의 가장 작은 단위이다.
엘리먼트는 원래 웹사이트에 대한 모든 정보를 담고 있는 객체인 DOM에서 사용하는 용어이다.
그래서 기존에는 엘리먼트라고 하면 DOM엘리먼트를 의미했다.
웹 사이트에서 개발자도구를 이용해서 보면 "Elements" 탭을 확인할 수 있다.
여기서 보이는 엘리먼트는 리액트 엘리먼트가 아니라
DOM엘리먼트이며 HTML요소를 나타낸다.
실제 브라우저의 DOM에 존재하는 엘리먼트는 DOM 엘리먼트이고,
리액트의 Virtual DOM에 존재하는 엘리먼트가 리액트 엘리먼트이다.
결국 리액트 엘리먼트는 DOM 엘리먼트의 가상표현이라고 볼 수 있다.
또한 DOM 엘리먼트는 리액트 엘리먼트에 비해서 많은 정보를 담고 있기 떄문에 상대적으로 크고 무겁다.
엘리먼트는 화면에 표시할 내용을 기술한다.
const element = <h1>Hello, world</h1>;
이 코드가 실행될 떄, 대입 연산자의 오른쪽 부분은 리액트의 createElement( )함수를
사용하여 엘리먼트를 생성하게 된다.
결국 이렇게 생성된 것이 바로 리액트 엘리먼트가 되는 것이다.
브라우저 DOM 엘리먼트와 달리
React 엘리먼트는 일반 객체이며(plain object) 쉽게 생성할 수 있다.
React DOM은 React 엘리먼트와 일치하도록 DOM을 업데이트한다.
* 엘리먼트는 컴포넌트의 "구성 요소"이므로 혼동하지 않도록 하자.
{
type: 'button',
props: {
className: 'bg-green',
children: {
type: 'b',
props: {
children: 'Hello, element!'
}
}
}
}
{
type: Button,
props: {
color: 'green',
children: 'Hello, element!'
}
}
이 처럼 HTML 태그는 곧바로 렌더링이 될 수있는 상태이다.
하지만 리액트 컴포넌트의 경우에는 Button 컴포넌트의 엘리먼트를 생성해서 합지게 된다.
이처럼 컴포넌트 렌더링을 위해서 모든 컴포넌트가 createElement( )함수를
통해 엘리먼트로 변환된다는 것을 잊지말자.
엘리먼트의 가장큰 특징은 불변성이다.
엘리먼트 생성 후에는 children이나 attributes를 바꿀 수 없다는 말이다.
컴포넌트는 일종의 붕어빵 틀이라고 보면된다.
붕어빵이 구어져서 밖으로 나오는 과정은 엘리먼트를 생성하는 것이고,
완성된 붕어빵은 엘리먼트 생성이 끝난 것이기 때문에 변경할 수 없다.
그렇다면 화면에 변경된 엘리먼트를 보여주기 위해서는 어떻게 해야 할까??
이런 경우에는 새로운 엘리먼트를 만드렁서 기존 엘리먼트와 바뀌치기 하면 된다.
엘리먼트를 생성한 이후에 실제로 화면에 보여주기 위해서
렌더링이라는 과정을 거쳐야 한다.
HTML 파일 어딘가에 <div>가 있다고 가정해보자.
<div id="root"></div>
이 코드는 모든 리액트 앱에 필수적으로 들어가는 아주 중요한 코드이다.
이 안에 들어가는 모든 엘리먼트를 React DOM에서
관리하기 때문에 이것을 "Root DOM node"라고 부른다.
React로 구현된 어플리케이션은 일반적으로 단 하나의 루트 DOM 노드가 있다.
React를 기존앱에 통합하려는 경우 원하는 만큼 많은 수의 독립적인
루트 DOM 노드가 있을 수 있다.
React 엘리먼트를 렌더링 하기 위해서는
우선 DOM 엘리먼트를 ReactDOM.createRoot( ) 에 전달한 다음,
React 엘리먼트를 root.render( )에 전달해야한다.
const root = ReactDOM.createRoot(
document.getElementById('root')
);
const element = <h1>Hello, world</h1>;
root.render(element);
React 엘리먼트는 불변객체이다.
엘리먼트를 생성한 이후에는 해당 엘리먼트의
자식이나 속성을 변결할 수 없다.
엘리먼트는 영화에서 하나의 프레임과 같이 특정 시점의 UI를 보여준다.
지금까지 소개한 내용을 바탕으로 하면 UI를 업데이트하는
유일한 방법은 새로운 엘리먼트를 생성하고 이를 root.render( )로 전달하는 것이다.
# 예제
const root = ReactDOM.createRoot(
document.getElementById('root')
);
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
root.render(element);
}
setInterval(tick, 1000);
위 함수는 setInterval( ) 콜백을 이용해 초마다 root.render( )를 호출한다.
내부적으로는 tick( )함수가 호출될 때마다 기존 엘리먼트를 변경하는 것이 아니라
새로운 엘리먼트를 생성해서 바꿔치기하는 것이다.
React DOM은 해당 엘리먼트와 그 자식 엘리먼트를 이전의 엘리먼트와
비교하고 DOM을 원하는 상태로 만드는데 필요한 경우에만 DOM을 업데이트한다.
변경된 부분만 업데이트가 진행되는 것을 확인할 수 있다.
import React from "react";
function Clock(props) {
return (
<div>
<h1>안녕, 리액트!</h1>
<h2>현재 시간: {new Date().toLocaleTimeString()}</h2>
</div>
)
}
export default Clock;
수정
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Clock from './chapter_04/Clock';
const root = ReactDOM.createRoot(document.getElementById('root'));
setInterval(()=>{
root.render(
<React.StrictMode>
<Clock />
</React.StrictMode>
);
}, 1000);
reportWebVitals();
setInterval( )함수를 사용해서 1,000ms(1초)마다
새롭게 Clock 컴포넌트를 root div에 렌더링하도록 코드를 수정했다.
엘리먼트의 정의
엘리먼트의 생김새
엘리먼트의 특징
엘리먼트는 한 번 생성되면 바꿀 수 없기 떄문에 엘리먼트를 업데이트하기 위해서는
다시 생성해야 함
기존 엘리먼트를 변경하는 것이 아니라 새로운 엘리먼트를 생성해서 바꿔치기하는 것