โ›“๏ธ

8. useRef

ย 

8.1 useRef๋ž€?

ย 
const ref = useRef(initialValue);
ย 
useRef์˜ ๊ธฐ๋ณธ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ useRef๋Š” ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” { current: initialValue } ์˜ ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ref.current ์˜ ํ˜•ํƒœ๋กœ ๊ฐ’์˜ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ useRef๋Š” .current ํ”„๋กœํผํ‹ฐ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” โ€œ์ƒ์žโ€์™€ ๊ฐ™๋‹ค๊ณ  ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

8.1.1 useRef์˜ ์‚ฌ์šฉ ๋ชฉ์ 

useRef๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€์˜ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ์ด ๋ฉ๋‹ˆ๋‹ค.
  1. ํŠน์ • DOM์— ์ ‘๊ทผํ•˜์—ฌ ์ œ์–ดํ•ด์•ผ ํ•  ๊ฒฝ์šฐ
  1. ๋ Œ๋”๋ง๊ณผ ๊ด€๊ณ„์—†์ด ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ
ย 
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฒฝ์šฐ, getElementById, querySelector ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ DOM์— ์ ‘๊ทผํ•˜์—ฌ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ React์˜ ๊ฒฝ์šฐ์—๋Š” ์ง์ ‘ DOM์„ ์กฐ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์Šคํฌ๋กค๋ฐ” ์œ„์น˜๋ฅผ ํŒŒ์•…ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ๋‚˜ input ์š”์†Œ์— ์ž๋™ ํฌ์ปค์Šค๋ฅผ ์„ค์ •ํ•ด ์ฃผ์–ด์•ผ ํ•  ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์ง์ ‘ DOM์„ ์ œ์–ดํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š” ์˜ˆ์™ธ์ ์ธ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋•Œ useRef๋ฅผ ์‚ฌ์šฉํ•ด DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๐Ÿ’ก
React์—์„œ DOM์˜ ์ง์ ‘ ์กฐ์ž‘์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š” ์ด์œ  React๋Š” Virtual DOM์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— DOM ์กฐ์ž‘์œผ๋กœ ์ธํ•œ ๋ธŒ๋ผ์šฐ์ € ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•œ๋‹ค๋Š” ์žฅ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ์ง์ ‘ DOM์„ ์กฐ์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด โ€œVirtual DOM์„ ์‚ฌ์šฉํ•œ ๋ธŒ๋ผ์šฐ์ € ๋ Œ๋”๋ง ์ตœ์†Œํ™”โ€ ๋ผ๋Š” React์˜ ์žฅ์ ์„ ๋†“์น˜๋Š” ์ผ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์ง์ ‘ DOM์„ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์„ ์ง€์–‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
ย 
๋˜ํ•œ useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ „ ์ƒ์• ์ฃผ๊ธฐ๋ฅผ ํ†ตํ•ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ์• ์ฃผ๊ธฐ๋ž€ DOM์— ๋งˆ์šดํŠธ๋˜๊ณ  ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ๊นŒ์ง€์˜ ๊ณผ์ •์„ ๋งํ•ฉ๋‹ˆ๋‹ค. useRef๋Š” .current ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ , ๋ Œ๋”๋ง์„ ํ•  ๋•Œ ๋™์ผํ•œ ref ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ„์†ํ•ด์„œ ๋ Œ๋”๋ง ๋˜๋”๋ผ๋„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ ์ „๊นŒ์ง€ ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปดํฌ๋„ŒํŠธ ๊ฐ’์˜ ๋ณ€๊ฒฝ์€ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜์ง€๋งŒ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚ฌ ํ•„์š”๋Š” ์—†์„ ๋•Œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

8.2 useRef vs useState vs ์ผ๋ฐ˜๋ณ€์ˆ˜

ย 

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

