[๐Ÿ’ŽReact] ์ œ์–ด ์ปดํฌ๋„ŒํŠธ์™€ ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ

h-a-n-aยท2023๋…„ 5์›” 11์ผ
1

๐Ÿ’ŽReact

๋ชฉ๋ก ๋ณด๊ธฐ
1/14

๋ฆฌ์•กํŠธ ํ›… ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค๋Š” ์„ค๋ช…์ด ์žˆ์—ˆ๋‹ค. ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฌด์—‡์ด๊ณ , ์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฌด์—‡์ด๋ž€ ๋ง์ธ๊ฐ€?
์˜ค๋Š˜์€ ์ด๊ฒƒ์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

์ œ์–ด ์ปดํฌ๋„ŒํŠธ

๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด

์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž์‹ ์˜ state๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. React์—์„œ๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” state๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์˜ state ์†์„ฑ์— ์œ ์ง€๋˜๋ฉฐ setState()์— ์˜ํ•ด ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.
(์ค‘๋žต)
์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ React์— ์˜ํ•ด ๊ฐ’์ด ์ œ์–ด๋˜๋Š” ์ž…๋ ฅ ํผ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ โ€œ์ œ์–ด ์ปดํฌ๋„ŒํŠธ (controlled component)โ€œ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

export default function App() {
  const [input, setInput] = useState("");
  const onChange = (e) => {
    setInput(e.target.value);
  };

  return (
    <div className="App">
      <input onChange={onChange} />
    </div>
  );
}

์ฆ‰, ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๋ฐ›๋Š” ์ปดํฌ๋„ŒํŠธ์— event ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด setState()๋กœ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์ œ์–ด ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’๊ณผ ์ €์žฅ๋˜๋Š” ๊ฐ’์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋™๊ธฐํ™”๋œ๋‹ค.

๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ

๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ์กด์˜ ๋ฐ”๋‹๋ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ฐ”๋‹๋ผ์—์„œ ํผ์„ ์ œ์ถœํ•˜๋Š” ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ์š”์†Œ ๋‚ด๋ถ€์˜ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ์„ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ๋• setState()๊ฐ€ ์•„๋‹Œ ref๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ’์„ ์–ป๊ณ , ๊ทธ ๊ฐ’์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋™๊ธฐํ™”๋˜์ง€ ์•Š๋Š”๋‹ค. ๋งŒ์•ฝ A์™€ B๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์„ ๋•Œ, A์— ๋Œ€ํ•œ ๋ณ€ํ™”๋ฅผ ์ฆ‰๊ฐ์ ์œผ๋กœ B๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›์•„์•ผ ํ•  ๋•Œ ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋Ÿฐ ๋ฐฉ์‹์— ๋Œ€ํ•œ ๋Œ€์‘์„ ํ•  ์ˆ˜ ์—†๋‹ค.

export default function App() {
  const inputRef = useRef(); // ref ์‚ฌ์šฉ
  const onClick = () => {
    console.log(inputRef.current.value);
  };

  return (
    <div className="App">
      <input ref={inputRef} />
      <button type="submit" onClick={onClick}>
        ์ „์†ก
      </button>
    </div>
  );
}

์ •๋ฆฌํ•˜์ž๋ฉด,
์ œ์–ด ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ์„ ํ•˜๋Š” ์•ก์…˜์„ ์ทจํ•  ๋•Œ๋งˆ๋‹ค ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ์™€ UI์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์ด ํ•ญ์ƒ ๋™๊ธฐํ™”๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. (ํ•ญ์ƒ ์ตœ์‹ ๊ฐ’ ์œ ์ง€)

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

์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ?

์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์€ ๋ฐฉ์‹์€ ๋ณดํ†ต ์•„๋ž˜ ์„ธ๊ฐ€์ง€๋ผ๊ณ  ํ•œ๋‹ค.

  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
  • ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์ „์†ก ๋ฒ„ํŠผ์˜ ์ƒํƒœ๋ฅผ disabled๋กœ ํ‘œ์‹œํ•˜๊ธฐ
  • ์‹ ์šฉ์นด๋“œ์™€ ๊ฐ™์€ ํŠน์ • ์ž…๋ ฅ ๋ฐฉ์‹ ์ ์šฉํ•˜๊ธฐ

์ฃผ์˜ํ•  ์ 

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋™๊ธฐํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ถˆํ•„์š”ํ•œ ๋‹จ์–ด ์ž…๋ ฅ์‹œ์—๋„ ๊ฐ’์ด ๊ฐฑ์‹ ๋˜์–ด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง/api ์š”์ฒญ์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.(-> ์ž์›๋‚ญ๋น„) ์ด๋Ÿฐ ๋ถˆํ•„์š”ํ•œ ๋ฐฉ๋ฒ•์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„  ์Šค๋กœํ‹€์ด๋‚˜ ๋””๋ฐ”์šด์‹ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (throttle & debounce)

์ผ๋ฐ˜์ ์œผ๋กœ ๋ชจ๋“  form ์š”์†Œ์—์„œ ์ƒํƒœ์˜ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฑด ์•„๋‹ˆ๊ณ , form ์š”์†Œ๊ฐ€ ์ฆ๊ฐ€ํ• ์ˆ˜๋ก ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์“ฐ๋กœํ‹€์ด๋‚˜ ๋””๋ฐ”์šด์‹ฑ์„ ๊ฑธ๊ธฐ๋Š” ํž˜๋“ค๋‹ค. ๋งŒ์•ฝ ๊ฐ’์ด ํŠธ๋ฆฌ๊ฑฐ ๋œ ์ดํ›„์— ๊ฐฑ์‹ ์ด ๋˜์–ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ๋”์šฑ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ ‡๊ฒŒ ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด ๋ Œ๋”๋ง์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ react-hook-form ์ด๋‹ค.

๋Š๋‚€ ์ 

์ œ์–ด ์ปดํฌ๋„ŒํŠธ์™€ ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด ์•Œ๊ณ ๋‚˜๋‹ˆ, ๋ฆฌ์•กํŠธ ํ›… ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์œ ์šฉ์„ฑ์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ๋ฌด์กฐ๊ฑด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ์ผ ์œ ๋ช…ํ•œ ๊ฑฐ๋งŒ ์ฐพ์•„์„œ ์“ธ ๊ฒŒ ์•„๋‹ˆ๋ผ ๊ฑฐ๊ธฐ์— ๋‹ด๊ธด ์ฒ ํ•™์ด๋‚˜ ํ•„์š”์„ฑ์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๊ณ , ๋‚ด๊ฐ€ ์ฃผ์ฒด์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•˜๊ตฌ๋‚˜ ๋ผ๊ณ  ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋Š๊ผˆ๋‹ค!

์ฐธ๊ณ ์‚ฌ์ดํŠธ
justkeepgoing ๋‹˜์˜ ๋ฒจ๋กœ๊ทธ

profile
ํ•˜๋ฃจํ•˜๋ฃจ๊ฐ€ ์—ฐ์Šต์ด๋‹ˆ ๋‚ด์ผ์€ ๋” ๊ฐ•ํ•ด์งˆ ๊ฒ๋‹ˆ๋‹ค

0๊ฐœ์˜ ๋Œ“๊ธ€