본문 바로가기

프론트엔드 개발/React - 이론

ReactElement란 무엇인가

0. 개요

본 포스팅에서는

ⓐ React Element란 무엇인가? 

ⓑ 그것이 어떻게 DomElement로 변환되어 랜더링되는지

에 대해서 알아보겠다. 

1. React Element란? 

(0) Element에 대하여

먼저 Element가 무엇인지 알아보겠다. Element의 사전적 의미는 '물체를 구성하는 성분'을 뜻한다. Html을 공부하면서 DomElement에 대해 들어 봤을 것이다. DOM Element는 화면을 구성하는 하나의 성분을 의미한다. 예를 들어 설명하겠다. 

위의 화면을 F12 개발자 모드로 둘러보면 다음과 같다. 

여기서 Div 태그 하나하나, 혹은 그 Div 태그 속 h1, h2 태그 하나하나가 화면을 구성하는 성분 중 하나임으로 DOM Element에 해당한다. 

ⓑ 그렇다면 React Element란 무엇인가

React Element란 리액트 앱을 구성하는 가장 작은 블록(성분)을 의미한다. ReactElement 또한 DOM Element처럼 원래 Element의 의미를 따르는 개념이다. 

 근데 이러면, React와 DOM에서 같은 Element라는 말을 사용해서 단어 사용에 혼돈이 오지 않을까?
 

당연히 그럴 수 있다고 생각한다. 근데도 Element라는 말을 양쪽에서 겹치게 사용하는 이유가 있다. 그 이유를 풀어쓰면 다음과 같다. 먼저 React에서는 '화면에 나타나는 내용에 대해 기술 하는 자바스크립트 객체'를 지칭하는 단어가 필요했다. 그래서 처음에는 해당 객체를 지칭하는 단어로 discriptor라는 표현을 썼다. 화면 내용에 대해 기술한다는 의미에서 만들어낸 신조어였다.  하지만, discriptor와 DOM Element의 관계를 생각했을 때, 해당 단어의 사용이 더 큰 혼란을 초래했다.

위에서 React Elements라고 써진 말을 Discriptor라고 잠시 치환하여 생각해보자. Discriptor와 Dom Elements의 관계를 보면, Discriptor를 랜더링(빌드)하면 DOM Elements가 된다. 따라서 디스크립터는 하나의 설계도이고, DOM 엘리먼츠는 그 설계도의 구현체인 셈이다. 두 개념은 구현 전인가, 구현 후인가 시간적 요소를 빼면 같은 내용인데, 아예 다른 신조어로 부르니까, 개념 이해 시 혼돈을 초래했다. 따라서 discripotor 또한 React 안의 Elements란 의미로 React Elements로 불리게 되었다. 정리하면 

React Elements 

"React 앱을 구성하는 가장 작은 블록" 

"화면을 어떻게 그릴지에 대해 기술하는 자바스크립트 객체"

= "랜더링 되지 않은 DOM Elements"

로 볼 수 있다. 

2. React Elements가 DOM Elements로 랜더링 되는 원리

ⓐ 전개도로 설명한 원리

전개도에 대한 설명은 다음과 같다. 
1. 우리가 먼저 React 컴포넌트를 작성한다. React 컴포넌트는 우리가 평소에 작성하던 하나의 변수 혹은 함수 로직이다. 
2. npm run start 등으로 Build를 시작하면, React 프레임워크에서 jsx파일에 대하여 React.createElements()를 수행한다. 
   (이때, createElements의 인수로는 type, [props], [... children]이 있다. type은 태그의 이름이다. props는 태그의 속성을 포함하고 있는 객체이다. 아직까지 우리는 props를 태그의 속성에 대한 값을 불러오는데만 사용한다. children는 자식 태그들이다.)

 3. React.createElements()는 컴포넌트를 React Element로 변환하는 역할을 한다. React Element는 아까 설명했듯이 화면에 그려질 내용을 기술하는 자바 스크립트 객체이다. 따라서 변환 후 모습은 다음과 같다. 

{
	type: "h1",
    props: {
    	children: "안녕하세요"
    }
}

 4. 해당 React Elements는 랜더링 되면서 진짜 Dom Elements로 변환된다. 그리고 그 DOM Elements가 우리가 보는 화면 속 구성요소이다. 

<h1> 안녕하세요 </h1>

너무 복잡하게 설명한 감이 있어서 1줄 요약한다.

(1. 개발자가 React 컴포넌트 작성) > (2. Build 시작...) > (3.React.createElements함수가 컴포넌트를 React Elements 객체로 변환) > (4. 해당 객체는 Rendering 될 때, 진짜 DOM 객체로 변환됨.) 

ⓑ 복잡한 예시 

하지만 이런 경우도 있을 수 있다. 

제가 만든 React 컴포넌트는 React 컴포넌트 안에 자식 태그로 진짜 태그가 아니라 또 다른 컴포넌트를 들고 있는데요? 이 경우는 변환 과정이 어떻게 되나요? 

좋은 질문이다! 이는 예를 들어서 설명하겠다. 

 

⑴ 컴포넌트 작성 

내가 짠 코드가 다음과 같다고 생각해보자. 
  ConFirmDialog라는 컴포넌트는 P 태그와 내가 새로 만든 사용자 정의 Button 태그를 가지고 있다. (기본 제공되는 버튼은 소문자로 시작하는 button 태그이다!) Button 태그는 새로운 컴포넌트로서 맨 위에 기술되어있다. Button 태그 속 내용물은 기본 button 태그와 b 태그 이다. 

 

⑵ React Elements로 변환

변환된 모습이다.  Confirm Dialog는 따로 props를 사용하지 않았음으로 Children 태그로 넘어가자. 거기서 기본 p 태그는 문자열 "p" 형태로 Type이 기술되어있고, 이하 내용은 위의 전개도 예시와 똑같다. 그리고 요주의 인물인 사용자 정의 Button 컴포넌트 부분을 살펴보자. 해당 부분은 "" 문자열 형태로 되어있지 않고, type: Button 형태로 그대로 써져있다. 이는 React.createElements 함수가 해당 부분은 기본 태그가 아닌 컴포넌트임을 인지하여 저렇게 적은 것이다. 이를 확인한 React는 해당 부분에 대해서 다시 한번 더 변환을 진행한다. 해당 변환은 태그가 더 이상 컴포넌트가 아니고, 진짜 HTML 태그를 만날 때까지 drilling 하여 진행 된다. 그래서 최종 형태는 다음과 같다. 

해당 부분에서 알 수 있듯 태그 사이에 내용물인 문자열은 children으로 들어가게 된다. 이제 이것이 랜더링 시에 DOM Elements가 되는 것이다. 

한 줄 요약 하면 

컴포넌트 속에 컴포넌트가 있을 시, React는 해당 컴포넌트를 JS 객체로 변환할 때, 모든 내용물이 HTML 태그와 문자열로 표현될때까지 drilling 하여 표현한다.