React 1์ฃผ์ฐจ ์ •๋ฆฌ

์ด ๊ธ€์˜ ๋ชฉ์ฐจ47๊ฐœ
  1. โœ… React๋ฅผ ์™œ ์‚ฌ์šฉํ• ๊นŒ?
  2. โœ… JSX์˜ ์žฅ์ 
  3. ๐Ÿ” JSX ๊ธฐ๋ณธ ๋ฌธ๋ฒ• ์ •๋ฆฌ
  4. 1. ํ•˜๋‚˜์˜ ์ตœ์ƒ์œ„ ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ๊ธฐ
  5. 2. HTML ์†์„ฑ ๋Œ€์‹  camelCase ์‚ฌ์šฉ
  6. 3. JavaScript ํ‘œํ˜„์‹ ์‚ฌ์šฉ
  7. 4. self-closing ํƒœ๊ทธ๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ซ๊ธฐ
  8. ๐Ÿงฉ Props๋ž€?
  9. ๐Ÿ’ก Props์˜ ํŠน์ง•
  10. โœ๏ธ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ: Comment ์ปดํฌ๋„ŒํŠธ
  11. ๐Ÿ”— ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ(Component Composition)
  12. ๐Ÿงผ ์ฝ”๋“œ ์ •๋ฆฌ๋ฅผ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ
  13. ์˜ˆ: Comment ์ปดํฌ๋„ŒํŠธ ๋ถ„ํ•ด
  14. ๐Ÿงฉ State๋ž€?
  15. โœ… ํŠน์ง•
  16. ๐Ÿ“ฆ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ State ์‚ฌ์šฉ
  17. โ— State๋Š” ์ง์ ‘ ์ˆ˜์ • โŒ
  18. ๐ŸŽข ์ƒ๋ช…์ฃผ๊ธฐ ๋‹จ๊ณ„
  19. ๐Ÿ›  ์ฃผ์š” ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ (ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ๊ธฐ์ค€)
  20. โ›“๏ธ ์ƒ๋ช…์ฃผ๊ธฐ ํ๋ฆ„ ์˜ˆ์ œ
  21. ๐Ÿ” Hook์ด๋ž€?
  22. โœ… useState
  23. ๐Ÿ‘‰ ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” Hook
  24. ๐Ÿ“Œ ์„ค๋ช…
  25. ๐ŸŒ€ useEffect
  26. ๐Ÿ‘‰ ๋ถ€์ˆ˜ ํšจ๊ณผ(Side Effect)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Hook
  27. โ›“๏ธ useEffect์˜ ๋™์ž‘ ๋ฐฉ์‹
  28. โœ… ์˜ˆ์ œ: ๋งˆ์šดํŠธ, ์–ธ๋งˆ์šดํŠธ, ์—…๋ฐ์ดํŠธ
  29. ๐Ÿงช useState & useEffect ๊ฐ™์ด ์‚ฌ์šฉํ•˜๊ธฐ
  30. โœ”๏ธ ๊ฒฐ๊ณผ:
  31. ๐Ÿ“ useMemo
  32. ๐Ÿ“Œ ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์–ต(memoization)ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ๋ฐฉ์ง€
  33. โœ… ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?
  34. ๐Ÿ“ ์˜ˆ์ œ
  35. ๐Ÿ” useCallback
  36. ๐Ÿ“Œ ํ•จ์ˆ˜๋ฅผ ๊ธฐ์–ต(memoization)ํ•ด์„œ ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€
  37. โœ… ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ?
  38. ๐Ÿ“ ์˜ˆ์ œ
  39. ๐ŸŽฏ useRef
  40. ๐Ÿ“Œ DOM ์š”์†Œ๋‚˜ ๋ณ€์ˆ˜์˜ ์ฐธ์กฐ(reference) ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” Hook
  41. ๐Ÿ“ ์˜ˆ์ œ: input์— ํฌ์ปค์Šค ์ฃผ๊ธฐ
  42. โœ… ๋ฆฌ์•กํŠธ์™€ DOM์˜ ์ด๋ฒคํŠธ ์ฐจ์ด์ 
  43. โœ… HTML DOM ๋ฐฉ์‹
  44. โœ… ๋ฆฌ์•กํŠธ ๋ฐฉ์‹
  45. ๐Ÿ’ก ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋ž€?
  46. ๐Ÿ› ๏ธ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ ๋ฐฉ๋ฒ•
  47. ๐Ÿ”ฅ ์ด๋ฒคํŠธ ๊ฐ์ฒด(e)

