[๋ฐ๋ธŒ์ฝ”์Šค] React์™€ JSX, UI ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ์ „ํ™˜

2025. 6. 14. 23:55ยท๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค/TIL

React๋Š” ํ”„๋ก ํŠธ์—”๋“œ์˜ ์‚ฌ๊ณ ๋ฐฉ์‹์„ ์™„์ „ํžˆ ๋ฐ”๊พผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. DOM์„ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” imperative ๋ฐฉ์‹์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด UI๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜์‹œ์ผฐ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•ต์‹ฌ์—๋Š” JSX๋ผ๋Š” ๋…ํŠนํ•œ ๋ฌธ๋ฒ•์ด ์žˆ๋‹ค. 

 

JSX๋Š” ์ฒ˜์Œ๋ณด๋ฉด, HTML๊ณผ Javascript๋ฅผ ์„ž์€ ์กฐ๊ธˆ ์ด์ƒํ•œ ๋ชจ์Šต(ใ…Žใ…Ž)์œผ๋กœ ๋ณด์ธ๋‹ค. ํ•˜์ง€๋งŒ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋†€๋ผ์šด ์ผ๊ด€์„ฑ๊ณผ ํšจ์œจ์„ฑ์„ ๊ฐ–์ถ˜ ๋ฌธ๋ฒ•์ด๋‹ค. ์˜ค๋Š˜์€ React์™€ JSX๊ฐ€ ์™œ ๋“ฑ์žฅํ–ˆ๊ณ , ์–ด๋–ค ์ฒ ํ•™๊ณผ ๊ตฌ์กฐ๋กœ ์„ค๊ณ„๋˜์—ˆ๋Š”์ง€ ์•Œ์•„๋ณธ๋‹ค


React์˜ ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ - DOM ์ง€์˜ฅ ํƒˆ์ถœํ•˜๊ธฐ

2010๋…„๋Œ€ ์ดˆ๋ฐ˜, ํ”„๋ก ํŠธ์—”๋“œ์˜ ๋ณต์žก๋„๋Š” ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ–ˆ๋‹ค. DOM ์กฐ์ž‘์€ ์ ์  ์–ด๋ ค์›Œ์กŒ๊ณ  ์ƒํƒœ์™€ ๋ทฐ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋™๊ธฐํ™”ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋„˜์ณ๋‚ฌ๋‹ค.

const div = document.createElement('div');
div.innerText = user.isLoggedIn ? '๋กœ๊ทธ์•„์›ƒ' : '๋กœ๊ทธ์ธ';
parent.appendChild(div);
  • ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด? -> ์ง์ ‘ DOM ๋‹ค์‹œ ์ˆ˜์ •ํ•ด์•ผ ํ•จ
  • UI๊ฐ€ ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก ์ฝ”๋“œ๋„ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ๋Š˜์–ด๋‚ฌ๋‹ค.

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํƒˆ์ถœํ•˜๊ธฐ ์œ„ํ•ด, React๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐœ์ƒ์„ ๋„์ž…ํ•˜์˜€๋‹ค.

์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ „์ฒด UI๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ด๋„ ๋˜์ง€ ์•Š์„๊นŒ?

์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ ๊ฒƒ์ด Virtual DOM์ด๋‹ค. ์‹ค์ œ DOM ๋Œ€์‹  ๋ฉ”๋ชจ๋ฆฌ ์ƒ์˜ DOM ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ณ€๊ฒฝ ์ „ํ›„๋ฅผ diffingํ•˜๊ณ , ์‹ค์ œ DOM์—๋Š” ์ตœ์†Œํ•œ์˜ ๋ณ€๊ฒฝ๋งŒ ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

์ด ์ฒ ํ•™์„ ๊ธฐ๋ฐ˜์œผ๋กœ, React๋Š” ๋‹ค์Œ์„ ์ œ์•ˆํ•˜์˜€๋‹ค.

  • UI = ์ƒํƒœ์— ๋”ฐ๋ฅธ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ
  • ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋ฉด ์ปดํฌ๋„ŒํŠธ ๋‹ค์‹œ ํ˜ธ์ถœ(re-render)
  • React๊ฐ€ ํšจ์œจ์ ์œผ๋กœ DOM patching ์ˆ˜ํ–‰

 

