Unit3 - [React] Custom Component

์˜ˆ์ง„ยท2022๋…„ 10์›” 31์ผ
0

๐Ÿ”ฅ Component Driven Development

1. CDD

: ๋ถ€ํ’ˆ ๋‹จ์œ„๋กœ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋‚˜๊ฐ€๋Š” ๊ฐœ๋ฐœ ๋ฐฉ๋ฒ•
( ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋Š” UI ์ปดํฌ๋„ŒํŠธ์˜ ํ•„์š”์„ฑ์œผ๋กœ ์ธํ•ด ๋งŒ๋“ค์–ด์กŒ๋‹ค. )

+ CDD ๋ฐฉ๋ฒ•์„ ํ™œ์šฉํ•˜์—ฌ UI๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ์‚ฌ์ดํŠธ : BBC , UN

2. CSS in JS

๊ตฌ์กฐํ™”๋œ CSS๊ฐ€ ํ•„์š”ํ•˜๊ฒŒ ๋œ ์ด์œ 

  • ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ์™€ ๋ณต์žก๋„, ํŒ€์› ์ˆ˜ ์ฆ๊ฐ€
  • ๋ชจ๋ฐ”์ผ์ด๋‚˜ ํƒœ๋ธ”๋ฆฟ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋””๋ฐ”์ด์Šค ๋“ฑ์žฅ

CSS ์ „์ฒ˜๋ฆฌ๊ธฐ (CSS Preprocessor) : CSS๊ฐ€ ๊ตฌ์กฐ์ ์œผ๋กœ ์ž‘์„ฑ๋  ์ˆ˜ ์žˆ๊ฒŒ ๋„์›€์„ ์ฃผ๋Š” ๋„๊ตฌ
( SASS๊ฐ€ CSS ์ „์ฒ˜๋ฆฌ๊ธฐ ์ค‘ ๊ฐ€์žฅ ์œ ๋ช… )

  • SASS(Syntactically Awesome Style Sheets) - Preprocessor
    : CSS๋ฅผ ํ™•์žฅํ•ด์ฃผ๋Š” ์Šคํฌ๋ฆฝํŒ… ์–ธ์–ด
    ( SCSS ์ฝ”๋“œ๋ฅผ ์ฝ์–ด์„œ ์ „์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ์ปดํŒŒ์ผํ•ด์„œ ์ „์—ญ CSS๋ฒˆ๋“ค ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์ „์ฒ˜๋ฆฌ๊ธฐ ์—ญํ•  )

CSS ๋ฐฉ๋ฒ•๋ก ์˜ ๊ณตํ†ต ์ง€ํ–ฅ์ 

  • ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ
  • ์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐํ™”(์‰ฌ์šด ์œ ์ง€๋ณด์ˆ˜)
  • ์ฝ”๋“œ์˜ ํ™•์žฅ์„ฑ
  • ์ฝ”๋“œ์˜ ์˜ˆ์ธก์„ฑ(ํด๋ž˜์Šค ๋ช…์œผ๋กœ ์˜๋ฏธ ์˜ˆ์ธก)

CSS ๋ฐฉ๋ฒ•๋ก  - BEM
: Block, Element, Modifier๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ํด๋ž˜์Šค๋ช…์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•

Styled-Component (CSS-in-JS)
: JavaScript์—์„œ CSS๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹ -> CSS๋ฅผ ์ปดํฌ๋„ŒํŠธ์˜ ์˜์—ญ์œผ๋กœ ๋ถˆ๋Ÿฌ๋“ค์ธ CSS ์ž‘์„ฑ ๋ฐฉ๋ฒ•


๐Ÿ”ฅ CDD ๊ฐœ๋ฐœ ๋„๊ตฌ

1. Styled Components

: JavaScript์—์„œ CSS๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹ -> CSS๋ฅผ ์ปดํฌ๋„ŒํŠธ์˜ ์˜์—ญ์œผ๋กœ ๋ถˆ๋Ÿฌ๋“ค์ธ CSS ์ž‘์„ฑ ๋ฐฉ๋ฒ•