๐Ÿ’ก React๋ž€?

React๋Š” Facebook(ํ˜„์žฌ Meta)์—์„œ ๋งŒ๋“  JavaScript ๊ธฐ๋ฐ˜์˜ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์›นํŽ˜์ด์ง€์˜ UI(User Interface)๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ, ํšจ์œจ์ ์ด๊ณ  ์ง๊ด€์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.


โœ… React๋ฅผ ์™œ ์‚ฌ์šฉํ• ๊นŒ?

๊ธฐ์กด์˜ ์›น ๊ฐœ๋ฐœ ๋ฐฉ์‹์€ HTML, CSS, JavaScript ํŒŒ์ผ์„ ๋‚˜๋ˆ ์„œ ๊ด€๋ฆฌํ•˜๊ณ ,

ํŽ˜์ด์ง€์˜ ์ž‘์€ ๋ณ€ํ™”๊ฐ€ ์žˆ์–ด๋„ ์ „์ฒด HTML์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•˜์ง€๋งŒ,

React๋Š” ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธํ•˜๊ณ , UI๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.


๐Ÿ’ก JSX๋ž€?

JSX (JavaScript XML) ๋Š” JavaScript์— XML์„ ํ™•์žฅํ•œ ๋ฌธ๋ฒ•์ด๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด, JavaScript ์ฝ”๋“œ ์•ˆ์—์„œ HTML์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ๋ฌธ๋ฒ•

const element = <h1>Hello, React!</h1>;
  • ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ, HTML ํƒœ๊ทธ๋ฅผ ๋งˆ์น˜ JavaScript ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด ์ฝ”๋“œ๋Š” ์‚ฌ์‹ค Babel์ด๋ผ๋Š” ๋„๊ตฌ์— ์˜ํ•ด React.createElement()๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

โœ… JSX์˜ ์žฅ์ 

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

๐Ÿ” JSX ๊ธฐ๋ณธ ๋ฌธ๋ฒ• ์ •๋ฆฌ

1. ํ•˜๋‚˜์˜ ์ตœ์ƒ์œ„ ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ๊ธฐ


// โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ
return (
  <h1>Hello</h1>
  <p>React</p>
);

// โœ… ์˜ฌ๋ฐ”๋ฅธ ์ฝ”๋“œ
return (
  <div>
    <h1>Hello</h1>
    <p>React</p>
  </div>
);

์ปดํฌ๋„ŒํŠธ๋Š” ํ•ญ์ƒ ํ•˜๋‚˜์˜ ๋ถ€๋ชจ ์š”์†Œ๋งŒ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.


2. HTML ์†์„ฑ ๋Œ€์‹  camelCase ์‚ฌ์šฉ


// HTML: <div class="box"></div>
// JSX:  <div className="box"></div>
  • class โ†’ className
  • onclick โ†’ onClick

JSX์—์„œ๋Š” HTML ์†์„ฑ์„ camelCase(์นด๋ฉœ ํ‘œ๊ธฐ๋ฒ•) ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.


3. JavaScript ํ‘œํ˜„์‹ ์‚ฌ์šฉ

JSX ์•ˆ์—์„œ๋Š” ์ค‘๊ด„ํ˜ธ {} ๋ฅผ ์‚ฌ์šฉํ•ด JavaScript ํ‘œํ˜„์‹์„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.