ย 
useState ์™€ useRef ๋Š” ๋ชจ๋‘ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ useState ์˜ ๊ฒฝ์šฐ state ๊ฐ€ ๋ณ€๊ฒฝ๋œ ํ›„์— ๋ฆฌ๋ Œ๋”๋ง์„ ์ง„ํ–‰ํ•˜๋Š” ๋ฐ˜๋ฉด, useRef ๋Š” ๋ฆฌ๋ Œ๋”๋ง์„ ์ง„ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. useRef ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๊ฐ’์ด ๋ณ€ํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋ณด์ด์ง€ ์•Š๋‹ค๊ฐ€ ๋ Œ๋”๋ง์ด ๋˜๋Š” ์‹œ์ ์— ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋ณด์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠน์„ฑ์— ๋งž์ถ”์–ด ๋ Œ๋”๋ง์ด ํ•„์š”ํ•œ state ์˜ ๊ฒฝ์šฐ์—๋Š” useState ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์šฉ๋„์™€ ์ƒ์•  ์ฃผ๊ธฐ ๋‚ด๋‚ด ๋ณ€ํ™”ํ•˜๋Š” ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค๋Š” ์ฐจ๋ณ„์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์ฆ‰, useState ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ์•  ์ฃผ๊ธฐ์™€ ๋ฐ€์ ‘ํ•œ ์—ฐ๊ด€์ด ์žˆ๋Š” ์š”์†Œ์ด๋ฏ€๋กœ ๋ Œ๋”๋ง๊ณผ ๊ด€๋ จ์ด ์—†๋Š” ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์œผ๋ฉฐ, useRef ๋Š” state ๋ Œ๋”๋ง๊ณผ ๋ฌด๊ด€ํ•œ ๊ฐ’๊ณผ ์ด์ „์˜ ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ์— ์ ํ•ฉํ•˜๋‹ค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ๊ฐ์˜ ์ƒํ™ฉ์— ๋งž๊ฒŒ Hook์„ ์ž˜ ์‚ฌ์šฉํ•ด์•ผ ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 

8.2.2 useRef ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

ย 
์•„๋ž˜ ์˜ˆ์ œ๋Š” ๊ฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค +1 ์”ฉ ์นด์šดํŠธ๊ฐ€ ๋˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ์ด์œ ๋กœ useRef ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ํ•จ๊ป˜ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 
import { useRef, useState } from "react"; import "./styles.css"; export default function App() { const [stateCount, setStateCount] = useState(0); const refCount = useRef(0); return ( <div className="App"> <button onClick={() => { setStateCount((prev) => prev + 1); }} > State ๋ฒ„ํŠผ </button> <button onClick={() => { refCount.current += 1; }} > Ref ๋ฒ„ํŠผ </button> <br /> <br /> <div>useState Count: {stateCount}</div> <div>useRef Count: {refCount.current}</div> </div> ); }
App.jsx
ย 
State ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด useState Count ๊ฐ’์ด 1์ด ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Ref ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด useRef Count ๋Š” ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง๋กœ useRef Count ๊ฐ’์€ ์นด์šดํŠธ๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ผ๊นŒ์š”? ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์นด์šดํŠธ๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ณ  ์žˆ์ง€๋งŒ ํ™”๋ฉด์— ๋ฐ”๋กœ ๋ Œ๋”๋ง์ด ๋˜์ง€ ์•Š์„ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ ๋ฒˆ State ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋ฆฌ๋ Œ๋”๋ง์„ ์‹œํ‚ค๊ฒŒ ๋˜๋ฉด useRef Count ๊ฐ’๋„ ์˜ฌ๋ผ๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. state ๊ฐ€ ๋ณ€ํ™”๋์„ ๋•Œ, refCount.current ์˜ ๊ฐ’๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ™”๋ฉด์— ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์œ ๋Š” useRef ๋กœ ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” useRef ๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋Š” component ์˜ ์ƒ์• ์ฃผ๊ธฐ ๋‚ด๋‚ด ๋ณ€ํ™”ํ•˜๋Š” ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— current ๊ฐ’์ด ๋ณ€ํ™”ํ•ด๋„ ๋ฆฌ๋ Œ๋”๋ง์— ๊ด€์—ฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์— ์žˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

8.3 useRef์™€ DOM

์•ž์„œ ์‚ดํŽด๋ณธ useRef๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  ์ค‘์—๋Š” ํŠน์ • DOM์— ์ ‘๊ทผํ•˜์—ฌ ์ œ์–ดํ•ด์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
React์—์„œ DOM์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ref๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ, ref๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” useRef๋ผ๋Š” React์˜ Hook์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด DOM์„ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…์‹œ๋‹ค.

