[React] useRef์™€ ์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ (#09-2)

  • React
[React] useRef์™€ ์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ (#09-2)

๐Ÿ“ ์—ฐ๊ด€ ํฌ์ŠคํŒ…

Github


์„œ๋ก 

์ž…๋ ฅ ํผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ, ๋ชจ๋“  ํ‚ค ์ž…๋ ฅ๋งˆ๋‹ค ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋Œ€์‹  "์ €์žฅ" ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์‹œ์ ์—๋งŒ ๊ฐ’์„ ์ฝ์–ด์˜ค๊ณ  ์‹ถ๋‹ค๋ฉด Ref ์‚ฌ์šฉํ•˜์ž

-> ์™œ๋ƒ๋ฉด ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ณ„์† ํŒ”๋กœ์—…ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ..

์‚ฌ์‹ค useState๋กœ๋„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์™œ useRef๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ?

useState ์™€ useRef์˜ ์ฐจ์ด

๋น„๊ต ํ•ญ๋ชฉ useState (์ œ์–ด ์ปดํฌ๋„ŒํŠธ) useRef (๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ)
๋ฆฌ๋ Œ๋”๋ง ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒ (๋งค ํ‚ค์ž…๋ ฅ ์‹œ) ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
์‹ค์‹œ๊ฐ„ ๊ฒ€์‚ฌ ๊ฐ€๋Šฅ (๊ธ€์ž ์ˆ˜ ์ œํ•œ, ์ž…๋ ฅ ์ฆ‰์‹œ ๊ฒฝ๊ณ  ๋“ฑ) ๋ถˆ๊ฐ€๋Šฅ (๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์‹œ์ ์—๋งŒ ํ™•์ธ ๊ฐ€๋Šฅ)
UI ๋™๊ธฐํ™” ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ UI๊ฐ€ ์ฆ‰์‹œ ๋ณ€ํ•จ ์ €์žฅ ์ „๊นŒ์ง€ UI ๋ณ€ํ™” ์—†์Œ
์ถ”์ฒœ ์ƒํ™ฉ ๋ณต์žกํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ์‹ค์‹œ๊ฐ„ ํ”ผ๋“œ๋ฐฑ ํ•„์š” ์‹œ ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘, ์„ฑ๋Šฅ ์ตœ์ ํ™” ํ•„์š” ์‹œ

1. useRef๋ฅผ ์ด์šฉํ•œ ์ž…๋ ฅ๊ฐ’ ์ˆ˜์ง‘

useState๋ฅผ ์“ฐ๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ useRef๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งŒ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

import { useRef } from 'react';

const title = useRef();
const description = useRef();
const dueDate = useRef();

function handleSave() {
  const enteredTitle = title.current.value;
  const enteredDescription = description.current.value;
  const enteredDueDate = dueDate.current.value;
  
  // ์ˆ˜์ง‘๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ
  onAdd({
    title: enteredTitle,
    description: enteredDescription,
    dueDate: enteredDueDate
  });
}

2. ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— Ref ์ „๋‹ฌํ•˜๊ธฐ (forwardRef)

๋‚ด์žฅ HTML ํƒœ๊ทธ(input, textarea)๊ฐ€ ์•„๋‹Œ ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— ref ์†์„ฑ์„ ๋„˜๊ธฐ๋ ค๋ฉด React์˜ forwardRef๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

import { forwardRef } from 'react';

const Input = forwardRef(function Input({ label, textarea, ...props }, ref) {
  return (
    <p>
      <label>{label}</label>
      {textarea ? (
        <textarea ref={ref} {...props} />
      ) : (
        <input ref={ref} {...props} />
      )}
    </p>
  );
});
  • forwardRef๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ref๋ฅผ ์ „๋‹ฌ๋ฐ›์œผ๋ฉฐ, ์ด๋ฅผ ๋‚ด๋ถ€์˜ ์‹ค์ œ DOM ์š”์†Œ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ: App์—์„œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ

์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์ด๋“œ๋ฐ”์™€ ์ƒ์„ธ ํ™”๋ฉด ๋ชจ๋‘์—์„œ ํ•„์š”ํ•˜๋ฏ€๋กœ, ๊ฐ€์žฅ ๊ณตํ†ต ๋ถ„๋ชจ์ธ App ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

// App.jsx
function handleAddProject(projectData) {
  setProjectsState(prevState => {
    const newProject = {
      ...projectData,
      id: Math.random() // ๊ฐ„๋‹จํ•œ ID ์ƒ์„ฑ
    };

    return {
      ...prevState,
      projects: [...prevState.projects, newProject] // ๊ธฐ์กด ๋ฐฐ์—ด ๋ณต์‚ฌ ํ›„ ์ƒˆ ํ”„๋กœ์ ํŠธ ์ถ”๊ฐ€
    };
  });
}

// ...๋ Œ๋”๋ง ๋ถ€๋ถ„
<NewProject onAdd={handleAddProject} />

4. ์ž…๋ ฅ ํƒ€์ž… ์ตœ์ ํ™” (Date Picker)

์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ •ํ™•ํ•œ ๋‚ ์งœ ํ˜•์‹์„ ๋ฐ›๊ธฐ ์œ„ํ•ด input์˜ type ์†์„ฑ์„ ํ™œ์šฉํ•œ๋‹ค.

<Input type="text" ref={title} label="Title" />
<Input textarea ref={description} label="Description" />
<Input type="date" ref={dueDate} label="Due Date" />
  • type="date"๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ € ๋‚ด์žฅ ๋ฐ์ดํŠธ ํ”ผ์ปค(Date Picker)๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ํŽธ๋ฆฌํ•˜๊ฒŒ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’ก ์š”์•ฝ ๋ฐ ํ•ต์‹ฌ ํฌ์ธํŠธ

  1. Ref vs State: ์‹ค์‹œ๊ฐ„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ํ•„์š” ์—†๋‹ค๋ฉด useRef๊ฐ€ ๋ Œ๋”๋ง ์ตœ์ ํ™”์™€ ์ฝ”๋“œ ๊ฐ„๊ฒฐ์„ฑ ๋ฉด์—์„œ ์œ ๋ฆฌํ•˜๋‹ค.
  2. forwardRef: ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ ์™ธ๋ถ€์—์„œ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก forwardRef๋ฅผ ์ ์šฉํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด์ž.
  3. ๋ถˆ๋ณ€์„ฑ ์œ ์ง€: ์ƒํƒœ ๋ฐฐ์—ด์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋Š” [...prevState.projects, newProject]์™€ ๊ฐ™์ด ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์•ผ ํ•œ๋‹ค.

5. ๋ฐ๋ชจ

๋ฐ๋ชจ

๋‹ค์Œ ๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ ์ €์žฅ ๋กœ์ง์€ ์™„์„ฑ๋˜์—ˆ๋‹ค. ๋‹ค์Œ์—๋Š” ์ž…๋ ฅ๊ฐ’์ด ๋น„์–ด์žˆ์„ ๋•Œ ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ๋Š” **์œ ํšจ์„ฑ ๊ฒ€์‚ฌ(Validation)**์™€ ๋ชจ๋‹ฌ(Modal) ์ฐฝ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

์ตœ์šฐ์ง„ ํ”„๋กœํ•„

Woojin

๊ตฌ์กฐ์ ์œผ๋กœ ์‚ฌ๊ณ ํ•˜๊ณ , ๊ทผ๊ฑฐ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.