const name = "๋ฏผ์ง€";
return <h1>์•ˆ๋…•ํ•˜์„ธ์š”, {name}๋‹˜!</h1>;
  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง๋„ ๊ฐ€๋Šฅ!

{isLoggedIn ? <Logout /> : <Login />}

4. self-closing ํƒœ๊ทธ๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ซ๊ธฐ

JSX์—์„œ๋Š” ํ˜ผ์ž ์“ฐ์ด๋Š” ํƒœ๊ทธ๋„ ๋ฐ˜๋“œ์‹œ ์Šฌ๋ž˜์‹œ(/) ๋ฅผ ๋ถ™์—ฌ ๋‹ซ์•„์•ผ ํ•œ๋‹ค.


<input />
<br />
<hr />

๐Ÿ’ก Props์™€ ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ

๐Ÿงฉ Props๋ž€?

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๋ฐฉ์‹

function Welcome(props) {
  return <h1>์•ˆ๋…•ํ•˜์„ธ์š”, {props.name}๋‹˜!</h1>;
}

<Welcome name="๋ฏผ์ง€" />
  • props.name์„ ํ†ตํ•ด ๋ถ€๋ชจ๊ฐ€ ์ „๋‹ฌํ•œ name ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ์— ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ๋Š” HTML ์†์„ฑ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•œ๋‹ค.

๐Ÿ’ก Props์˜ ํŠน์ง•

  1. ์ฝ๊ธฐ ์ „์šฉ โ†’ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ props ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
  2. ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ํ•œ ๋ฒˆ์— ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  3. ๋™์ ์œผ๋กœ ๋ Œ๋”๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค. (๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ์ด ๋ฐ”๋€œ)

โœ๏ธ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ: Comment ์ปดํฌ๋„ŒํŠธ

function Comment(props) {
  return (
    <div className="comment">
      <h2>{props.name}</h2>
      <p>{props.comment}</p>
    </div>
  );
}
<Comment name="์ง€ํ›ˆ" comment="์ข‹์€ ๊ธ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!" />
<Comment name="์ˆ˜์•„" comment="๋งŽ์ด ๋ฐฐ์›Œ๊ฐ€์š” ๐Ÿ˜Š" />
  • ์ด๋ ‡๊ฒŒ props๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๐Ÿ”— ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ(Component Composition)

ํ•ฉ์„ฑ์ด๋ž€, ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋ชจ์•„์„œ ํ•˜๋‚˜์˜ ํฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

function CommentList() {
  return (
    <div>
      <Comment name="๋ฏผ์ง€" comment="์ •๋ง ์ข‹์•„์š”!" />
      <Comment name="์ง€ํ›ˆ" comment="๋ฐฐ์›Œ๊ฐ‘๋‹ˆ๋‹ค~" />
    </div>
  );
}
  • CommentList๋Š” Comment๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•ด ๋งŒ๋“  ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ์ค‘์ฒฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”


๐Ÿงผ ์ฝ”๋“œ ์ •๋ฆฌ๋ฅผ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ

์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋„ˆ๋ฌด ์ปค์ง€๊ฑฐ๋‚˜ ๊ธฐ๋Šฅ๋ณ„๋กœ ๊ตฌ๋ถ„์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ์„ ํ†ตํ•ด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ: Comment ์ปดํฌ๋„ŒํŠธ ๋ถ„ํ•ด

function Avatar(props) {
  return <img src={props.user.avatarUrl} alt={props.user.name} />;
}

function UserInfo(props) {
  return (
    <div className="user-info">
      <Avatar user={props.user} />
      <span>{props.user.name}</span>
    </div>
  );
}