JSX์˜ ๋“ฑ์žฅ - UI๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋‹ค

React์˜ ํ•ต์‹ฌ์€ UI๋ฅผ ํ•จ์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

function Button(props) {
  return React.createElement('button', null, props.label);
}

๊ทธ์น˜๋งŒ ์ด๋Ÿฐ ์ฝ”๋“œ๋Š” ๋„ˆ๋ฌด ์žฅํ™ฉํ•˜๋‹ค. ๊ฒฐ๊ตญ HTML๊ณผ ๋น„์Šทํ•œ UI ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์‹ถ์–ด์ง„๋‹ค. ๊ทธ๋ž˜์„œ ๋“ฑ์žฅํ•œ ๊ฒƒ์ด JSX์ด๋‹ค.

 

JSX๋Š” syntactic sugar

<Button label="Click me" />

๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ JS์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

 

React.createElement(Button, { label: 'Click me' });

์ฆ‰, JSX๋Š” React.createElement ํ˜ธ์ถœ์„ ์งง๊ฒŒ ์“ฐ๋Š” ๋ฌธ๋ฒ•์ด๋‹ค. HTML์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” Javascript ์ฝ”๋“œ๋‹ค. ๊ทธ๋ž˜์„œ ์กฐ๊ฑด๋ฌธ, ๋ฐ˜๋ณต๋ฌธ, ๋ณ€์ˆ˜ ์‚ฝ์ž…์ด ์ž์œ ๋กญ๋‹ค.

 

JSX์˜ ์ง„์งœ ์žฅ์  - ์„ ์–ธํ˜• UI์™€ ํŠธ๋ฆฌ ๊ตฌ์กฐ ํ‘œํ˜„

JSX์˜ ๋“ฑ์žฅ์€ ๋‹จ์ˆœํžˆ ๋ฌธ๋ฒ•์˜ ํŽธ์˜์„ฑ์„ ๋„˜์–ด์„œ, UI๋ฅผ ํŠธ๋ฆฌ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.

 

UI๋ฅผ ํ•˜๋‚˜์˜ ํŠธ๋ฆฌ๋กœ ๋ฐ”๋ผ๋ณด๋Š” ์‚ฌ๊ณ ๋ฐฉ์‹

<App>
  <Header />
  <Main>
    <Article />
    <Sidebar />
  </Main>
  <Footer />
</App>

์ด๊ฑด ๋‹จ์ˆœํ•œ ํƒœ๊ทธ ๋‚˜์—ด์ด ์•„๋‹ˆ๋‹ค! ์ด ์ž์ฒด๊ฐ€ UI ํŠธ๋ฆฌ๋‹ค. ๋ฐ์ดํ„ฐ๋กœ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ์ˆœํšŒํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋‹ค. React๋Š” ์ด๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ Virtual DOM์œผ๋กœ ๊ตฌ์„ฑํ•œ ํ›„ diffing & patching์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

Babel ํŠธ๋žœ์ŠคํŒŒ์ผ๋ง

๋ธŒ๋ผ์šฐ์ €๋Š” JSX๋ฅผ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ฝ”๋“œ๋Š” ๋ฐ˜๋“œ์‹œ babel์„ ํ†ตํ•ด ๋ณ€ํ™˜๋˜์–ด์•ผ ํ•œ๋‹ค.

<Button label="Hi" />

⇓

React.createElement(Button, { label: 'Hi' });

์ด ๊ณผ์ • ๋•๋ถ„์— ์šฐ๋ฆฌ๋Š” HTML-like ๋ฌธ๋ฒ•์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ๋™์‹œ์— ํƒ€์ž… ์‹œ์Šคํ…œ๊ณผ ESLint, Prettier ๊ฐ™์€ ๋„๊ตฌ๋„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

