๐Ÿ“ Study/React

[React] state์™€ ๋ฆฌ๋ Œ๋”๋ง

0=2. 2025. 6. 28. 17:59

โœ… ์™œ state๊ฐ€ ํ•„์š”ํ•œ๊ฐ€?

HTML์ด๋‚˜ React์—์„œ UI๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ •์ ์ธ ๊ตฌ์กฐ์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ UI๋Š” ์‚ฌ์šฉ์ž ์ž…๋ ฅ, ๋„คํŠธ์›Œํฌ ์‘๋‹ต, ํƒ€์ด๋จธ ๋“ฑ ์™ธ๋ถ€ ์ž๊ทน์— ๋”ฐ๋ผ ๋ฐ”๋€Œ์–ด์•ผ ํ•œ๋‹ค.

  • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ˆซ์ž๊ฐ€ ์ฆ๊ฐ€ํ•ด์•ผ ํ•จ
  • ๋กœ๊ทธ์ธํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ด๋ฆ„์ด ๋ณด์—ฌ์•ผ ํ•จ
  • ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋ฉด ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ฐ”๋€Œ์–ด์•ผ ํ•จ

 

์ˆ˜๋™ ๋ Œ๋” ๋ฐฉ์‹

์ƒํƒœ๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์ง์ ‘ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ˆ˜๋™์œผ๋กœ ๋ Œ๋”๋ง์„ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

let count = 0;

function handleClick() {
  count++;
  document.getElementById("value").textContent = count;
}

์ด ๋ฐฉ์‹์„ ์ด์šฉํ•˜๋ฉด ๋ Œ๋” ํƒ€์ด๋ฐ์„ ํŒ๋‹จํ•˜๊ณ  ๊ฐ’์„ ์ถ”์ ํ•ด์•ผํ•œ๋‹ค. ๋˜ํ•œ DOM์„ ์ˆ˜๋™์œผ๋กœ ์กฐ์ž‘ํ•œ๋‹ค.
๋งŒ์•ฝ count์— ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ UI ์š”์†Œ๋‚˜ ๋กœ์ง์ด ์žˆ์œผ๋ฉด, ๋™๊ธฐํ™”๊ฐ€ ๋ˆ„๋ฝ๋˜์–ด ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

React์˜ state๋ฅผ ์ด์šฉํ•˜๋ฉด count๋ผ๋Š” ์ƒํƒœ ํ•˜๋‚˜๋งŒ ๊ด€๋ฆฌํ•˜๋ฉด React๊ฐ€ UI๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์ด๋‹ค.

 

โœ… Vanilla JS์˜ DOM ์ˆ˜์ •๊ณผ React์˜ ๊ฐ€์ƒ DOM ๋น„๊ต

๋ธŒ๋ผ์šฐ์ €๊ฐ€ DOM์„ ๋ Œ๋”๋งํ•˜๋Š” 5๋‹จ๊ณ„

์ผ๋ฐ˜์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” HTML/CSS/JS๋ฅผ ๋ฐ›์•„ ์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•œ๋‹ค.

  1. HTML ํŒŒ์‹ฑ → DOM ํŠธ๋ฆฌ ์ƒ์„ฑ
  2. CSS ํŒŒ์‹ฑ → CSSOM ํŠธ๋ฆฌ ์ƒ์„ฑ
  3. DOM + CSSOM → ๋ Œ๋” ํŠธ๋ฆฌ(Render Tree) ์ƒ์„ฑ
  4. Layout (Reflow) → ๊ฐ ์š”์†Œ์˜ ์œ„์น˜, ํฌ๊ธฐ ๊ณ„์‚ฐ
  5. Paint (Repaint) → ์‹ค์ œ ํ”ฝ์…€์„ ํ™”๋ฉด์— ์น ํ•จ

์ด๊ฑธ ํ•ฉ์ณ์„œ ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ ๋˜๋Š” ๋ Œ๋” ํŠธ๋ฆฌ ์ƒ์„ฑ ๋ฐ ํ™”๋ฉด ์ถœ๋ ฅ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

 

์ผ๋ฐ˜ JavaScript (Vanilla JS)์˜ ๋ฌธ์ œ์ 

  • DOM์„ ์ง์ ‘ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ด ํŒŒ์ดํ”„๋ผ์ธ์ด ์ „์ฒด ํ˜น์€ ์ผ๋ถ€ ์žฌ์‹คํ–‰๋œ๋‹ค.
  • ํŠนํžˆ Layout & Paint ๋‹จ๊ณ„๊ฐ€ ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒํ•˜๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ์ƒ๊ธฐ๊ณ , ์• ๋‹ˆ๋ฉ”์ด์…˜, ํด๋ฆญ ๋ฐ˜์‘์ด ๋А๋ ค์ง€๋Š” ๋ Œ๋”๋ง ๋ณ‘๋ชฉ(bottleneck)์ด ์ƒ๊ธด๋‹ค.
document.getElementById("item").style.width = "200px";
document.getElementById("item").style.height = "300px";

๋‘ ๋ฒˆ ๋ชจ๋‘ layout & paint๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