function Comment(props) {
  return (
    <div className="comment">
      <UserInfo user={props.author} />
      <p>{props.text}</p>
      <span>{props.date}</span>
    </div>
  );
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋” ๋ช…ํ™•ํ•œ ์—ญํ• ์„ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด ์žฌ์‚ฌ์šฉ๋„ ์‰ฌ์›Œ์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๋„ ํŽธํ•ด์ง„๋‹ค.

๐Ÿ’ก State์™€ ์ƒ๋ช…์ฃผ๊ธฐ

๐Ÿงฉ State๋ž€?

State(์ƒํƒœ) ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ธฐ์–ตํ•ด์•ผ ํ•  ๋ฐ์ดํ„ฐ

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์ด๋‚˜ ๋‚ด๋ถ€์˜ ๋ณ€ํ™”์— ๋”ฐ๋ผ ๋ฐ”๋€Œ๋Š” ๊ฐ’์ด๋‹ค.

โœ… ํŠน์ง•

  • State๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์„ ์–ธ๋จ
  • ๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋ง
  • Props๋Š” ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฐ›๋Š” ๊ฐ’(์™ธ๋ถ€), State๋Š” ์ปดํฌ๋„ŒํŠธ ์ž์‹ ์ด ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ’(๋‚ด๋ถ€)

๐Ÿ“ฆ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ State ์‚ฌ์šฉ

import React from 'react';

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 }; // ์ดˆ๊ธฐ ์ƒํƒœ ์ •์˜

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ count: this.state.count + 1 }); // ์ƒํƒœ ์—…๋ฐ์ดํŠธ
  }

  render() {
    return (
      <div>
        <p>ํ˜„์žฌ ์นด์šดํŠธ: {this.state.count}</p>
        <button onClick={this.handleClick}>+1</button>
      </div>
    );
  }
}
  • this.state๋Š” ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์ •์˜
  • this.setState()๋Š” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•จ

โ— State๋Š” ์ง์ ‘ ์ˆ˜์ • โŒ

this.state.count = this.state.count + 1; // โŒ ์ ˆ๋Œ€ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ˆ ๋จ!

๋ฐ˜๋“œ์‹œ setState()๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋งŒ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ž˜์•ผ ๋ฆฌ์•กํŠธ๊ฐ€ ์ƒํƒœ ๋ณ€ํ™”์™€ ํ•จ๊ป˜ ์ž๋™์œผ๋กœ ๋ Œ๋”๋ง์„ ๊ด€๋ฆฌํ•ด์ค€๋‹ค.

this.state๋ฅผ ์ง์ ‘ ๋ฐ”๊พธ๋ฉด ํ™”๋ฉด์— ์•„๋ฌด๋Ÿฐ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.


๐Ÿ’ก ์ƒ๋ช…์ฃผ๊ธฐ(Lifecycle)๋ž€?

์ปดํฌ๋„ŒํŠธ๋Š” ์ƒ์„ฑ โ†’ ์—…๋ฐ์ดํŠธ โ†’ ์ œ๊ฑฐ์˜ ํ๋ฆ„์„ ๊ฐ–๋Š”๋ฐ,

์ด ๊ณผ์ •์„ ์ปดํฌ๋„ŒํŠธ ์ƒ๋ช…์ฃผ๊ธฐ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๐ŸŽข ์ƒ๋ช…์ฃผ๊ธฐ ๋‹จ๊ณ„

  1. Mounting (์ƒ์„ฑ): ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋งŒ๋“ค์–ด์ง€๋Š” ๋‹จ๊ณ„
  2. Updating (์—…๋ฐ์ดํŠธ): props ๋˜๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ
  3. Unmounting (์ œ๊ฑฐ): ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์งˆ ๋•Œ

๐Ÿ›  ์ฃผ์š” ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ (ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ๊ธฐ์ค€)

๋ฉ”์„œ๋“œ ์‹œ์  ์—ญํ• 
constructor() ์ƒ์„ฑ ์ „ ์ดˆ๊ธฐ๊ฐ’ ์„ค์ •
render() ๋ Œ๋”๋ง ํ™”๋ฉด์— UI ์ถœ๋ ฅ
componentDidMount() ๋ Œ๋”๋ง ํ›„ API ํ˜ธ์ถœ, setInterval ๋“ฑ
componentDidUpdate() ์ƒํƒœ๋‚˜ props๊ฐ€ ๋ณ€๊ฒฝ๋œ ํ›„ ๋ณ€ํ™” ๊ฐ์ง€
componentWillUnmount() ์ œ๊ฑฐ ์ง์ „ ์ •๋ฆฌ ์ž‘์—… (ํƒ€์ด๋จธ ์ œ๊ฑฐ ๋“ฑ)

