거의 알고리즘 일기장
jsx, React.createElement, element 본문
jsx란?
react component안을 보면 html tag처럼 생긴걸 볼수 있다.
jsx는 javascript의 확장 문법으로, ui가 어떻게 생겨야 하는지 간단히 작성할수있다.
//예시
import React from 'react';
const Test = () => {
//return안에 있는 html tag같은게 jsx
return (
<div>
</div>
)
}
export default Test;
JSX는 React.createElement(component, props, ...children) 함수에 대한 문법적 설탕을 제공할 뿐입니다.
한문장으로 정의하자면 이렇다. ( JSX 이해하기 머릿글이다.)
jsx는 그냥 React.createElement(...args)을 우리가 보기 편한 형태인 html tag형태로 치환한 문법일 뿐이다.
그러면 이제 이 궁금증이 꼬리에 꼬리를 물고 생길것이다.
질문: 그럼 치환되는 형태인 React.createElement(...args)는 도대체 뭐냐?..
-> 함수의 이름으로도 유추할수있는데, react의 element를 return 한다.
질문: react의 element는 또 뭐냐?? ㅡㅡ
이 질문에 대한 답을 하기전에, 전통적인 UI programming과 react의 차이점에 대해서 보자.
전통적인 ui programming과 react의 가장 큰 차이점은
직접 DOM을 제어할 필요가 없다.
즉 전통적인 방식처럼 instant의 관리도 할 필요가 없는것이다. ex) instant 생성, 삭제, 업데이트 등등
그래도 이해가 안갈수 있으니, 이제 code level에서 살펴보자.
전통적인 ui programming 방식
class Form extends TraditionalObjectOrientedView {
render() {
// Read some data passed to the view
const { isSubmitted, buttonText } = this.attrs;
if (!isSubmitted && !this.button) {
// Form is not yet submitted. Create the button!
this.button = new Button({
children: buttonText,
color: 'blue'
});
this.el.appendChild(this.button.el);
}
if (this.button) {
// The button is visible. Update its text!
this.button.attrs.children = buttonText;
this.button.render();
}
if (isSubmitted && this.button) {
// Form was submitted. Destroy the button!
this.el.removeChild(this.button.el);
this.button.destroy();
}
if (isSubmitted && !this.message) {
// Form was submitted. Show the success message!
this.message = new Message({ text: 'Success!' });
this.el.appendChild(this.message.el);
}
}
}
위 코드에서 Form component(class)는
1. button과 message의 instance를 가지고 있다.
2. 각각의 instance의 create update delete에 대해서, 이 form component에서 다 관리해주고 있다.
이뿐만이 아니라, 이 코드는 서로 밀접하게 이어져있기 때문에, 추후에 분리나 다른 요소의 추가 같은 경우에 쉽지 않다.
react는 ??
우리가 작성한 element를 react에 전달하면, react가 이 element를 보고 알아서 관리를 해준다.
element: An element is a plain object describing a component instance or DOM node and its desired properties ( component instance나 dom node의 property들을 설명하는 object )
1. element는 react에게 우리가 화면에 뭘 그려야 할지 알려주는 객체!!
2. 우리가 instance에 직접 접근해서 method를 call 할수 없다. 그저, type과 props 두개의 field를 가진 객체다.
3. react가 이 element를 보고 instance를 제어한다.
쉽게 비유를 들자면, 우리가 react에게 ui rendering에 대해서 어떻게 해달라고 부탁하는 주문서라고 생각하면 더 쉽다.이제 우리는 jsx부터 element까지 알게 되었다.
여기서부터는 element에 대해서 더 자세히 알아보는 부분이므로, 넘어가도 좋다.
밑에 있는 링크글과 내용이 동일하니, 이 글을 읽어도 좋고..ㅎㅎ
https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html
element 형식
//이 type을 통해 react component를 뜻하는지, dom tag element를 뜻하는지 구분한다.
type: (string | ReactClass)
props: Object
//DOM element
{
type: 'button', //string, html tag name 이다.
props: {
className: 'button button-blue',
//children은 children prop을 이용해서 포함한다.
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
//Component Element
{
type: Button, //ReactClass
props: {
color: 'blue',
children: 'OK!'
}
}
element의 동작
이런 element가 있다고 하자
{
type: Button,
props: {
color: 'blue',
children: 'OK!'
}
}
react는 type이 string이 아닐시 (html tag name이 아닐시)
type이 string이 될때까지 찾아간다. 여기서는 Button이 무엇인지
//Button의 return 값
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
이제 맨위의 Form을 react의 방식대로 작성해보자.
const Form = ({ isSubmitted, buttonText }) => {
if (isSubmitted) {
// Form submitted! Return a message element.
return {
type: Message,
props: {
text: 'Success!'
}
};
}
// Form is still visible! Return a button element.
return {
type: Button,
props: {
children: buttonText,
color: 'blue'
}
};
};
instance의 생성, 삭제, 갱신들을 더이상 신경쓸 필요가 없으며, 코드 자체도 간략해진다.
조금의 노력으로 최적화가 가능하다.
밑의 코드를 실행시에
ReactDOM.render({
type: Form,
props: {
isSubmitted: false,
buttonText: 'OK!'
}
}, document.getElementById('root'));
react는 밑의 과정처럼 점진적으로 정리를 해간다.
// React: You told me this...
{
type: Form,
props: {
isSubmitted: false,
buttonText: 'OK!'
}
}
// React: ...And Form told me this...
{
type: Button,
props: {
children: 'OK!',
color: 'blue'
}
}
// React: ...and Button told me this! I guess I'm done.
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
이 과정이 reconciliation이다.
이건 ReactDOM.render() or setState()를 call할때 시작된다.
reconciliation이 끝나게 되면, renderer (react-dom or react-native)가 update의 필요성이 있는 dom node를 update한다.
이 과정 덕분에 react app이 최적화가 쉽다. 예를 들어 어떤 컴포넌트가 관련된 props가 변경되지 않은 경우 건너뛰는게 가능하다.
(Reconciliation: React에서 어떤 부분들이 변해야하는지 서로 다른 두 개의 트리를 비교하는 데 사용하는 알고리즘)
Reconciliation에 대해서 더 알고 싶다면
https://ko.reactjs.org/docs/reconciliation.html
이 글을 한번 읽어보길 바란다. 어떠한 알고리즘을 썼고 어떠한 상황에서 빠른지에 대해서 적혀있다.
참고
https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html
'web' 카테고리의 다른 글
yarn berry, workspace에 대해서 (0) | 2022.05.05 |
---|---|
GraphQL 찍먹기 (0) | 2022.03.06 |
ajax? fetch? axios? (0) | 2021.11.29 |
요즘 쓰는 git commit message convention (0) | 2021.11.27 |
custom useAxios hook (0) | 2021.11.11 |