๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ—‚ WIL

cloneElement๋ฅผ ์“ฐ์ง€ ๋ชปํ•œ ์ด์œ 

by nalong 2025. 5. 4.

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

 

๋ฌผ๋ก  ๊ณตํ†ตํ™”๊ฐ€ ์–ธ์ œ๋‚˜ ์ •๋‹ต์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ๊ธ‰ํ•œ ์ผ์ • ์†์—์„œ ๊ฐœ๋ฐœํ•˜๊ฑฐ๋‚˜ ๊ธฐํš์ด 1์ฐจ, 2์ฐจ๋กœ ๋‚˜๋ˆ ์ง€๋Š” ๊ฒฝ์šฐ์—๋Š” ์„ฃ๋ถ€๋ฅธ ๊ณตํ†ตํ™”๋ณด๋‹ค๋Š” ์ตœ๋Œ€ํ•œ ์ž˜ ์ฝํžˆ๋Š” ์ฝ”๋“œ๋ฅผ ์šฐ์„ ์œผ๋กœ ๊ฐœ๋ฐœํ•œ ๋’ค, ๋‚˜์ค‘์— ํ˜ผ์ž ๋ฆฌํŒฉํ† ๋งํ•˜๋Š” ์‹์œผ๋กœ ์ ‘๊ทผํ–ˆ๋‹ค. 

 

์ด๋ฒˆ์— ๊ฐœ๋ฐœํ•œ ๊ธฐ๋Šฅ์€ ์ž…๋ ฅ์ฐฝ ์˜†์— ๋ฒ„ํŠผ์„ ๋ถ™์ด๊ณ , ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ…์ŠคํŠธ ์ธ์‹ ๊ฒฐ๊ณผ๋ฅผ ์ž…๋ ฅ ํ•„๋“œ์— ๋ฐ˜์˜ํ•˜๋Š” OCR ๊ธฐ๋Šฅ์ด์—ˆ๋Š”๋ฐ, ๊ณตํ†ตํ™”ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ๋ช…ํ™•ํ•˜๊ณ  ์ž‘์•˜๊ธฐ์— ์ฒ˜์Œ๋ถ€ํ„ฐ ์ตœ๋Œ€ํ•œ ๋‚ด๋ถ€์—์„œ ๋ชจ๋“  ์ •์ฑ…์„ ๊ฐ์‹ธ๋Š” ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ณ ์ž ํ–ˆ๋‹ค.

 

๊ธฐ๋Šฅ ์ž์ฒด๋Š” ๋‹จ์ˆœํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด๋“ค์„ ํ•จ๊ป˜ ๋งŒ์กฑํ•ด์•ผ ํ–ˆ๋‹ค.

  • ๋ฒ„ํŠผ์€ ์ž…๋ ฅ ํ•„๋“œ์— ํฌ์ปค์Šค ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋…ธ์ถœ๋˜์–ด์•ผ ํ•จ
  • ํด๋ฆญ ์‹œ ํŒ์˜ค๋ฒ„ ํ˜•ํƒœ์˜ UI๊ฐ€ ํ‘œ์‹œ๋˜๊ณ , ๊ทธ ์•ˆ์—๋Š” ์ •์ฑ… ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ์„ธ๋ถ€ ๋กœ์ง์ด ์กด์žฌํ•จ
  • ๋ฒ„ํŠผ ํด๋ฆญ ๊ฒฐ๊ณผ๋Š” ์™ธ๋ถ€๋กœ ์ฝœ๋ฐฑ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•จ
  • ๋งˆ์นจํ‘œ, ์ค„ ๋ฐ”๊ฟˆ ๋“ฑ์˜ ๊ธฐํ˜ธ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์ž…๋ ฅ ๋ณด์กฐ ๋ฒ„ํŠผ ํŒจ๋„์ด ํ•จ๊ป˜ ๋™์ž‘ํ•ด์•ผ ํ•จ

cloneElement ํ™œ์šฉํ•˜๊ธฐ