โ›“๏ธ ์ƒ๋ช…์ฃผ๊ธฐ ํ๋ฆ„ ์˜ˆ์ œ

class LifeCycleDemo extends React.Component {
  constructor(props) {
    super(props);
    console.log('1๏ธโƒฃ constructor');
    this.state = { count: 0 };
  }

  componentDidMount() {
    console.log('3๏ธโƒฃ componentDidMount');
  }

  componentDidUpdate() {
    console.log('๐Ÿ”„ componentDidUpdate');
  }

  componentWillUnmount() {
    console.log('โŒ componentWillUnmount');
  }

  render() {
    console.log('2๏ธโƒฃ render');
    return (
      <div>
        <p>{this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          ์ฆ๊ฐ€
        </button>
      </div>
    );
  }
}

๋ฒ„ํŠผ ํด๋ฆญ โ†’ ์ƒํƒœ ์—…๋ฐ์ดํŠธ โ†’ render โ†’ componentDidUpdate ์ˆœ์„œ๋กœ ํ˜ธ์ถœ๋œ๋‹ค.

๐Ÿ’ก ๋ฆฌ์•กํŠธ Hook ์ •๋ฆฌ

๐Ÿ” Hook์ด๋ž€?

Hook(ํ›…)์€ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ state์™€ ์ƒ๋ช…์ฃผ๊ธฐ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ํ•จ์ˆ˜

๋ฆฌ์•กํŠธ 16.8๋ถ€ํ„ฐ ๊ณต์‹์ ์œผ๋กœ ๋„์ž…๋˜์—ˆ๊ณ , ์ง€๊ธˆ์€ ๊ฑฐ์˜ ๋ชจ๋“  ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ์—์„œ Hook์„ ์‚ฌ์šฉํ•œ๋‹ค.


โœ… useState

๐Ÿ‘‰ ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” Hook

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // count: ์ƒํƒœ๊ฐ’, setCount: ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜

