우리는 JSX 문법을 사용하기 때문에 리액트 돔 요소를 잘 모를 수 있습니다. 이런 JSX 문법은 Babel이 createElement 를 호출하는 코드로 변환해 줍니다.
const jsxDOM = <p>돔</p>;
const reactDOM = React.createElement('p', {}, '돔');
브라우저에서 돔을 변경하는 것은 비교적 오래 걸리는 작업입니다. 그래서 빠른 렌더링을 위해서 돔 변경을 최소화 하는것이 좋습니다. 이러한 돔 변경의 최소화를 위해 리액트는 가상 돔이라는 것을 활용합니다. 리액트는 메모리에 가상 돔을 올려놓고 이전과 이후에 가상 돔을 비교 후, 변경된 부분만 실제 돔에 반영하는 전략을 채택하고 있습니다.
리액트에 가상 돔을 만들고, 실제 돔에 반영할 변경 사항을 찾는 과정을 한번 따라가 보겠습니다. 아래의 코드는 jsx 표현식으로 코드를 작성하는 경우에 어떤 구조로 객체를 생성하는지를 보여줍니다. jsxDOM 을 출력한 형태가 consoleLogResult 라고 보시면 됩니다.
const jsxDOM = (
<a key="key1" style={{ width: 100 }} href="http://google.com">
click here
</a>
)
console.log(jsxDOM);
const consoleLogResult = {
type: 'a',
key: 'key1',
ref: null,
props: {
href:'http://google.com',
style: {
width: 100,
},
children: 'click here',
},
// ...
}
리액트 요소 트리가 실제 돔으로 만들어 지기 위해서는 모든 리액트 요소의 타입 속성값이 문자열이어야 합니다. 예를 들어 아래와 같이 type이 Title 인 리액트 요소 트리가 있다면 한번 더 변환될 필요가 있는 것입니다.
function Title({ title }) {
return (
<h2>{title}</h2>
);
}
const jsxDOM = (
<a key="key1" style={{ width: 100 }} href="http://google.com">
<span>click here</span>
<Title title="리액트 공부하기"/>
</a>
);
console.log(jsxDOM);
const consoleLogResult = {
type: 'a',
key: 'key1',
ref: null,
props: {
href:'http://google.com',
style: {
width: 100,
},
children: [
{type: 'span', props: {children: 'click here'}},
{type: Title, props: {title: '리액트 공부하기'}}
],
},
// ...
}
한번 더 변환하여 아래와 같이 모든 리액트 요소 타입의 속성값이 문자열이 된다면 이것을 가상 돔이라고 할 수 있습니다. 하지만, 가상 돔은 UI 에서 변경된 부분을 빨리 찾기 위한 개념이므로, 이러한 컴포넌트의 리액트 요소도 가상돔의 일부라고 생각할 수 있습니다.
function Title({ title }) {
return (
<h2>{title}</h2>
);
}
const jsxDOM = (
<a key="key1" style={{ width: 100 }} href="http://google.com">
<span>click here</span>
<Title title="리액트 공부하기"/>
</a>
);
console.log(jsxDOM);
const consoleLogResult = {
type: 'a',
key: 'key1',
ref: null,
props: {
href:'http://google.com',
style: {
width: 100,
},
children: [
{type: 'span', props: {children: 'click here'}},
{type: 'h2', props: {children: '리액트 공부하기'}}
],
},
// ...
}
현재의 리액트 트리로부터 가상 돔을 만들고, 이전 가상 돔과 비교해서 실제 돔에 반영할 내용을 결정하는 단계를 렌더 단계라고 부릅니다. 참고로, 최종 리액트 요소 트리를 만들기 위해서 치환되는 Title과 같은 컴포넌트의 리액트 요소도 메모리에 저장되서 렌더 단계의 효율을 높이는데 사용됩니다. 렌더 단계는 render 함수를 호출하거나 상태값 변경 함수를 호출하는 것으로 시작될 수 있습니다.
다음으로 이전의 가상 돔과 현재의 가상 돔을 비교하여 실제 돔에 반영하는 단계를 커밋 단계라고 부릅니다. 이 경우에 필요한 돔만 변경할 수 있도록 리액트가 내부적으로 처리를 해줍니다. 따라서 UI 렌더링에 대한 속도를 향상 시킬 수 있습니다.
전체의 과정을 정리해 보겠습니다. 렌더 함수가 호출되면서 최초의 렌더 단계가 실행이 되었고, 이렇게 만들어진 가상 돔이 실제 돔으로 만들어졌습니다. 사용자의 행위로 컴포넌트의 상태값이 변경이 되었고, 곧 두번째 랜더 단계가 실행이 되고, 새로운 가상 돔이 만들어졌습니다. 이 때, 이전의 가상 돔과 비교해서 변경된 부분만 실제 돔에 반영이 됩니다.
출처 : 실전 리액트 프로그리맹 - 인프런 (추천합니다 !!)
[Frontend/React] 12. Context API 를 사용하여 데이터 전달하기 (0) | 2020.10.03 |
---|---|
[Frontend/React] 11. 리액트 훅(hook) (0) | 2020.10.03 |
[Frontend/React] 9. Fragment / Potal 사용하기 (0) | 2020.10.03 |
[Frontend/React] 8. 컴포넌트의 속성값과 상태값 (0) | 2020.10.03 |
[Frontend/React] 7. 단일 페이지 애플리케이션(SPA) (0) | 2020.10.03 |