8.3.1 useRef๋กœ ํŠน์ •ํ•œ DOM ์„ ํƒ

import React, { useRef } from "react"; function App() { const textInput = useRef(null); // --- โ“ต useRef ์ƒ์„ฑ const ClickBtn = () => { console.log("Click!"); }; const handleClickBtn = () => { textInput.current.focus(); // --- โ“ท useRef๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” input ํƒœ๊ทธ์— ํฌ์ปค์Šค ์ด๋ฒคํŠธ ์ ์šฉ }; return ( <div> <input type="text" /> <input type="button" value="ref X" onClick={ClickBtn} /> <br /> <input type="text" ref={textInput} /> // --- โ“ถ ref props๋กœ ์ „๋‹ฌ <input type="button" value="ref O" onClick={handleClickBtn} /> </div> ); }; export default App;
App.js
ย 
์œ„ ์ฝ”๋“œ๋Š” useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ input์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ ์˜ˆ์ œ์™€ ๊ทธ๋ ‡์ง€ ์•Š์€ ์˜ˆ์ œ๋ฅผ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 8-1 ref๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ input๊ทธ๋ฆผ 8-1 ref๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ input
๊ทธ๋ฆผ 8-1 ref๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ input
ย 
๋จผ์ €, ์ฒซ ๋ฒˆ์งธ input์€ onClick ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ์ฝ˜์†”๋งŒ ์ฐํž ๋ฟ ๋‹ค๋ฅธ ๋ณ€ํ™”๋Š” ์ƒ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‘ ๋ฒˆ์งธ input์€ onClick ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ input ํƒœ๊ทธ์— ํฌ์ปค์Šค๊ฐ€ ์ ์šฉ๋˜๋Š”๋ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ๋ฆ„์œผ๋กœ ์ ์šฉ์ด ๋ฉ๋‹ˆ๋‹ค.
ย 
import React, { useRef } from "react"; const textInput = useRef(null); // --- โ“ต useRef ์ƒ์„ฑ <input type="text" ref={textInput} /> // --- โ“ถ ref props๋กœ ์ „๋‹ฌ <input type="button" value="ref O" onClick={handleClickBtn} />
ย 
useRef๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด react ๋ชจ๋“ˆ์—์„œ useRef๋ฅผ import ํ•ด์˜จ ํ›„, text input์— ๋Œ€ํ•œ useRef๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ’์„ ๋ฐ›์•„์˜ค๊ณ  ์‹ถ์€ input ํƒœ๊ทธ์— ref props๋กœ ์ „๋‹ฌํ•ด์ค๋‹ˆ๋‹ค.
ย 
const handleClickBtn = () => { textInput.current.focus(); // --- โ“ท useRef๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” input ํƒœ๊ทธ์— ํฌ์ปค์Šค ์ด๋ฒคํŠธ ์ ์šฉ };
ย 
๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ, handleClickBtn ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๊ณ  textInput.current.focus๋ฅผ ํ†ตํ•ด input ํƒœ๊ทธ์— ํฌ์ปค์Šค๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 8-2 ref๋ฅผ ์‚ฌ์šฉํ•œ input๊ทธ๋ฆผ 8-2 ref๋ฅผ ์‚ฌ์šฉํ•œ input
๊ทธ๋ฆผ 8-2 ref๋ฅผ ์‚ฌ์šฉํ•œ input
ย 
ย 
๊ทธ๋Ÿฌ๋ฉด ์œ„์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋กœ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ input ํƒœ๊ทธ์— ํฌ์ปค์Šค๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

8.3.2 useRef๋กœ DOM ์„ ํƒ ํ›„ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ ์‚ฌํ•ญ

useRef๋ฅผ ์ด์šฉํ•˜์—ฌ ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„ ํƒํ•˜๊ณ ์ž ํ•˜๋Š” ํƒœ๊ทธ์— ref props๋ฅผ ์ „๋‹ฌํ•˜๋ฉด, ๊ทธ๋•Œ๋ถ€ํ„ฐ๋Š” ํ•ด๋‹น ํƒœ๊ทธ๊ฐ€ ์„ ํƒ๋˜์–ด ๋‹ค์–‘ํ•˜๊ฒŒ ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์Œ์„ input ํƒœ๊ทธ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด DOM์„ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š๋ƒ์— ๋”ฐ๋ผ ์›ํ•˜๋Š” ๊ฐ’์ด ๋‚˜์˜ค๊ธฐ๋„ ํ•˜๊ณ  null์ด๋‚˜ undefined ๊ฐ’์ด ๋‚˜์˜ค๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ •ํ™•ํžˆ ์–ธ์ œ ๊ทธ๋Ÿฐ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€, ์›ํ•˜๋Š” ๋ฐ”์™€ ๋‹ค๋ฅธ ๊ฒฐ๊ด๊ฐ’์ด ๋‚˜์˜ค์ง€ ์•Š๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ• ์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 
import React, { useRef } from "react"; import music from "./assets/music.mp3"; function Player() { const audioRef = useRef(null); audioRef.current.play(); console.log(audioRef.current); const handlePlay = () => { audioRef.current.play(); console.log("๐ŸŽต์žฌ์ƒ๐ŸŽต"); }; const handlePause = () => { audioRef.current.pause(); console.log("โธ์ค‘์ง€!"); }; return ( <> <audio src={music} ref={audioRef} controls></audio> <br /> <div style={{ margin: "10px 89px" }}> <button onClick={handlePlay}> ๐ŸŽต ์žฌ์ƒ </button> <button onClick={handlePause}> โธ ์ค‘์ง€ </button> </div> </> ); } export default Player;
Player.js
๊ทธ๋ฆผ 8-3๊ทธ๋ฆผ 8-3
๊ทธ๋ฆผ 8-3
ย 
์œ„์˜ ์ฝ”๋“œ๋Š” ์žฌ์ƒ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์˜ค๋””์˜ค๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์ค‘์ง€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์˜ค๋””์˜ค๊ฐ€ ์ค‘์ง€๋˜๋Š” ํ”Œ๋ ˆ์ด์–ด ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด audio์— ๋Œ€ํ•œ useRef๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ”๋กœ ref.current์˜ ํ˜•ํƒœ๋กœ ์˜ค๋””์˜ค์— ์ ‘๊ทผํ•ด ๋ด…์‹œ๋‹ค.
ย 
const audioRef = useRef(null); audioRef.current.play(); console.log(audioRef.current); ... return ( <audio src={music} ref={audioRef} controls></audio> );
ย 
๊ทธ๋ฆผ 8-4๊ทธ๋ฆผ 8-4
๊ทธ๋ฆผ 8-4
ย 
๊ฐ’์ด ์ •์˜๋˜์ง€ ์•Š์•„ ์—๋Ÿฌ๊ฐ€ ๋‚˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ ๊ทธ๋Ÿฐ ๊ฑธ๊นŒ์š”? ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” React์˜ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ๊ณผ์ •์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
React์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ตœ์ดˆ ๋ Œ๋”๋ง ๋˜์—ˆ์„ ๋•Œ๋ฅผ ์ผ๋ถ€ ์š”์•ฝํ•˜์—ฌ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  1. ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  1. props, state ๋“ฑ์˜ ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. (์ตœ์ดˆ ๋งˆ์šดํŠธ ์‹œ 1๋ฒˆ๋งŒ ์‹คํ–‰)
  1. React DOM์„ ๋ Œ๋”๋งํ•œ๋‹ค. (return ์‹คํ–‰)
  1. ๊ธฐ์กด์˜ DOM์— ๋ฐ˜์˜ํ•œ๋‹ค.
ย 
ํ”Œ๋ ˆ์ด์–ด ์˜ˆ์ œ์—์„œ๋Š” ์•„์ง React DOM์„ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์•˜๊ณ , ๊ธฐ์กด DOM์— ๋ฐ˜์˜๋˜์ง€ ์•Š์€ ์ฑ„๋กœ ref.current์˜ ํ˜•ํƒœ๋กœ ์ฐธ์กฐ๋ฅผ ํ•˜๋ ค๊ณ  ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ย 
์ด๋Ÿฌํ•œ ํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” React DOM์„ ๋ Œ๋”๋งํ•˜๊ณ  ๊ธฐ์กด์˜ DOM์— ๋ฐ˜์˜๋˜๊ณ  ๋‚œ ํ›„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ†ตํ•ด ref.current๊ฐ€ ์กด์žฌํ•  ๋•Œ์—๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
ย 
import React, { useEffect, useRef } from "react"; import music from "./assets/music.mp3"; function Player() { const audioRef = useRef(null); useEffect(() => { audioRef.current && audioRef.current.play(); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•œ ํ›„ ์‚ฌ์šฉ }); const handlePlay = () => { audioRef.current.play(); console.log("๐ŸŽต์žฌ์ƒ๐ŸŽต"); }; const handlePause = () => { audioRef.current.pause(); console.log("โธ์ค‘์ง€!"); }; return ( <> <audio src={music} ref={audioRef} controls></audio> <br /> <div style={{ margin: "10px 89px" }}> <button onClick={handlePlay}> ๐ŸŽต ์žฌ์ƒ </button> <button onClick={handlePause}> โธ ์ค‘์ง€ </button> </div> </> ); } export default Player;
Player.js ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•œ ์ตœ์ข… ์ฝ”๋“œ
ย 
๐Ÿ’ก
audio ์š”์†Œ์˜ controls ์†์„ฑ ์žฌ์ƒ, ์ •์ง€, ๋ณผ๋ฅจ ์กฐ์ ˆ๊ณผ ๊ฐ™์€ ์˜ค๋””์˜ค ๊ธฐ๋ณธ์ ์ธ ์ปจํŠธ๋กค๋Ÿฌ ํ‘œ์‹œ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ์ž…๋‹ˆ๋‹ค.
ย 

8.4 (์‹ค์Šต) useRef ์‘์šฉํ•ด๋ณด๊ธฐ

ย 

8.4.1 useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ focus ๊ด€๋ฆฌํ•˜๊ธฐ

ย 
์ด๋ฒˆ ํŒŒํŠธ์—์„œ๋Š” useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • input ์š”์†Œ๋ฅผ focus ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์•„๋ž˜ ์˜ˆ์ œ๋“ค์€ ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ž…๋ ฅํ•˜์ง€ ์•Š์€ input ์š”์†Œ๋กœ ๋ฐ”๋กœ focus๋˜์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๋ฝ๋œ input ์š”์†Œ ์—†์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.
ย 
import React from "react"; function App() { return ( <form style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "10px", }} > <h2>ํ”„๋กœํ•„ ์„ค์ •</h2> <label> ์ด๋ฉ”์ผ: <input type="email"></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ: <input type="password"></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ: <input type="password"></input> </label> <label> ์ด๋ฆ„: <input type="text"></input> </label> <label> ๋‹‰๋„ค์ž„: <input type="text"></input> </label> <button type="submit" style={{ width: "180px" }}> ํšŒ์›๊ฐ€์ž…ํ•˜๊ธฐ </button> </form> ); } export default App;
App.js ๊ธฐ๋ณธ ํ˜•ํƒœ
ย 
form์—์„œ onsubmit ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, input์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์œ„์˜ ์ฝ”๋“œ๋งŒ์œผ๋กœ๋Š” input์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์•„์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด useRef๋ฅผ ์ด์šฉํ•˜์—ฌ input์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ inputRef๋Š” ์ƒˆ๋กœ์šด input ์š”์†Œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด๋„ ๋ฐฐ์—ด๋กœ์จ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ธฐ๋ณธ๊ฐ’์„ ๋นˆ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
ย 
import React, { useRef } from "react";
App.js useRef ์ถ”๊ฐ€ํ•˜๊ธฐ
ย 
const inputRef = useRef([]);
App.js useRef ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด ๋ฐฐ์—ด ์ƒ์„ฑ
ย 
React์—์„œ๋Š” ref๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํŠน์ • DOM ์š”์†Œ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์ž…๋ ฅ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ref๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ input ์š”์†Œ์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์•„ ์•„๋ž˜์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ inputRef๋กœ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค.
์•„๋ž˜ ์˜ˆ์ œ๋“ค์€ ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์–ด๋– ํ•œ ๊ฐ’๋„ ์ž…๋ ฅ์„ ํ•˜์ง€ ์•Š์€ input ์š”์†Œ๋กœ ๋ฐ”๋กœ focus๋˜์–ด, ๋ˆ„๋ฝ๋œ input ์š”์†Œ ์—†์ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.์„ค์ •ํ•œ ์ด๋ฆ„์œผ๋กœ ๋ณ€๋™๋˜๋Š” ๊ฐ์ฒด์˜ ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ input ์š”์†Œ์—์„œ ๋ณ€๋™๋˜๋Š” ๊ฐ’์„ ๋ฐ›๋Š” ๋ณ€์ˆ˜์ธ inputRef๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์ค๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์„œ, inputRef ๋Š” ๊ฐ๊ฐ์˜ input ์š”์†Œ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›๋Š” ๊ฐ’์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ["email"] ๋‚˜ ["pw"] ์™€ ๊ฐ™์ด ๊ด„ํ˜ธ ํ‘œ๊ธฐ๋ฒ•(bracket notation) ํ˜•ํƒœ๋กœ ๊ณ ์œ ํ•œ ์ด๋ฆ„์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
ย 
// --- โ‘  ์ˆ˜์ • ์ „ ์ฝ”๋“œ ์˜ˆ์‹œ <label> ์ด๋ฉ”์ผ: <input type="email"></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ: <input type="password"></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ: <input type="password"></input> </label> <label> ์ด๋ฆ„: <input type="text"></input> </label> <label> ๋‹‰๋„ค์ž„: <input type="text"></input> </label> // --- โ‘ก ์ˆ˜์ • ํ›„ ์ฝ”๋“œ ์˜ˆ์‹œ <label> ์ด๋ฉ”์ผ: <input type="email" ref={(el)=>(inputRef.current["email"]=el)}></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ: <input type="password" ref={(el)=>(inputRef.current["pw"]=el)}></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ: <input type="password" ref={(el)=>(inputRef.current["pwcheck"]=el)} ></input> </label> <label> ์ด๋ฆ„:{" "} <input type="text" ref={(el)=>(inputRef.current["name"]=el)}></input> </label> <label> ๋‹‰๋„ค์ž„: <input type="text" ref={(el)=>(inputRef.current["nickname"]=el)}></input> </label>
App.js์—์„œ ref ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€
ย 
์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด, ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด inputRef์˜ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 
console.log(inputRef);
App.js์—์„œ inputRef ์ถœ๋ ฅ
ย 
๊ทธ๋ฆผ 8-5์ฒ˜๋Ÿผ inputRef ์•ˆ์—๋Š” current๋ผ๋Š” ์—ฐ๊ด€๋ฐฐ์—ด์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์œ„์—์„œ ์ž…๋ ฅํ•œ ๊ด„ํ˜ธ ํ‘œ๊ธฐ๋ฒ•์œผ๋กœ input ๊ฐ’์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 8-5 App.js inputRef ์ถœ๋ ฅ๊ฒฐ๊ณผ๊ทธ๋ฆผ 8-5 App.js inputRef ์ถœ๋ ฅ๊ฒฐ๊ณผ
๊ทธ๋ฆผ 8-5 App.js inputRef ์ถœ๋ ฅ๊ฒฐ๊ณผ
ย 
๐Ÿ’ก
์—ฌ๊ธฐ์„œ ์—ฐ๊ด€๋ฐฐ์—ด์ด๋ž€ ๋ฐฐ์—ด์„ ํ‚ค(key)์™€ ๊ฐ’(value)์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
ย 
๋งˆ์ง€๋ง‰์œผ๋กœ ์ œ์ถœ์–‘์‹์— ๋”ฐ๋ผ ๊ฐ’์„ ์ž…๋ ฅํ•˜๊ณ ์„œ ํšŒ์›๊ฐ€์ž…ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ์ œ์ถœํ–ˆ์„ ๋•Œ, input ์š”์†Œ์˜ ์ž…๋ ฅ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ๋‹ค๋ฉด, ํ•ด๋‹น input ์š”์†Œ์— focus๊ฐ€ ๋˜๋Š” inputCheck ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
ย 
const inputCheck = (e) => { e.preventDefault(); if (inputRef.current["email"].value === "") { console.log("์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["email"].focus(); return; } else if (inputRef.current["pw"].value === "") { console.log("๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["pw"].focus(); return; } else if (inputRef.current["pwcheck"].value === "") { console.log("๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["pwcheck"].focus(); return; } else if (inputRef.current["name"].value === "") { console.log("์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["name"].focus(); return; } else if (inputRef.current["nickname"].value === "") { console.log("๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["nickname"].focus(); return; } };
App.js inputCheck ํ•จ์ˆ˜ ์ƒ์„ฑ
ย 
๊ทธ๋ฆฌ๊ณ  form์—์„œ onsubmit ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ, inputCheck ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ์•„๋ž˜์˜ ์ฝ”๋“œ๋กœ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
ย 
<form style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "10px", }} onSubmit={inputCheck} >
App.js form ์š”์†Œ ์ˆ˜์ •
ย 
๊ทธ๋ฆผ 8-6์€ ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ทธ๋ฆฌ๊ณ  ์ด๋ฆ„์ด ์ž…๋ ฅ๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ๊ณผ ๋‹‰๋„ค์ž„์€ ์ž‘์„ฑํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋•Œ ํšŒ์›๊ฐ€์ž…ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด, ๊ทธ๋ฆผ 8-7์ฒ˜๋Ÿผ input ๊ฐ’์ด ๋น ์ง„ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ๊ณผ ๋‹‰๋„ค์ž„ ์ค‘ ์ฝ”๋“œ์—์„œ ๋จผ์ € ์„ ์–ธ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ์—์„œ focus๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 8- 6 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ์ „ ํ™”๋ฉด๊ทธ๋ฆผ 8- 6 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ์ „ ํ™”๋ฉด
๊ทธ๋ฆผ 8- 6 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ์ „ ํ™”๋ฉด
๊ทธ๋ฆผ 8- 7 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ํ›„ ํ™”๋ฉด๊ทธ๋ฆผ 8- 7 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ํ›„ ํ™”๋ฉด
๊ทธ๋ฆผ 8- 7 ํšŒ์›๊ฐ€์ž…๋ฒ„ํŠผ ํด๋ฆญ ํ›„ ํ™”๋ฉด
ย 
import React, { useRef } from "react"; function App() { const inputRef = useRef([]); const inputCheck = (e) => { e.preventDefault(); if (inputRef.current["email"].value === "") { console.log("์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["email"].focus(); return; } else if (inputRef.current["pw"].value === "") { console.log("๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["pw"].focus(); return; } else if (inputRef.current["pwcheck"].value === "") { console.log("๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["pwcheck"].focus(); return; } else if (inputRef.current["name"].value === "") { console.log("์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["name"].focus(); return; } else if (inputRef.current["nickname"].value === "") { console.log("๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"); inputRef.current["nickname"].focus(); return; } }; return ( <form style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "10px", }} onSubmit={inputCheck} > <h2>ํ”„๋กœํ•„ ์„ค์ •</h2> <label> ์ด๋ฉ”์ผ: <input type="email" ref={(el)=>(inputRef.current["email"]=el)}></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ: <input type="password" ref={(el)=>(inputRef.current["pw"]=el)}></input> </label> <label> ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ: <input type="password" ref={(el)=>(inputRef.current["pwcheck"]=el)} ></input> </label> <label> ์ด๋ฆ„:{" "} <input type="text" ref={(el)=>(inputRef.current["name"]=el)}></input> </label> <label> ๋‹‰๋„ค์ž„: <input type="text" ref={(el)=>(inputRef.current["nickname"]=el)}></input> </label> <button type="submit" style={{ width: "180px" }}>ํšŒ์›๊ฐ€์ž…ํ•˜๊ธฐ</button> </form> ); } export default App;
App.js ์™„์„ฑ์ฝ”๋“œ
ย