  return (
    <div>
      <p>ํ˜„์žฌ ์นด์šดํŠธ: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

๐Ÿ“Œ ์„ค๋ช…

  • useState(0) โ†’ ์ดˆ๊ธฐ๊ฐ’ 0
  • count โ†’ ํ˜„์žฌ ์ƒํƒœ๊ฐ’
  • setCount โ†’ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜
  • ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” ์ž๋™์œผ๋กœ ์žฌ๋ Œ๋”๋ง

๐ŸŒ€ useEffect

๐Ÿ‘‰ ๋ถ€์ˆ˜ ํšจ๊ณผ(Side Effect)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Hook

API ํ˜ธ์ถœ, ํƒ€์ด๋จธ ์„ค์ •, DOM ์ง์ ‘ ์กฐ์ž‘ ๋“ฑ์„ ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

import React, { useState, useEffect } from 'react';

function Timer() {
  const [count, setCount] = useState(0);

  // ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋œ ํ›„ ์‹คํ–‰๋จ
  useEffect(() => {
    console.log(`์นด์šดํŠธ๊ฐ€ ${count}๋กœ ๋ฐ”๋€Œ์—ˆ์–ด์š”!`);
  }, [count]); // count๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์‹คํ–‰

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

โ›“๏ธ useEffect์˜ ๋™์ž‘ ๋ฐฉ์‹

์˜์กด์„ฑ ๋ฐฐ์—ด ([]) ์‹คํ–‰ ์‹œ์  ์˜ˆ์‹œ
์—†์Œ ํ•ญ์ƒ ์‹คํ–‰ (๋ Œ๋”๋ง๋งˆ๋‹ค) useEffect(() => { ... });
๋นˆ ๋ฐฐ์—ด [] ์ตœ์ดˆ ๋งˆ์šดํŠธ ์‹œ 1๋ฒˆ ์‹คํ–‰ useEffect(() => { ... }, []);
ํŠน์ • ๊ฐ’ [a, b] a ๋˜๋Š” b๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ์‹คํ–‰ useEffect(() => { ... }, [a, b]);

โœ… ์˜ˆ์ œ: ๋งˆ์šดํŠธ, ์–ธ๋งˆ์šดํŠธ, ์—…๋ฐ์ดํŠธ

useEffect(() => {
  console.log('์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚จ'); // Mount

  return () => {
    console.log('์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง'); // Unmount
  };
}, []); // ๋นˆ ๋ฐฐ์—ด: ์ตœ์ดˆ ๋งˆ์šดํŠธ & ์–ธ๋งˆ์šดํŠธ ์‹œ๋งŒ ์‹คํ–‰

๐Ÿงช useState & useEffect ๊ฐ™์ด ์‚ฌ์šฉํ•˜๊ธฐ

function WelcomeMessage({ name }) {
  const [message, setMessage] = useState('');

  useEffect(() => {
    setMessage(`${name}๋‹˜, ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!`);
  }, [name]);

  return <p>{message}</p>;
}

โœ”๏ธ ๊ฒฐ๊ณผ:

  • name์ด ๋ฐ”๋€Œ๋ฉด ์ž๋™์œผ๋กœ message๋„ ๋ณ€๊ฒฝ๋จ
  • ์˜์กด์„ฑ ๋ฐฐ์—ด ๋•๋ถ„์— ํ•„์š”ํ•œ ์‹œ์ ์—๋งŒ ์‹คํ–‰๋จ

๐Ÿ“ useMemo

๐Ÿ“Œ ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์–ต(memoization)ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ๋ฐฉ์ง€

const memoizedValue = useMemo(() => {
  return someHeavyComputation(input);
}, [input]);

โœ… ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ๊ณ„์‚ฐ ๋น„์šฉ์ด ๋†’์€ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋„๋ก ํ•  ๋•Œ
  • ํŠน์ • props๋‚˜ state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๋‹ค์‹œ ๊ณ„์‚ฐ๋˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ

๐Ÿ“ ์˜ˆ์ œ

import { useMemo, useState } from "react";

function ExpensiveComponent({ input }) {
  const expensiveValue = useMemo(() => {
    console.log("๐Ÿ’ฅ ์—ฐ์‚ฐ ์‹คํ–‰!");
    return input * 1000000;
  }, [input]);

  return <p>๊ฒฐ๊ณผ: {expensiveValue}</p>;
}

input์ด ๋ฐ”๋€” ๋•Œ๋งŒ ์—ฐ์‚ฐ์ด ๋‹ค์‹œ ์ˆ˜ํ–‰๋˜๊ณ , ๊ทธ ์™ธ์—๋Š” ์ด์ „ ๊ฐ’ ์žฌ์‚ฌ์šฉ


๐Ÿ” useCallback

๐Ÿ“Œ ํ•จ์ˆ˜๋ฅผ ๊ธฐ์–ต(memoization)ํ•ด์„œ ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€

jsx
๋ณต์‚ฌํŽธ์ง‘
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

โœ… ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ?

  • ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— props๋กœ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ธธ ๋•Œ
  • ๋ฆฌ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ

๐Ÿ“ ์˜ˆ์ œ

import React, { useCallback, useState } from "react";
import Child from "./Child";

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log("Clicked!");
  }, []);

  return (
    <><button onClick={() => setCount(count + 1)}>+1</button>
      <Child onClick={handleClick} />
    </>
  );
}

Child ์ปดํฌ๋„ŒํŠธ๋Š” handleClick์ด ๋ณ€ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ


๐ŸŽฏ useRef