์ดˆ๊ธฐ์—๋Š” children์„ ๋ฐ›์•„ cloneElement๋กœ ๊ฐ์‹ธ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด ๋ณด์•˜๋Š”๋ฐ, ์‹ค์ œ๋กœ ์ ์šฉํ•ด ๋ณด๋‹ˆ ์—ฌ๋Ÿฌ ๋ฌธ์ œ๊ฐ€ ๋“œ๋Ÿฌ๋‚ฌ๋‹ค.

React.cloneElement(children, {
  onFocus: handleFocus,
  onBlur: handleBlur,
  ref: inputRef,
});

์‹ค์ œ๋กœ ๋ถ€๋”ชํžŒ ๋ฌธ์ œ๋“ค

  • ์ผ๋‹จ children์ด ๋‹จ์ผ ์š”์†Œ๋ผ๋Š” ๋ณด์žฅ์ด ์—†์—ˆ๋‹ค.
    • ์‹ค์ œ ๋ Œ๋”๋ง๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค ์ค‘ ์ผ๋ถ€๋Š” ์ž…๋ ฅ ์š”์†Œ๊ฐ€ ํ•˜๋‚˜๋กœ ๊ณ ์ •๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์กฐ๊ฑด ๋ถ„๊ธฐ๋ฅผ ํ†ตํ•ด ์„œ๋กœ ๋‹ค๋ฅธ input / textarea ๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š” ๊ตฌ์กฐ์˜€๋‹ค.
  • ์ด๋ฏธ ์™ธ๋ถ€์—์„œ onFocus, onBlur, ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์–ด ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•จ.

๊ฒฐ๊ตญ cloneElement๋Š” ๊ตฌ์กฐ๊ฐ€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋‹จ์ˆœํ•œ ์ƒํ™ฉ์—์„œ๋Š” ๊ดœ์ฐฎ์ง€๋งŒ, ์ง€๊ธˆ์ฒ˜๋Ÿผ ๋‹ค์–‘ํ•œ ๊ตฌ์กฐ์—์„œ๋Š” ์˜คํžˆ๋ ค ๋” ๋งŽ์€ ์ œ์•ฝ์„ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

๋‚ด๋ถ€ ํƒ์ƒ‰ ๋ฐฉ์‹

์™ธ๋ถ€ ๊ตฌ์กฐ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ž…๋ ฅ ํ•„๋“œ๋ฅผ ์ง์ ‘ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ–ˆ๋‹ค.

const inputElement =
  containerRef.current?.querySelector('input') ||
  containerRef.current?.querySelector('textarea');

 

containerRef๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‚ด๋ถ€์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด input ๋˜๋Š” textarea ์š”์†Œ๋ฅผ ํƒ์ƒ‰ํ•ด focus ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ๋ฒ„ํŠผ ๋…ธ์ถœ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

  • ์™ธ๋ถ€์—์„œ ref๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š์•„๋„ ๋จ
  • ๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ•ด์ ธ๋„ ๋‚ด๋ถ€์—์„œ ํƒ์ƒ‰ ๊ฐ€๋Šฅ
  • ํฌ์ปค์Šค ๊ฐ์ง€, ๋ Œ๋”๋ง ์กฐ๊ฑด, ๋ฒ„ํŠผ ์œ„์น˜ ๋“ฑ ๋ชจ๋“  ํŒ๋‹จ์„ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ

์ž…๋ ฅ ๋ณด์กฐ ํŒจ๋„ ์—ญ์‹œ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. ref๋ฅผ ๋„˜๊ฒจ๋ฐ›๋Š” ๋Œ€์‹ , ๋™์ผํ•˜๊ฒŒ containerRef.current?. querySelector(...)๋ฅผ ์‚ฌ์šฉํ•ด ์ž…๋ ฅ ํ•„๋“œ๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ , ํŠน์ • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋‚ด๋ถ€์—์„œ ์ž…๋ ฅ ๊ฐ’์„ ์กฐ์ž‘ํ•˜๊ณ  ์ด๋ฒคํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

<EditorFieldWrapper>
  <input type="text" />
</EditorFieldWrapper>