useRef()

1. ๊ฐœ์š”

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์„ ์‚ฌ์šฉํ•  ๋•Œ ํŠน์ • DOM์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” getElementById, querySelector์™€ ๊ฐ™์€ DOM Selector ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋ฆฌ์•กํŠธ์—์„œ๋Š” ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๋ฐ”๋กœ useRef()ํ›…์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.


2. useRef() ๋กœ ํŠน์ • DOM ์„ ํƒํ•˜๊ธฐ

๋จผ์ € useRef()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • DOM์„ ์„ ํƒํ•˜์ž. ์šฐ์„ ์ ์œผ๋กœ ํ•  ์ผ์€ useRef()๋ฅผ ๋ฆฌ์•กํŠธ์—์„œ ์ž„ํฌํŠธํ•œ ํ›„ Ref ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์ผ์ด๋‹ค. ๊ทธ ํ›„ Ref ๊ฐ์ฒด๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•˜๊ณ  ์‹ถ์€ DOM์— ref๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ํ•จ๊ป˜ ๋ณด์ž.

import React, { useRef } from "react";

const Test = () => {
  const nameRef = useRef();
  const emailRef = useRef();

  console.log(nameRef, emailRef);

  return (
    <div>
      <div>
        <input ref={nameRef} type="text" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”." />
        <button>name focus</button>
      </div>
      <div>
        <input ref={emailRef} type="text" placeholder="์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”." />
        <button>email focus</button>
      </div>
    </div>
  );
};

export default Test;

useRef()๋ฅผ ํ†ตํ•ด ๋‘๊ฐœ์˜ Ref ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ํ•˜๋‚˜๋Š” nameRef์ด๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” emailRef์ด๋‹ค. ๊ทธ ํ›„ ๊ฐ๊ฐ input์˜ ref ๊ฐ’์œผ๋กœ ์„ค์ •ํ–ˆ๋‹ค. ์ฝ˜์†”๋กœ ์–ด๋–ค ๋‚ด์šฉ์ด ์ฐํžˆ๋Š”์ง€ ๋ณด์ž.

Ref ๊ฐ์ฒด์˜ .current ๊ฐ’์€ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” DOM๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค.

์ข€ ๋” ๋‚˜์•„๊ฐ€ input์˜†์— ์œ„์น˜ํ•œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๊ฐ๊ฐ์˜ input์— focus๋ฅผ ์ฃผ๋„๋ก ํ•ด๋ณด์ž. ๊ทธ๋ ‡๋‹ค๋ฉด ์•„๋ž˜์˜ ์ถ”๊ฐ€์ ์ธ ์ฝ”๋“œ(๋ฒ„ํŠผ์˜ onClick) ์ž‘์„ฑ์ด ํ•„์š”ํ•˜๋‹ค.

import React, { useRef } from "react";

const Test = () => {
  const nameRef = useRef();
  const emailRef = useRef();

  // ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ํ•ด๋‹น input์— ํฌ์ปค์Šค๋ฅผ ์ฃผ๋Š” ํ•จ์ˆ˜
  const onClickBtn = (ref) => {
    if (ref === "name") {
      nameRef.current.focus();
    } else {
      emailRef.current.focus();
    }
  };

  return (
    <div>
      <div>
        <input ref={nameRef} type="text" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”." />
        <button onClick={() => onClickBtn("name")}>name focus</button>
      </div>
      <div>
        <input ref={emailRef} type="text" placeholder="์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”." />
        <button onClick={() => onClickBtn("email")}>email focus</button>
      </div>
    </div>
  );
};

export default Test;

.current.focus()์„ ํ†ตํ•ด input์— focus๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ํด๋ฆญ์„ ํ†ตํ•ด ํ™•์ธํ•ด ๋ณด๋ฉด ์•„๋ž˜์˜ ์‚ฌ์ง„๊ณผ ๊ฐ™๋‹ค. ์•„๋ž˜๋Š” email focus ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์˜ ๋ชจ์Šต์ด๋‹ค.


3. useRef() ๋กœ ๋ณ€์ˆ˜ ๊ด€๋ฆฌํ•˜๊ธฐ

useRef()๋Š” DOM๋ฅผ ์„ ํƒํ•˜๋Š” ์šฉ๋„ ์™ธ์—๋„, ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์กฐํšŒ ๋ฐ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” useState()๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜(๋ฐ์ดํ„ฐ)๊ฐ€ ๋ณ€ํ•  ๋•Œ ๋งˆ๋‹ค ๋ฆฌ๋žœ๋”๋ง์„ ํ•˜๊ฒŒ ๋˜๋ฉด์„œ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ ๋ณ€์ˆ˜๋“ค์ด ์ดˆ๊ธฐํ™”๋œ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ดํ•ดํ•ด๋ณด์ž.

import React, { useState } from "react";

const Test = () => {
  var number = 0;
  const [render, setRender] = useState(true);

  const onClickPlusBtn = () => {
    number += 1;
    console.log(`number์˜ ๊ฐ’์ด ${number}๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`);
  };

  const onClickRender = () => {
    setRender((prev) => !prev);
  };

  console.log(`์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋ง ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. number์˜ ๊ฐ’์€ ${number}์ž…๋‹ˆ๋‹ค.`);

  return (
    <div>
      <div>
        <span>Number: {number}</span>
        <button onClick={onClickPlusBtn}>+</button>
      </div>
      <button onClick={onClickRender}>๋žœ๋”๋ง</button>
    </div>
  );
};

export default Test;