๐Ÿ“Œ DOM ์š”์†Œ๋‚˜ ๋ณ€์ˆ˜์˜ ์ฐธ์กฐ(reference) ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” Hook

const myRef = useRef(null);
  • .current ์†์„ฑ์œผ๋กœ ์‹ค์ œ DOM ์ ‘๊ทผ ๊ฐ€๋Šฅ
  • ์ƒํƒœ ๋ณ€๊ฒฝ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ณ€๊ฒฝ๋˜์–ด๋„ ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š์Œ

๐Ÿ“ ์˜ˆ์ œ: input์— ํฌ์ปค์Šค ์ฃผ๊ธฐ

import React, { useRef } from "react";

function FocusInput() {
  const inputRef = useRef(null);

  const onClick = () => {
    inputRef.current.focus();
  };

  return (
    <><input ref={inputRef} />
      <button onClick={onClick}>ํฌ์ปค์Šค ์ฃผ๊ธฐ</button>
    </>
  );
}

๐Ÿ’ก ์ด๋ฒคํŠธ(Event)๋ž€?

  • ์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์‚ฌ๊ฑด
    • ๋ฒ„ํŠผ ํด๋ฆญ, ํ‚ค๋ณด๋“œ ์ž…๋ ฅ, ๋งˆ์šฐ์Šค ์›€์ง์ž„, ํผ ์ œ์ถœ ๋“ฑ
  • ์˜ˆ: onClick, onChange, onSubmit, onMouseEnter, onKeyDown, โ€ฆ

โœ… ๋ฆฌ์•กํŠธ์™€ DOM์˜ ์ด๋ฒคํŠธ ์ฐจ์ด์ 

๊ตฌ๋ถ„ DOM ๋ฐฉ์‹ ๋ฆฌ์•กํŠธ ๋ฐฉ์‹
์ด๋ฒคํŠธ ์ด๋ฆ„ ์†Œ๋ฌธ์ž (onclick) ์นด๋ฉœํ‘œ๊ธฐ๋ฒ• (onClick)
์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ „๋‹ฌ ๋ฐฉ์‹ ๋ฌธ์ž์—ด ("myFunc()") ํ•จ์ˆ˜ ({myFunc})

๐Ÿ“Ž ์˜ˆ์‹œ ๋น„๊ต

โœ… HTML DOM ๋ฐฉ์‹

<button onclick="handleClick()">Click Me</button>

โœ… ๋ฆฌ์•กํŠธ ๋ฐฉ์‹

<button onClick={handleClick}>Click Me</button>

๐Ÿ’ก ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋ž€?

  • ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜
  • ๋ณดํ†ต ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์ •์˜ํ•ด์„œ ์‚ฌ์šฉ
function MyComponent() {
  const handleClick = () => {
    alert("๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
  };

  return <button onClick={handleClick}>ํด๋ฆญ</button>;
}

๐Ÿ› ๏ธ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ ๋ฐฉ๋ฒ•

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋ ค๋ฉด ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋˜๋Š” .bind() ์‚ฌ์šฉ

jsx
๋ณต์‚ฌํŽธ์ง‘
// ๋ฐฉ๋ฒ• 1: ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์‚ฌ์šฉ
<button onClick={() => handleClick(userId)}>ํด๋ฆญ</button>

// ๋ฐฉ๋ฒ• 2: bind ์‚ฌ์šฉ
<button onClick={handleClick.bind(null, userId)}>ํด๋ฆญ</button>

๐Ÿ”ฅ ์ด๋ฒคํŠธ ๊ฐ์ฒด(e)

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ž๋™ ์ „๋‹ฌ๋˜๋Š” ๊ฐ์ฒด

jsx
๋ณต์‚ฌํŽธ์ง‘
function handleClick(event) {
  console.log(event.target); // ํด๋ฆญ๋œ DOM ์š”์†Œ
}
์ „์ฒด ๊ธ€ ๋ณด๊ธฐ