JSX ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹

JSX๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ตญ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

{
  type: 'button',
  props: {
    children: 'ํด๋ฆญ',
    onClick: () => alert('clicked'),
  },
  key: null,
  ref: null,
  $$typeof: Symbol(react.element)
}

์ฆ‰, JSX๋Š” ReactElement๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ผ์ข…์˜ ๋นŒ๋”๋‹ค. ์ด ReactElement๋Š” Virtual DOM ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ๊ฐ€ ๋˜๋ฉฐ, ๋ฆฌ๋ Œ๋”๋ง ์‹œ diff์˜ ๊ธฐ์ค€์ด ๋œ๋‹ค.

 

JSX vs Template ๋ฌธ๋ฒ•

Vue, Angular๋Š” HTML ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋ฐ˜๋ฉด React๋Š” JSX๋ฅผ ํ†ตํ•ด UI๋„ Javascript์˜ ์ผ๋ถ€๋กœ ๊ฐ„์ฃผํ•œ๋‹ค. ์ด ๋ฐฉ์‹์—๋Š” ๊ฐ•๋ ฅํ•œ ์žฅ์ ์ด ์žˆ๋‹ค.

//์กฐ๊ฑด๋ฌธ
{isLoggedIn && <LogoutButton />}

//๋ฐ˜๋ณต๋ฌธ
{items.map(item => <Item key={item.id} {...item} />)}

//์ƒ์ˆ˜ ๋ถ„๋ฆฌ
const controls = <ControlPanel />;
return <Header right={controls} />;

ํ…œํ”Œ๋ฆฟ ๋ฌธ๋ฒ•์—์„œ๋Š” ์ด ๋ชจ๋“  ๊ฑธ ๋ณ„๋„์˜ ๋ฌธ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜์ง€๋งŒ, JSX๋Š” JS๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.

 

JSX์˜ ๋‹จ์  

  • HTML๊ณผ ๋น„์Šทํ•˜๋‚˜ ์™„์ „ํžˆ ๊ฐ™์ง€๋Š” ์•Š๋‹ค.
  • Babel ์„ค์ • ํ•„์š”(ํŠธ๋žœ์ŠคํŒŒ์ผ ๋‹จ๊ณ„ ์ถ”๊ฐ€)
  • ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์™€ ํ•จ๊ป˜ ์“ฐ๋ ค๋ฉด ์ถ”๊ฐ€ ์„ค์ • ํ•„์š”

ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„ ๋‹จ์ ์ด๋ผ๊ณ  ํ• ๋งŒํ•œ ๊ฒƒ๋“ค์€ ํ™˜๊ฒฝ ์…‹์—… ๋ฌธ์ œ๊ณ , ๋”ฑํžˆ ๋‹จ์ ๋„ ์•„๋‹ˆ๊ธด ํ•จ. ์žฅ๊ธฐ์ ์œผ๋กœ ๋ณด๋ฉด JSX์˜ ์ผ๊ด€์„ฑ๊ณผ ํ™•์žฅ์„ฑ์€ ์ด์ ์ด ๋” ํฌ๋‹ค.


React์™€ JSX๋Š” UI๋ฅผ ๋ฐ์ดํ„ฐ์ฒ˜๋Ÿผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“  ์‚ฌ๊ณ ๋ฐฉ์‹์˜ ์ „ํ™˜์ด๋‹ค. imperative → declarative, mutable DOM → immutable state, ์ˆ˜๋™ ๋ Œ๋”๋ง → ์ž๋™ ๋ฆฌ๋ Œ๋”๋ง์œผ๋กœ์˜ ์ „ํ™˜์ด๋‹ค.