๋ณ€์ˆ˜ number๋Š” var๋ฅผ ํ†ตํ•ด ์„ ์–ธ์ด ๋˜์—ˆ๊ณ  ์•„๋ฌด๋ฆฌ +๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ๋‹ค ํ•ด๋„ ํ™”๋ฉด์ด ๋‹ค์‹œ ๋žœ๋”๋ง์ด ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ์ฝ˜์†”์„ ์ฐ์—ˆ์„ ๋•Œ ์ฝ”๋“œ ๋‚ด๋ถ€์—์„œ๋Š” ์ˆซ์ž๊ฐ€ ํ•˜๋‚˜์”ฉ ์˜ค๋ฅด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๊ทธ ์•„๋ž˜์˜ ๋žœ๋”๋ง ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋• ์–ด๋–จ๊นŒ? number์˜ ๊ฐ’์ด ์ดˆ๊ธฐํ™” ๋˜์–ด ๋‹ค์‹œ 0์ด ๋œ๋‹ค.

์ด๋ฒˆ์—๋Š” var๊ฐ€ ์•„๋‹Œ useRef()๋ฅผ ํ†ตํ•ด ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•ด๋ณด์ž. ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ž.

import React, { useState, useRef } from "react";

const Test = () => {
  const number = useRef(0);
  const [render, setRender] = useState(true);

  const onClickPlusBtn = () => {
    number.current += 1;
    console.log(`number์˜ ๊ฐ’์ด ${number.current}๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`);
  };

  const onClickRender = () => {
    setRender((prev) => !prev);
  };

  console.log(
    `์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋ง ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. number์˜ ๊ฐ’์€ ${number.current}์ž…๋‹ˆ๋‹ค.`
  );

  return (
    <div>
      <div>
        <span>Number: {number.current}</span>
        <button onClick={onClickPlusBtn}>+</button>
      </div>
      <button onClick={onClickRender}>๋žœ๋”๋ง</button>
    </div>
  );
};

export default Test;

์œ„์™€ ๊ฐ™์ด var๋กœ ์„ ์–ธํ•œ number๋ฅผ useRef()๋กœ ๋ฐ”๊พธ์—ˆ๊ณ  useRef()์˜ ()์•ˆ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ 0์„ ๋„ฃ์–ด ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•˜์˜€๋‹ค. ๊ทธ๋ฆฌ๊ณ  number.current๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์กฐํšŒํ•œ๋‹ค. ๋˜ํ•œ +๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค number.current์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•˜์—ฌ 1์”ฉ ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๊ฒŒ ํ•˜์˜€๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์˜ ์‚ฌ์ง„๊ณผ ๊ฐ™๋‹ค.

์ด์ „ var๋กœ ์„ ์–ธํ–ˆ์„ ๋•Œ ์ฒ˜๋Ÿผ +๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋• number๊ฐ’์ด 1์”ฉ ์ฆ๊ฐ€ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง ๋˜์—ˆ์„ ๋• ์ด์ „๊ณผ ๋‹ค๋ฅด๊ฒŒ number๊ฐ’์ด 0์œผ๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์•Œ ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜์˜ ์‚ฌ์‹ค์€ useRef()๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜์˜ ๊ฐ’์ด ๋ณ€ํ•˜๋”๋ผ๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์œ„์˜ ์‚ฌ์ง„์—์„œ๋Š” Number: 8์ด๋ผ๊ณ  ๋˜์–ด์žˆ์ง€๋งŒ ์ด๋Š” ๋žœ๋”๋ง ๋ฒ„ํŠผ์œผ๋กœ ์ธํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง์ด ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๊ณ  ๊ทธ ์ „๊นŒ์ง€๋Š” ์ˆ˜์ •๋œ number์˜ ๊ฐ’์„ ํ™”๋ฉด์—์„œ๋Š” ๋ณผ ์ˆ˜ ์—†๋‹ค. ์•„๋ž˜์˜ ์‚ฌ์ง„์„ ์ฐธ๊ณ ํ•˜๋ผ!


4. Conclusion

useRef()๋ฅผ ํ†ตํ•ด DOM์— ์ง์ ‘ ์ ‘๊ทผํ•˜๊ณ  ์ž‘์—…ํ•˜๋Š” ๊ณผ์ •์€ ํŠนํžˆ input๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ๋ช‡ ๋ฒˆ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ useRef()๋ฅผ ํ†ตํ•ด ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ํ•œ ๋ฒˆ๋„ ํ•ด๋ณด์ง€ ๋ชปํ•˜์˜€๋‹ค. var๋กœ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ์˜ ์ฐจ์ด๋Š” ์ดํ•ด๊ฐ€ ๋˜์ง€๋งŒ ์–ด๋–ค ๊ธฐ๋Šฅ์—์„œ useRef()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋Š” ์•„์ง ์˜๋ฌธ์ด๋‹ค. ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ์™€ useRef()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์žฅ์ ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค.(์ดํ›„ ๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ ํ•ด๋‹น ๋‚ด์šฉ์ด ๋‚˜์˜ค๋ฉด useRef()์ฑ•ํ„ฐ์— ์ •๋ฆฌ๋ฅผ ํ•ด์•ผ๊ฒ ๋‹ค.)


์ฐธ๊ณ 

ko.reactjs.org - useRef 10. useRef ๋กœ ํŠน์ • DOM ์„ ํƒํ•˜๊ธฐ [React] useRef ์‚ฌ์šฉ๋ฒ• ๋ฐ ์˜ˆ์ œ


๐Ÿ‘†

๐Ÿ“… 2022-08-01

Last updated