CSS in JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด CSS๋ฅผ JavaScript๋กœ ๋„ฃ์–ด์ค˜์„œ,
HTML + JS + CSS ๋ฅผ ๋ฌถ์–ด์„œ ํ•˜๋‚˜์˜ JSํŒŒ์ผ ์•ˆ์—์„œ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ ์ค‘ ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ => Styled Components

Styled Components ์„ค์น˜ํ•˜๊ธฐ

- ํ„ฐ๋ฏธ๋„์— ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ Styled Components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

npm install --save styled-components  # npm

yarn add styled-components  # yarn

- package.json์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์—ฌ๋Ÿฌ ๋ฒ„์ „์˜ Styled Components๊ฐ€ ์„ค์น˜๋˜์–ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์ค„์—ฌ์ค€๋‹ค.

{
  "resolutions": {
    "styled-components": "^5"
  }
}

- Styled Components๋ฅผ ์‚ฌ์šฉํ•  ํŒŒ์ผ์—์„œ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

import styled from "styled-components"

Styled Components ๋ฌธ๋ฒ•

1. ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

Styled Components๋Š” ES6์˜ Templete Literals ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. => ๋”ฐ์˜ดํ‘œ๊ฐ€ ์•„๋‹Œ ๋ฐฑํ‹ฑ( ` ) ์‚ฌ์šฉ

import styled from "styled-components";

// Styled Components๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ 
const SkyBlueButton = styled.button`
  background-color: skyblue;
`;

export default function App() {
  // React ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋“ฏ์ด ์‚ฌ์šฉ
  return <SkyBlueButton>SkyBlue Button</SkyBlueButton>;
}

์œ„ ์ฝ”๋“œ ์ถœ๋ ฅ ํ™”๋ฉด


2. ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌํ™œ์šฉํ•ด์„œ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

import styled from "styled-components";

const SkyBlueButton = styled.button`
  background-color: Skyblue;
`;

// ๋งŒ๋“ค์–ด์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌํ™œ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
const BigSkyBlueButton = styled(SkyBlueButton)`
  padding: 10px;
  margin-top: 10px;
`;

// ์žฌํ™œ์šฉํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
const BigRedButton = styled(BigSkyBlueButton)`
  background-color: blue;
  color: white;
`;

export default function App() {
  return (
    <>
      <SkyBlueButton>Skyblue Button</SkyBlueButton>
      <br />
      <BigSkyBlueButton>Big Skyblue Button</BigSkyBlueButton>
      <br />
      <BigRedButton>Big blue Button</BigRedButton>
    </>
  );
}

์œ„ ์ฝ”๋“œ ์ถœ๋ ฅ ํ™”๋ฉด


3. Props ํ™œ์šฉํ•˜๊ธฐ

- Styled Component๋กœ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋„ React ์ปดํฌ๋„ŒํŠธ์ฒ˜๋Ÿผ props๋ฅผ ๋‚ด๋ ค์ค„ ์ˆ˜ ์žˆ๊ณ , ๋‚ด๋ ค์ค€ props ๊ฐ’์— ๋”ฐ๋ผ์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
- Styled Components๋Š” ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ๋ฒ•( ${ } )์„ ์‚ฌ์šฉํ•˜์—ฌ JavaScript ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
- props๋ฅผ ๋ฐ›์•„์˜ค๋ ค๋ฉด props๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

1) Props๋กœ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋งํ•˜๊ธฐ

import styled from "styled-components";

// ๋ฐ›์•„์˜จ prop์— ๋”ฐ๋ผ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค. (์‚ผํ•ญ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ)
const Button1 = styled.button`
  background: ${(props) => (props.skyblue ? "skyblue" : "white")};
`;

export default function App() {
  return (
    <>
      <Button1>Button1</Button1>
      <Button1 skyblue>Button2</Button1>
      </>
  );
}

์œ„ ์ฝ”๋“œ ์ถœ๋ ฅ ํ™”๋ฉด


2) Props ๊ฐ’์œผ๋กœ ๋ Œ๋”๋งํ•˜๊ธฐ
props์˜ ๊ฐ’์„ ํ†ต์งธ๋กœ ํ™œ์šฉํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

import styled from "styled-components";

// ๋ฐ›์•„์˜จ prop ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์ด์šฉํ•ด ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
const Button1 = styled.button`
  background: ${(props) => (props.color ? props.color : "white")};
`;

// ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ๋„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
const Button2 = styled.button`
  background: ${(props) => props.color || "white"};
`;

export default function App() {
  return (
    <>
      <Button1>Button1</Button1>
      <Button1 color="orange">Button1</Button1>
      <Button1 color="tomato">Button1</Button1>
      <br />
      <Button2>Button2</Button2>
      <Button2 color="pink">Button2</Button2>
      <Button2 color="turquoise">Button2</Button2>
    </>
  );
}

4. ์ „์—ญ ์Šคํƒ€์ผ ์„ค์ •ํ•˜๊ธฐ
- ์ „์—ญ ์Šคํƒ€์ผ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด Styled Components์—์„œ createGlobalStyle ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

import { createGlobalStyle } from "styled-components";

- ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด CSS ํŒŒ์ผ์—์„œ ์ž‘์„ฑํ•˜๋“ฏ ์„ค์ •ํ•ด์ฃผ๊ณ  ์‹ถ์€ ์Šคํƒ€์ผ์„ ์ž‘์„ฑํ•œ๋‹ค.

const GlobalStyle = createGlobalStyle`
	button {
		padding : 5px;
    	margin : 2px;
    	border-radius : 3px;
		}
`

- <GlobalStyle> ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ์ „์—ญ์— <GlobalStyle> ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด ์ ์šฉ๋œ๋‹ค.

function App() {
	return (
		<>
			<GlobalStyle />
			<Button>์ „์—ญ ์Šคํƒ€์ผ ์ ์šฉ</Button>
		</>
	);
}

2. Storybook

: UI ๊ฐœ๋ฐœ ๋„๊ตฌ, Component Driven Development๋ฅผ ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ (์ปดํฌ๋„ŒํŠธ ์‹œ๊ฐํ™” & ๋ฌธ์„œํ™”)

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

Storybook ์ฃผ์š” ๊ธฐ๋Šฅ

  • UI ์ปดํฌ๋„ŒํŠธ๋“ค ์นดํƒˆ๋กœ๊ทธํ™”
  • ์ปดํฌ๋„ŒํŠธ ๋ณ€ํ™”๋ฅผ Stories๋กœ ์ €์žฅ
  • ํ•ซ ๋ชจ๋“ˆ ์žฌ๋กœ๋”ฉ๊ณผ ๊ฐ™์€ ๊ฐœ๋ฐœ ํˆด ๊ฒฝํ—˜์„ ์ œ๊ณต
  • ๋ฆฌ์•กํŠธ๋ฅผ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ๋ทฐ ๋ ˆ์ด์–ด ์ง€์›

Storybook ๊ธฐ๋ณธ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

- Storybook ์„ค์น˜

npx storybook init

Storybook ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด, /.storybook ํด๋”์™€ /src/stories ํด๋”๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
/.storybook ํด๋” => Storybook ๊ด€๋ จ ์„ค์ • ํŒŒ์ผ, /src/stories ํด๋” => Storybook ์˜ˆ์‹œ ํŒŒ์ผ

- Storybook ์‹คํ–‰

npm run storybook

localhost:6006์œผ๋กœ ์ ‘๊ทผํ•˜์—ฌ Storybook์„ ์‹คํ–‰ํ•œ๋‹ค.

Storybook์„ ์‚ฌ์šฉํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ณ  ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์น˜์ง€ ์•Š์•„๋„ ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ์ปดํฌ๋„ŒํŠธ์˜ ๋ณ€ํ™”๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๊ฐ„๋‹จํ•œ ์Šคํ† ๋ฆฌ ์ž‘์„ฑ
src ํด๋” > Title.js ํŒŒ์ผ ์ƒ์„ฑ, ์•„๋ž˜์™€ ๊ฐ™์ด React ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด export ํ•ด์ค€๋‹ค.

// Title.js

import React from "react";

// title์€ h1 ์š”์†Œ์˜ textContent, textColor์€ ๊ธ€์ž์ƒ‰์ด ๋˜๋Š” props
const Title = ({title, textColor}) => (
<h1 style={{color: textColor}}>{title}</h1>
);

export default Title;

๊ฐ™์€ ์œ„์น˜์ธ src ํด๋” > Title.stories.js ํŒŒ์ผ ์ƒ์„ฑ
.storybook ์•ˆ์— ์žˆ๋Š” Storybook ์„ค์ • ํŒŒ์ผ์— ์˜ํ•ด ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ๊ณผ ๋˜‘๊ฐ™์€ ํŒŒ์ผ ์ด๋ฆ„์— .stories๋ฅผ ๋ถ™์—ฌ ํŒŒ์ผ์„ ๋งŒ๋“ค๋ฉด ์•Œ์•„์„œ ์Šคํ† ๋ฆฌ๋กœ ์ธ์‹ํ•œ๋‹ค.

// Title.stories.js

// ์•ž์—์„œ ์ž‘์„ฑํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
import Title from "../Title";

// title : ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์œผ๋กœ, '/'๋ฅผ ๋„ฃ์–ด ์นดํ…Œ๊ณ ๋ฆฌํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.
// component : ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์Šคํ† ๋ฆฌ๋กœ ๋งŒ๋“ค ๊ฒƒ์ธ์ง€ ๋ช…์‹œํ•œ๋‹ค.
// argTypes : ์ปดํฌ๋„ŒํŠธ์— ํ•„์š”ํ•œ ์ „๋‹ฌ์ธ์ž์˜ ์ข…๋ฅ˜์™€ ํƒ€์ž…์„ ์ •ํ•ด์ค€๋‹ค.
//            ์ง€๊ธˆ์€ title, textColor์ด๋ผ๋Š” ์ „๋‹ฌ์ธ์ž์— text ํƒ€์ž…์ด ํ•„์š”ํ•จ์„ ์˜๋ฏธํ•œ๋‹ค.
export default {
  title: "Practice/Title",
  component: Title,
  argTypes: {
    title: { control: "text" },
    textColor: { control: "text" },
  },
};

// Title ์ปดํฌ๋„ŒํŠธ๊ฐ€ args๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ props๋กœ ๋‚ด๋ ค์ค€๋‹ค.
const Template = (args) => <Title {...args} />;

// Storybook์—์„œ ํ™•์ธํ•˜๊ณ  ์‹ถ์€ ์ปดํฌ๋„ŒํŠธ๋Š” export const๋กœ ์ž‘์„ฑ
// ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ Storybook์— ๋„ฃ์–ด์ค„ ์Šคํ† ๋ฆฌ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ค€๋‹ค.
// Template.bins({}); ๋Š” ์ •ํ•ด์ง„ ๋ฌธ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์‚ฌ์šฉ
export const RedTitle = Template.bind({});

// ๋งŒ๋“ค์–ด์ค€ ์Šคํ† ๋ฆฌ์˜ ์ „๋‹ฌ์ธ์ž๋ฅผ ์ž‘์„ฑ
RedTitle.args = {
  title: "Red Title",
  textColor: "red",
};

// ์Šคํ† ๋ฆฌ ํ•˜๋‚˜ ๋” ์ƒ์„ฑ
export const BlueTitle = Template.bind({});

// ์Šคํ† ๋ฆฌ์˜ ์ „๋‹ฌ์ธ์ž๋ฅผ ์ž‘์„ฑ
BlueTitle.args = {
  title: "Blue Title",
  textColor: "blue",
};


// ์ „๋‹ฌ์ธ์ž๋ฅผ ์ง์ ‘ ๋ฐ›๋Š” ์Šคํ† ๋ฆฌ ์ž‘์„ฑ
export const StorybookTitle = (args) => {
  return <Title {...args} />;
};

Storybook ๊ณต์‹๋ฌธ์„œ


๐Ÿ”ฅ useRef

: useRef๋ฅผ ํ™œ์šฉํ•˜๋ฉด DOM ๋…ธ๋“œ, ์—˜๋ฆฌ๋จผํŠธ, React ์ปดํฌ๋„ŒํŠธ ์ฃผ์†Œ๊ฐ’์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

( React : DOM ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ๊ฒƒ ์ง€์–‘ -> document.querySelector ๋“ฑ ์‚ฌ์šฉ x )

DOM ์—˜๋ฆฌ๋จผํŠธ์˜ ์ฃผ์†Œ๊ฐ’์„ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

  • focus
  • text selection
  • media playback
  • ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ
  • d3, greensock ๋“ฑ DOM ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

=> ์œ„์™€ ๊ฐ™์€ DOM ๊ฐ์ฒด ์ฃผ์†Œ ํ•„์š”ํ•œ ์ƒํ™ฉ์ด ๊ณ„์† ๋ฐœ์ƒํ•ด useRef ๋ฉ”์„œ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค.

const ์ฃผ์†Œ๊ฐ’์„_๋‹ด๋Š”_๊ทธ๋ฆ‡ = useRef(์ฐธ์กฐ์ž๋ฃŒํ˜•)
// ์ฃผ์†Œ๊ฐ’์„_๋‹ด๋Š”_๊ทธ๋ฆ‡ ๋ณ€์ˆ˜์— ์–ด๋–ค ์ฃผ์†Œ๊ฐ’์ด๋“  ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.
return (
  <div>
  	<input ref={์ฃผ์†Œ๊ฐ’์„_๋‹ด๋Š”_๊ทธ๋ฆ‡} type="text" />
  		{/* React์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ref๋ผ๋Š” ์†์„ฑ์— ์ฃผ์†Œ๊ฐ’์„_๋‹ด๋Š”_๊ทธ๋ฆ‡์„ ๊ฐ’์œผ๋กœ ํ• ๋‹นํ•˜๋ฉด*/}
        {/* ์ฃผ์†Œ๊ฐ’์„_๋‹ด๋Š”_๊ทธ๋ฆ‡ ๋ณ€์ˆ˜์—๋Š” input DOM ์—˜๋ฆฌ๋จผํŠธ์˜ ์ฃผ์†Œ๊ฐ€ ๋‹ด๊ธด๋‹ค. */}
        {/* ์ดํ›„ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ input DOM ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. */}
  	</div>;

=> ์ฃผ์†Œ๊ฐ’์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ re-render ๋˜๋”๋ผ๋„ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.

useRef๋ฅผ ๋‚จ์šฉํ•˜๋Š” ๊ฒƒ์€ React์˜ ์„ ์–ธํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์›์น™๊ณผ ๋ฐฐ์น˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ์กฐ์‹ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์˜ˆ์ œ 1 : focus
https://codesandbox.io/s/patient-worker-3kzhd?from-embed

์˜ˆ์ œ 2 : media playback
https://codesandbox.io/s/priceless-sanderson-kx77s?from-embed


+ Event.stopPropagation()
: ํ˜„์žฌ ์ด๋ฒคํŠธ๊ฐ€ ์บก์ฒ˜๋ง/๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„์—์„œ ๋” ์ด์ƒ ์ „ํŒŒ๋˜์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•œ๋‹ค.

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