JSX๋Š” ์ด ํŒจ๋Ÿฌ๋‹ค์ž„์„ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ€์žฅ ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค. ๋‹จ์ˆœํ•œ ๋ฌธ๋ฒ•์ด ์•„๋‹ˆ๋ผ, UI๋ฅผ ์ฝ”๋“œ๋กœ ์„œ์ˆ ํ•˜๋Š” ์ƒˆ๋กœ์šด ์–ธ์–ด๋‹ค. React๋ฅผ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ  ์“ฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” JSX๊ฐ€ ๋‹จ์ˆœํ•œ HTML์ด ์•„๋‹˜์„ ๋ช…ํ™•ํžˆ ์ธ์‹ํ•ด์•ผ ํ•œ๋‹ค.

'๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค > TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[๋ฐ๋ธŒ์ฝ”์Šค] Redux  (2) 2025.06.16
[๋ฐ๋ธŒ์ฝ”์Šค] React ๊ธฐ์ดˆ ํ•ต์‹ฌ ์ •๋ฆฌ(state, ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น, ์ปดํฌ๋„ŒํŠธ ๋ฐ˜๋ณต)  (1) 2025.06.15
[๋ฐ๋ธŒ์ฝ”์Šค] ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ: ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋ถ€ํ„ฐ ํด๋ž˜์Šค๊นŒ์ง€  (0) 2025.06.11
[๋ฐ๋ธŒ์ฝ”์Šค] ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ธฐ์ดˆ(ํƒ€์ž…, ์ธํ„ฐํŽ˜์ด์Šค, ์—ด๊ฑฐํ˜•)  (1) 2025.06.10
[๋ฐ๋ธŒ์ฝ”์Šค] ๊ฐ์ฒด์ง€ํ–ฅ ์–ธ์–ด  (3) 2025.06.04
'๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค/TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [๋ฐ๋ธŒ์ฝ”์Šค] Redux
  • [๋ฐ๋ธŒ์ฝ”์Šค] React ๊ธฐ์ดˆ ํ•ต์‹ฌ ์ •๋ฆฌ(state, ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น, ์ปดํฌ๋„ŒํŠธ ๋ฐ˜๋ณต)
  • [๋ฐ๋ธŒ์ฝ”์Šค] ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ: ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋ถ€ํ„ฐ ํด๋ž˜์Šค๊นŒ์ง€
  • [๋ฐ๋ธŒ์ฝ”์Šค] ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ธฐ์ดˆ(ํƒ€์ž…, ์ธํ„ฐํŽ˜์ด์Šค, ์—ด๊ฑฐํ˜•)
ํ‚ํ‚์ž‰
ํ‚ํ‚์ž‰
๋ฟŒ๋ก ํŠธ ๊ฐœ๋ฐœ์ž(์ง€๋ง์ƒ)์˜ ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž ๋„์ „๊ธฐ
  • ํ‚ํ‚์ž‰
    monicx.dev
    ํ‚ํ‚์ž‰
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (115) N
      • ๐Ÿ–ฅ๏ธdevelop (13) N
        • Github (2)
        • Frontend (6) N
        • Backend (5)
        • Mobile (0)
        • CS (0)
        • Three.js (0)
        • Docker (0)
      • ๐Ÿ“•review (17)
        • ์ฑ… (12)
        • ํ–‰์‚ฌ (0)
        • ํšŒ๊ณ  (2)
      • โญproject (5)
        • petiary (2)
        • ๆšŽ่ฉ  (0)
        • ์ธํ„ด (2)
      • ๐Ÿ˜ถ‍๐ŸŒซ๏ธalgorithm (0)
      • ๐Ÿ’กtips (1)
      • ๐Ÿ˜Ždaily (10)
      • ๐Ÿ•น๏ธgame (0)
      • ๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค (65) N
        • TIL (41) N
        • ํ”„๋กœ์ ํŠธ (16)
        • ํšŒ๊ณ  (8)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
  • ๋งํฌ

    • ๋ฒจ๋กœ๊ทธ
  • ์ธ๊ธฐ ๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
ํ‚ํ‚์ž‰
[๋ฐ๋ธŒ์ฝ”์Šค] React์™€ JSX, UI ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ์ „ํ™˜
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”