React.createElement 호출의 복잡성 문제
React.createElement는 가상 DOM 객체를 만들어 주는 함수이지만 HTML요소가 부모/자식 관계로 구성되면 코드가 지나치게 복잡해지는 문제가 있다.
<ul>
<li>
<a href="http://www.google.com">
<p>go to google</p>
</a>
</li>
</ul>
이 코드를 React.createElement 호출로 구현해보자. 하지만 CE가 연속적으로 호출되면 해당 소스가 직관적으로 와닿지 않는다는 걸 알 수 있다.
import React from 'react'
import ReactDOM from 'react-dom/client'
const CE = React.createElement
const rootVirtualDOM = CE('ul', null, [
CE('li', null, [
CE('a', {href: 'http://google.com', target: '_blank'}, [
CE('p', null, 'go to google')
])
])
])
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(rootVirtualDOM)
위와 같은 React.createElement의 복잡성을 해결하기 위해 자바스크립트 언어에 없는 JSX기능을 언어 확장(language extension)형태로 추가했다.
import ReactDOM from 'react-dom/client'
// JSX코드를 통해 createElement의 복잡성을 해소함.
const rootVirtualDOM = (
<ul>
<li>
<a href="http://google.com" target="_blank">
<p>go to Googlef</p>
</a>
</li>
</ul>
)
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(rootVirtualDOM)
JSX = Javascript + XML
JSX는 'Javascript XML'의 줄임말로 XML 구문에 자바스크립트 코드를 결합해 사용하는 용도로 만들어진 구문이다.
React.createElement 호출 코드를 간결하게 하려고 고안된 것이며 자바스크립트 언어를 확장하는 방식으로 구현되었다.
- 웹 브라우저의 HTML 구문 분석기와 달리 JSX의 구문 분석기는 XML 규약을 엄격하게 준수해야 한다.
<input type="text"> → <input type="text" /> <img src="some url"> → <img src="some url" />
- JSX 구문에서 중괄호의 의미
XML에 자바스크립트 코드를 삽입하려면 중괄호{}를 사용하는 형태의 문법을 제공해 삽입한다. 중괄호 안의 자바스크립트 코드는 값만을 반환해야 한다. return 없이 값을 반환하는 구문을 타입스크립트에서는 표현식이라고 한다.
const hello = 'hello world!' <p>{hello}</p> // 중괄호를 사용해 javascript를 jsx에 삽입한다.
표현식과 실행문, 그리고 JSX
표현식(expression)이란 return 키워드 없이 어떤 값을 반환하는 코드를 뜻한다. 1, true, 'Hello world!'처럼 값으로 칠 수 있는 것들을 의미한다. 1+1과 같은 코드 조각, 함수 호출로 반환되는 값 등 값이 될 수 있는 모든 것을 의미한다. 표현식과 대비되는 개념으로는 실행문(execution statement)이 있다. 실행문은 if, switch ~ case, for문 등을 의미한다. 즉, 그 자체로는 값이 아닌 것들을 의미한다.
배열과 JSX 구문
JSX구문은 단순화된 React.createElement 호출이므로 반환값은 가상DOM 객체이기 때문에 변수나 배열에 담을 수 있다.
또한, JSX문에서 자식 컴포넌트가 여러 개일 경우 반드시 XML 작성 원칙을 준수해야 한다. XML 문법에서 XML요소는 부모없이 존재할 수 없다.
import ReactDOM from 'react-dom/client'
const children = [
<li>
<a href="http://www.google.com" target="_blank">
<p>go to Google</p>
</a>
</li>,
<li>
<a href="http://www.google.com" target="_blank">
<p>go to Google</p>
</a>
</li>,
<li>
<a href="http://www.google.com" target="_blank">
<p>go to Google</p>
</a>
</li>
]
// {children}는 부모 컴포넌트인 <ul>없이 {children} 형태로 존재할 수 없다.
const rootVirtualDOM = <ul>{children}</ul>
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(rootVirtualDOM)
- 데이터 배열을 컴포넌트 배열로 만들기
import ReactDOM from 'react-dom/client' const children = [0, 1, 2].map((n: number) => <h3>Hello world! {n}</h3>) const rootVirtualDOM = <div>{children}</div> const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) root.render(rootVirtualDOM)
브라우저 상에서는 이렇게 key가 없다는 오류가 발생한다. 해당 오류를 제거하기 위해 key속성을 추가한다.
React에서 key는 리스트의 각 항목을 식별하기 위한 고유한 값으로 사용되며, 렌더링 성능을 최적화하고 컴포넌트가 적절히 업데이트 되도록 돕는 역할을 한다.
import ReactDOM from 'react-dom/client' import * as D from './data' const children = D.makeArray(10).map((notUsed, index) => ( <div key={index}> <p>{D.randomId()}</p> <p>{D.randomName()}</p> <p>{D.randomJobTitle()}</p> <p>{D.randomSentence()}</p> <img src={D.randomAvatar()} width={100} height={100} /> </div> )) const rootVirtualDOM = <div>{children}</div> const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) root.render(rootVirtualDOM)
'FrontEnd > React' 카테고리의 다른 글
[React] key와 children 속성 이해하기 (0) | 2024.11.11 |
---|---|
[React] 컴포넌트 이해하기 (3) | 2024.11.11 |
[React] 리액트 동작 원리 (0) | 2024.11.10 |
[React] 첫 번째 리액트 프로젝트 만들기 (1) | 2024.11.10 |
[React] 리액트 개발환경 만들기 (etc. VSCode 개발환경 설정) (2) | 2024.11.08 |