React๋Š” ์–ด๋–ป๊ฒŒ ์ตœ์ ํ™”ํ• ๊นŒ?

React๋Š” Virtual DOM(๊ฐ€์ƒ DOM)์ด๋ผ๋Š” ๊ตฌ์กฐ๋ฅผ ๋„์ž…ํ•ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

 

๊ฐ€์ƒ DOM

  • ์‹ค์ œ DOM์„ ๋ฉ”๋ชจ๋ฆฌ์ƒ์— ๋ณต์ œํ•ด ๋งŒ๋“  ๊ฐ€๋ฒผ์šด ํŠธ๋ฆฌ ๊ตฌ์กฐ
  • ์ƒํƒœ(state)๊ฐ€ ๋ฐ”๋€Œ๋ฉด, React๋Š” ๊ฐ€์ƒ DOM์„ ๋จผ์ € ์—…๋ฐ์ดํŠธํ•จ
  • ์ด์ „ ๊ฐ€์ƒ DOM๊ณผ ๋ณ€๊ฒฝ๋œ ๊ฐ€์ƒ DOM์„ ๋น„๊ตํ•ด์„œ ์ฐจ์ด์ ๋งŒ ๊ณ„์‚ฐ(diffing)

๋ณ€๊ฒฝ์ ๋งŒ ์‹ค์ œ DOM์— ๋ฐ˜์˜

  • ๊ณ„์‚ฐ์ด ๋๋‚˜๋ฉด ๊ฐ€์žฅ ์ตœ์†Œํ•œ์˜ DOM ์ˆ˜์ •๋งŒ ์ ์šฉ(batch update ์ผ๊ด„ ์ฒ˜๋ฆฌ)
  • ๋ Œ๋”๋ง ํšŸ์ˆ˜ ์ตœ์†Œํ™”  ์„ฑ๋Šฅ ์ตœ์ ํ™” ํšจ๊ณผ

 

โœ… state

state๋Š” ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.
์ปดํฌ๋„ŒํŠธ๋Š” state๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋ง๋˜๋ฉฐ, ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ, ๋น„๋™๊ธฐ ์‘๋‹ต ๋“ฑ ๋‹ค์–‘ํ•œ ์ด์œ ๋กœ state๊ฐ€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค.

useState ํ›…

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ state๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด React๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํ›…์ด๋‹ค.

const [state, setState] = useState(initialValue);
  • initialValue: state์˜ ์ดˆ๊ธฐ๊ฐ’. ์ˆซ์ž, ๋ฌธ์ž์—ด, ๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ ์–ด๋–ค ์ž๋ฃŒํ˜•๋„ ๊ฐ€๋Šฅํ•จ.
  • state: ํ˜„์žฌ ์ƒํƒœ ๊ฐ’
  • setState: ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜ (modifier)

 

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // ์ดˆ๊ธฐ๊ฐ’ 0

  return (
    <div>
      <span>ํ˜„์žฌ ๊ฐ’: {count}</span>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

 

 

state๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” 2๊ฐ€์ง€ ๋ฐฉ์‹

์ง์ ‘ ํ• ๋‹น ๋ฐฉ์‹

setCount(count + 1);
  • count๊ฐ€ ํ˜„์žฌ ํด๋กœ์ € ์•ˆ์— ์žˆ๋Š” ๊ฐ’์ด๋ผ๋ฉด, ์ด๊ฑธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒˆ ๊ฐ’์„ ์ง์ ‘ ๊ณ„์‚ฐํ•ด์„œ ๋„ฃ๋Š” ๋ฐฉ์‹
  • ์ƒํƒœ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋น„๋™๊ธฐ์ ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์—ฌ๋Ÿฌ ๋ฒˆ ์—ฐ์† ํ˜ธ์ถœ ์‹œ ๊ฐ’ ๊ผฌ์ผ ์ˆ˜ ์žˆ์Œ
  • ์ƒˆ๋กœ์šด ๊ฐ’์ด ๊ธฐ์กด ์ƒํƒœ์™€ ๋ฌด๊ด€ํ•  ๋•Œ ์‚ฌ์šฉ

 

ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ ๋ฐฉ์‹

setCount(prev => prev + 1);
  • ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž prev๋Š” ํ˜„์žฌ ์ƒํƒœ ๊ฐ’์„ ๋œปํ•จ
  • ์ด ๋ฐฉ์‹์€ React๊ฐ€ ์ตœ์‹  ์ƒํƒœ ๊ฐ’์„ ์ž๋™์œผ๋กœ ๋„ฃ์–ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๋ฒˆ ์—ฐ์† ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ๋น„๋™๊ธฐ ์ƒํ™ฉ์—์„œ๋„ ์•ˆ์ •์ ์ž„
  • ๊ธฐ์กด ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์‚ฐ/๋ณ€ํ˜•ํ•  ๋•Œ ์‚ฌ์šฉ

 

const [count, setCount] = useState(0);

<button onClick={() => setCount(count + 1)}>+1</button>
const [count, setCount] = useState(0);

<button onClick={() => setCount(prev => prev + 1)}>+1</button>