React ๊ฐœ๋… ์ •๋ฆฌ ๐Ÿ“

Dodamยท2023๋…„ 9์›” 8์ผ
0

[React]

๋ชฉ๋ก ๋ณด๊ธฐ
1/12
post-thumbnail

React

  • Virtual DOM : ๋ธŒ๋ผ์šฐ์ €์— ์‹ค์ œ๋กœ ๋ณด์—ฌ์ง€๋Š” DOM์ด ์•„๋‹ˆ๋ผ ๋ฉ”๋ชจ๋ฆฌ ์ƒ์—๋งŒ ์กด์žฌํ•˜๋Š” ๊ฐ€์ƒ์˜ DOM์œผ๋กœ, ๊ทธ๋ƒฅ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ ์†๋„๊ฐ€ ์‹ค์ œ DOM๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๋‹ค.
  • ๋ฆฌ์•กํŠธ๋Š” ์ƒํƒœ(state)๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋ฉด Virtual DOM์— ๋จผ์ € ๋ Œ๋”๋งํ•œ ํ›„, ์‹ค์ œ DOM๊ณผ ๋น„๊ตํ•ด ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๋ถ€๋ถ„๋งŒ ๋ถ€๋ถ„์ ์œผ๋กœ ํŒจ์น˜ํ•œ๋‹ค.

Environment

Webpack, Babel

  • Webpack : ์ปดํฌ๋„ŒํŠธ๋ณ„๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์ž‘์„ฑํ•œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ์„ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ฃผ๋Š” ์—ญํ• 
  • Babel : JSX ๋“ฑ ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ
    (์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ๊ธฐ์กด ๋ฌธ๋ฒ•์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ํŠธ๋žœ์ŠคํŒŒ์ผ๋Ÿฌ๋กœ, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์•„์ง ์ง€์›ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ผ๋ถ€ ๋ธŒ๋ผ์šฐ์ €๋งŒ ์ง€์›ํ•˜๋Š” ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.)

Component

  • ์ปดํฌ๋„ŒํŠธ : ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ UI ์กฐ๊ฐ
  • ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•  ๋• ๋ฆฌ์•กํŠธ๋ฅผ import ํ•ด์•ผ ํ•œ๋‹ค.
    import React from 'react';
  • ReactDOM.render() : ๋ธŒ๋ผ์šฐ์ €์— ์žˆ๋Š” ์‹ค์ œ DOM ๋‚ด๋ถ€์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ

JSX

  • ๋ฆฌ์•กํŠธ Fragment : <></>, ๋ธŒ๋ผ์šฐ์ €์ƒ์— ์‹ค์ œ ์—˜๋ฆฌ๋จผํŠธ๋กœ ๋‚˜์ž๋‚˜์ง€ ์•Š์Œ. ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์˜ ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹จ์ˆœํžˆ ๊ฐ์‹ธ๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์œผ๋กœ ๋ถˆํ•„์š”ํ•œ div๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  Fragment๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ธ๋ผ์ธ ์Šคํƒ€์ผ์€ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฉฐ, ์Šคํƒ€์ผ ์†์„ฑ ์ด๋ฆ„์€ ์นด๋ฉœ์ผ€์ด์Šค๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
    ex) background-color โ†’ backgroundColor
const style = {
	backgroundColor: 'black',
  	fontSize: 24
}

<div style={style}>{name}</div>
  • css class๋Š” class ๋Œ€์‹  className์œผ๋กœ ์ž‘์„ฑ
  • JSX ๋‚ด๋ถ€ ์ฃผ์„์€ {/* ์ด ์•ˆ์— */} ์ž‘์„ฑ (์ค‘๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ์•ผ ํ•จ)
  • ํƒœ๊ทธ ์•ˆ์—์„œ๋Š” // ์ฃผ์„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (<Hello //์ฃผ์„ />)

Props

  • defaultProps : ์ปดํฌ๋„ŒํŠธ์— props๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฐ’ ์„ค์ •
import React from 'react';

function Hello({ color, name }) {
  return <div style={{ color }}>์•ˆ๋…•ํ•˜์„ธ์š” {name}</div>
}

Hello.defaultProps = {
  name: '์ด๋ฆ„์—†์Œ'
}
  • props.children : ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„ ๋• props.children์„ ์‚ฌ์šฉํ•œ๋‹ค.
return <div>{props.children}</div>;

์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง

  • ์ฃผ๋กœ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž ๋˜๋Š” && ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • JSX์—์„œ null, false, undefined๋ฅผ ๋ Œ๋”๋งํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š”๋‹ค.
  • props ๊ฐ’ ํ• ๋‹น์„ ์ƒ๋žตํ•˜๋ฉด true๊ฐ€ ํ• ๋‹น๋œ๋‹ค. (isSpecial === isSpecial={true})

useState

  • ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ž™์…˜์— ๋”ฐ๋ผ ๋ฐ”๋€Œ๋Š” ๋™์ ์ธ ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•  ๋•Œ state๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์›๋ž˜ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ๋ฆฌ์•กํŠธ 16.8์—์„œ Hooks์ด ๋„์ž…๋˜๋ฉด์„œ, ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • useState Hook์„ ์ด์šฉํ•ด ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ state๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Setter ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ :
    - ์ƒˆ๋กœ์šด state ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๋ฐฉ์‹
    setValue(value + 1);

    • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ์‹ (ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ)
      setValue(prevValue => prevValue + 1);
    • ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ ๋ฐฉ์‹์€ ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™”์™€๋„ ๊ด€๋ จ๋˜์–ด ์žˆ๋‹ค.
  • ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ : onClick={onIncrease()} X, onClick={onIncrease} OK
    (์ „์ž๋Š” ๋ Œ๋”๋ง๋˜๋Š” ์‹œ์ ์—์„œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ๋ฒ„๋ฆผ)

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ input ํƒœ๊ทธ ์ƒํƒœ ๊ด€๋ฆฌ :

  • useState์—์„œ ๋ฌธ์ž์—ด์ด ์•„๋‹ˆ๋ผ ๊ฐ์ฒด๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

  • input ํƒœ๊ทธ์— name์„ ์„ค์ •ํ•˜๊ณ , ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ด ๊ฐ’์„ ์ฐธ์กฐํ•œ๋‹ค. (e.target.name: e.target.value)

  • ๊ฐ์ฒด state๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋Š” ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ ๋˜๊ณ , ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    spread ์—ฐ์‚ฐ์ž (...)๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

// XXX
inputs[name] = value;

// OOO
setInputs({
	...inputs,
  [name]: value
});
  • ์ด๋ ‡๊ฒŒ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์ฃผ์–ด์•ผ๋งŒ
    • ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ , ์ด์— ๋”ฐ๋ผ ๋ฆฌ๋ Œ๋”๋ง์ด ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.
      (setState()๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ๊ธฐ์กด ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๊ฒŒ ๋˜๋ฉด ๊ฐ’์ด ๋ฐ”๋€Œ์–ด๋„ ๋ฆฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.)
    • ์ปดํฌ๋„ŒํŠธ ์—…๋ฐ์ดํŠธ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

useRef

  • ์ปดํฌ๋„ŒํŠธ์—์„œ ํŠน์ • DOM ์š”์†Œ๋ฅผ ์„ ํƒํ•ด์•ผ ํ•  ๋•Œ
const nameInput = useRef();	// Ref ๊ฐ์ฒด ์ƒ์„ฑ

const onReset = () => {
  setInputs({
    name: '',
    nickname: ''
  });
  nameInput.current.focus(); // Ref ๊ฐ์ฒด์˜ current ๊ฐ’์œผ๋กœ ์ ‘๊ทผ
};

<input
	name="name"
	onChange={onChange}
	value={name}
	ref={nameInput}	// ref ์ง€์ •
/>
  • ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜ ๊ด€๋ฆฌ :

    • useRef๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ณ€์ˆ˜๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์–ด๋„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š”๋‹ค.
      (ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ useRef๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ผ๋ฐ˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ๊ฐ’์ด ์ดˆ๊ธฐํ™” ๋œ๋‹ค. state๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, state ๊ฐ’์ด ์„ค์ •๋  ๋•Œ๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค.)

    • ๋ฆฌ์•กํŠธ์˜ state๋Š” setter๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๋‚˜์„œ ๋ Œ๋”๋ง์ด ๋œ ์ดํ›„์— ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด,
      useRef๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ณ€์ˆ˜๋Š” ์„ค์ • ํ›„ ๋ฐ”๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

    • useRef()๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์œผ๋ฉด, ์ด ๊ฐ’์ด Ref ๊ฐ์ฒด .current์˜ ๊ธฐ๋ณธ๊ฐ’์ด ๋œ๋‹ค.
      .current๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

const nextId = useRef(4);
const onCreate = () => {
  nextId.current += 1;
};

๋ฐฐ์—ด

  • ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋ ค๋ฉด map() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ๋ฆฌ์•กํŠธ์—์„œ ๋ฐฐ์—ด์„ ๋ Œ๋”๋งํ•  ๋•Œ๋Š” key props๋ฅผ ๋ฐ˜๋“œ์‹œ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
    key๋Š” ๊ณ ์œ ํ•œ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•˜๋ฉฐ (์ฃผ๋กœ id ๊ฐ’์œผ๋กœ ์„ค์ •, ์ค‘๋ณต๋˜๋Š” key๊ฐ€ ์žˆ์œผ๋ฉด ์—…๋ฐ์ดํŠธ๊ฐ€ ์ œ๋Œ€๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.) ๋งŒ์•ฝ, key๋กœ ์„ค์ •ํ• ๋งŒํ•œ ๊ฐ’์ด ์—†๋‹ค๋ฉด map() ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ index๋ฅผ key๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • key props๊ฐ€ ํ•„์š”ํ•œ ์ด์œ  :
    key๊ฐ€ ์—†๋‹ค๋ฉด ๋ฐฐ์—ด์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ƒ๊ฒจ์„œ ๋ฆฌ๋ Œ๋”๋ง์„ ํ•  ๋•Œ, ๋น„ํšจ์œจ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๋ Œ๋”๋ง์„ ํ•˜๊ฒŒ ๋œ๋‹ค. (ex. a, b, d, e ์‚ฌ์ด์— c๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ, b์™€ d ์‚ฌ์ด์— c๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ a, b, d -> c, e -> d, e ์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฝ์ž…๋œ๋‹ค.)
    key๊ฐ€ ์žˆ์œผ๋ฉด ์ˆ˜์ •๋˜์ง€ ์•Š๋Š” ๊ธฐ์กด์˜ ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์›ํ•˜๋Š” ๋‚ด์šฉ๋งŒ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.


    ๋ฐฐ์—ด์— ํ•ญ๋ชฉ ์ถ”๊ฐ€ / ์ œ๊ฑฐ / ์ˆ˜์ •ํ•˜๊ธฐ

  • ๋ฐฐ์—ด์— ๋ณ€ํ™”๋ฅผ ์ค„ ๋•Œ์—๋„ ๊ฐ์ฒด์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์•ผ ํ•œ๋‹ค.
    push, splice, sort ๋“ฑ ๊ธฐ์กด ๋ฐฐ์—ด์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

    • ๋ฐฐ์—ด์— ํ•ญ๋ชฉ ์ถ”๊ฐ€ํ•˜๊ธฐ

      • spread ... ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ (๊ธฐ์กด ๋ฐฐ์—ด์„ ํŽผ์ณ์„œ ๋ณต์‚ฌํ•ด ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.)
        setUsers([...users, user]);
      • concat ํ•จ์ˆ˜ (๊ธฐ์กด์˜ ๋ฐฐ์—ด์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๋ฐฐ์—ด ๋ฐ˜ํ™˜)
        setUsers(users.concat(user));

    • ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ ์ œ๊ฑฐํ•˜๊ธฐ

      • filter ํ•จ์ˆ˜ (๋ฐฐ์—ด์—์„œ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑํ•˜๋Š” ์›์†Œ๋“ค๋งŒ ์ถ”์ถœํ•ด ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•จ)
      setUsers(users.filter(user => user.id !== id));
      // id === user.id์ธ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐ
    • ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ ์ˆ˜์ •ํ•˜๊ธฐ
      - ๋ฐฐ์—ด์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋„ map() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

      const onToggle = id => {
      	setUsers(
      	users.map(user =>
           user.id === id ? { ...user, active: !user.active } : user
          )
        );
      };

      ํ•ด๋‹นํ•˜๋Š” id์˜ ์œ ์ € active ๊ฐ’์„ ๋ฐ˜์ „์‹œ์ผœ์ค€๋‹ค.


useEffect

  • useEffect๋ฅผ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ/์–ธ๋งˆ์šดํŠธ/์—…๋ฐ์ดํŠธ(ํŠน์ • props๊ฐ€ ๋ฐ”๋€” ๋•Œ) ์‹œ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

deps ๋ฐฐ์—ด์ด ๋นˆ ๋ฐฐ์—ด์ธ ๊ฒฝ์šฐ

  • useEffect ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜, ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์˜์กด๊ฐ’ ๋ฐฐ์—ด(deps)๋ฅผ ๋„ฃ๋Š”๋‹ค.
    deps ๋ฐฐ์—ด์— ์žˆ๋Š” ํ•ญ๋ชฉ์˜ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    deps๋กœ ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ๋งŒ(์ฒ˜์Œ ๋ Œ๋”๋ง๋  ๋•Œ) useEffect์— ๋“ฑ๋กํ•œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

  • userEffect๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•Œ ๋ฐ˜ํ™˜๋˜๋Š” ํ•จ์ˆ˜๋Š” cleanup ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. deps๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ cleanup ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

  • ๋งˆ์šดํŠธ / ์–ธ๋งˆ์šดํŠธ :

    • ๋งˆ์šดํŠธ ์‹œ ์ฃผ๋กœ ํ•˜๋Š” ์ž‘์—…
      • props๋กœ ๋ฐ›์€ ๊ฐ’์„ ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ปฌ ์ƒํƒœ๋กœ ์„ค์ •
      • ์™ธ๋ถ€ API ์š”์ฒญ
      • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
      • setInterval์„ ํ†ตํ•œ ๋ฐ˜๋ณต ์ž‘์—…, ๋˜๋Š” setTimeout์„ ํ†ตํ•œ ์ž‘์—… ์˜ˆ์•ฝ
    • ์–ธ๋งˆ์šดํŠธ ์‹œ ์ฃผ๋กœ ํ•˜๋Š” ์ž‘์—…
      • setInterval, setTimeout์„ ์‚ฌ์šฉํ•ด ๋“ฑ๋กํ•œ ์ž‘์—… clearํ•˜๊ธฐ (clearInterval, clearTimeout)
      • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธ์Šคํ„ด์Šค ์ œ๊ฑฐ

deps ๋ฐฐ์—ด์— ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ

  • deps ๋ฐฐ์—ด์— ๊ฐ’์„ ๋„ฃ์œผ๋ฉด, ํ•ด๋‹น ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ์—๋„ useEffect์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ, ๊ฐ’์ด ๋ฐ”๋€Œ๊ธฐ ์ง์ „์— cleanup ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

  • useEffect ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ๋‚˜ props๋Š” ๋ฐ˜๋“œ์‹œ deps์— ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด userEffect์— ๋“ฑ๋กํ•œ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๊ฐ€์žฅ ์ตœ์‹  ๊ฐ’์„ ์ฐธ์กฐํ•  ๊ฒƒ์ด๋ผ๊ณ  ๋ณด์žฅํ•  ์ˆ˜ ์—†๋‹ค.

deps ๋ฐฐ์—ด์„ ์ƒ๋žตํ•œ ๊ฒฝ์šฐ (=userEffect์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ ์ƒ๋žต)

  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    - ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋ฉด, ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐ”๋€ ๋‚ด์šฉ์ด ์—†๋”๋ผ๋„ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.
    (์‹ค์ œ DOM์—์„œ๋Š” ๋ฐ”๋€ ๋‚ด์šฉ์ด ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋งŒ ์—…๋ฐ์ดํŠธ๋˜์ง€๋งŒ, Virtual DOM์—์„œ๋Š” ์ „๋ถ€ ๋ Œ๋”๋ง๋œ๋‹ค.)


useMemo

  • ์ด๋ฏธ ์—ฐ์‚ฐ๋œ ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ("memorized" : ์ด์ „์— ์—ฐ์‚ฐํ•ด๋‘” ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•จ)
const count = countActiveUsers(users);

const count = useMemo(() => countActiveUsers(users), [users];
  • ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ : ์ฝœ๋ฐฑ ํ•จ์ˆ˜ (์—ฐ์‚ฐ ํ•จ์ˆ˜),
    ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ : deps ๋ฐฐ์—ด
  • deps ๋ฐฐ์—ด ์•ˆ์˜ ๋‚ด์šฉ์ด ๋ฐ”๋€Œ๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ๊ฐ’์„ ์—ฐ์‚ฐํ•ด์ฃผ๊ณ ,
    ๋‚ด์šฉ์ด ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „์— ์—ฐ์‚ฐํ•œ ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

useCallback

  • useMemo๋Š” ํŠน์ • (์—ฐ์‚ฐ์˜) ๊ฒฐ๊ณผ ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•  ๋•Œ, useCallback์€ ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•  ๋•Œ ์“ด๋‹ค.
    useCallback์€ useMemo๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๋‹ค.
    (useMemo๋กœ ๋Œ€์ฒดํ•  ์ˆ˜๋„ ์žˆ๋‹ค.)

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

  • ํ•จ์ˆ˜ ์•ˆ์—์„œ ์‚ฌ์šฉ๋˜๋Š” props๋‚˜ ์ƒํƒœ๋Š” ๋ฐ˜๋“œ์‹œ deps ๋ฐฐ์—ด์— ํฌํ•จ์‹œ์ผœ์•ผ ํ•œ๋‹ค.

  • ํ•จ์ˆ˜ ์•ˆ์—์„œ state๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ, ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋ฉด setState์— ๋“ฑ๋กํ•˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ์ตœ์‹  state๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด deps์— state๋ฅผ ๋„ฃ์–ด์ฃผ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

React.Memo (์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ์ตœ์ ํ™” ์ž‘์—…)

  • React DevTools > ์„ค์ • > Highlight Updates : ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • React.Memo : ์ปดํฌ๋„ŒํŠธ์˜ props๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•ด ์ปดํฌ๋„ŒํŠธ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
    (๋ฆฌ๋ Œ๋”๋ง์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ๋งŒ ๋ฆฌ๋ Œ๋”๋งํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.)

  • ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ export ํ•  ๋•Œ, export default React.memo(component_name)์™€ ๊ฐ™์ด ๊ฐ์‹ธ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

  • React.memo์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ (propsAreEqualํ•จ์ˆ˜)๋ฅผ ์‚ฌ์šฉํ•ด ํŠน์ • props๋งŒ ๋น„๊ตํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์˜๋„์น˜ ์•Š์€ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

export default React.memo(
  UserList,
  (prevProps, nextProps) => prevProps.users === nextProps.users
);
  • useMemo, useCallback, React.memo๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์„ฑ๋Šฅ์„ ์‹ค์ œ๋กœ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š”(=์‹ค์ œ๋กœ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š”) ์ƒํ™ฉ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

useReducer

  • useReducer๋ฅผ ํ†ตํ•ด์„œ๋„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. useReducer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ๋ถ„๋ฆฌ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • useReducer vs useState
    ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ ๊ฐ’์ด ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋˜์–ด์„œ ๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ•ด์ง„๋‹ค๋ฉด (ex: ํ•œ ํ•จ์ˆ˜์—์„œ ์—ฌ๋Ÿฌ state์˜ setter๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ) useReducer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค.

์ปค์Šคํ…€ Hooks

  • ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ง์„ ๋ถ„๋ฆฌ์‹œ์ผœ ํ•„์š”ํ•  ๋•Œ ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• : useState, useEffect, useReducer, useCallback ๋“ฑ ๊ธฐ์กด Hooks๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฐ’๋“ค์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • useInputs ์ปค์Šคํ…€ Hook์„ useReducer๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๊ธฐ

Context API (์ „์—ญ ๊ฐ’ ๊ด€๋ฆฌ)

  • Context API๋ฅผ ์‚ฌ์šฉํ•ด ํ”„๋กœ์ ํŠธ์˜ ์ „์—ญ ๊ฐ’์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ƒํƒœ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•จ์ˆ˜, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธ์Šคํ„ด์Šค, DOM ๋“ฑ์„ ๋ชจ๋‘ ์ „์—ญ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • React.createContext() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด Context๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ๋Š” Context์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Context ๊ฐ์ฒด ์•ˆ์—๋Š” Provider๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋“ค์–ด์žˆ๋Š”๋ฐ, ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด Context์˜ ๊ฐ’์„ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

export const AuthContext = React.createContext(null);

<AuthContext.Provider value={dispatch}>
	...
</AuthContext.Provider>
// dispatch๋ฅผ Context ๊ฐ’์œผ๋กœ ์ •ํ•ด์ฃผ์–ด์„œ ์ „์—ญ์—์„œ dispatch๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

Context ์‚ฌ์šฉํ•˜๊ธฐ

import React, { useContext } from 'react';
import { AuthContext } from './App';

const User = () => {
	const dispatch = useContext(AuthContext);
    
    return (
    	<div onClick={() => {
        	dispatch({type: "TOGGLE", id: user.id})}} />
    );
};

์ด๋ ‡๊ฒŒ useReducer์™€ Context API๋ฅผ ๊ฐ™์ด ํ™œ์šฉํ•˜๋ฉด
Context API๋ฅผ ์‚ฌ์šฉํ•ด dispatch๋ฅผ ์–ด๋””์„œ๋“ ์ง€ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ ๊ตฌ์กฐ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์ง„๋‹ค.

Immer (๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

  • ๋ฆฌ์•กํŠธ์—์„œ ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋ ค๋ฉด, ๊ธฐ์กด ๋ฐฐ์—ด/๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๋ฐฐ์—ด/๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ค˜์•ผ ํ•œ๋‹ค.
    ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—์„œ๋Š” ์–ด๋ ต์ง€ ์•Š์ง€๋งŒ, ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ•ด์ง€๋ฉด ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋ฉด์„œ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด๋‚ด๋Š” ์ฝ”๋“œ๊ฐ€ ์กฐ๊ธˆ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • Immer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ๋ถˆ๋ณ€์„ฑ์„ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋„ Immer๊ฐ€ ๋ถˆ๋ณ€์„ฑ ๊ด€๋ฆฌ๋ฅผ ๋Œ€์‹  ํ•ด์ค€๋‹ค.

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ

  • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—๋Š” render() ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ผญ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    props๋ฅผ ์กฐํšŒํ•  ๋•Œ๋Š” this.props๋กœ ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค.
import React, { Component } from 'react';

class Hello extends Component {
	render() {
    	const { color, name, isSpecial } = this.props;
    }
}
  • defaultProps ์„ค์ •์€ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ํด๋ž˜์Šค ๋‚ด๋ถ€์— static ํ‚ค์›Œ๋“œ์™€ ํ•จ๊ป˜ ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
class Hello extends Component {
	static defaultProps = {
    	name: '์ด๋ฆ„์—†์Œ'
    };
 ...
}
 
Hello.defaultProps = {
	name: '์ด๋ฆ„์—†์Œ'
};
  • ์ปค์Šคํ…€ ๋ฉ”์„œ๋“œ ๋งŒ๋“ค๊ธฐ
class Counter extends Component {
	handleIncrease() {
    	console.log('increase');
    }
  
  	handleDecrease() {
    	console.log('decrease');
    }
    // ...
}

์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค ๋‚ด๋ถ€์— ์ข…์†๋œ ํ•จ์ˆ˜๋ฅผ ๋ฉ”์„œ๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ํด๋ž˜์Šค์—์„œ ์ปค์Šคํ…€ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค ๋•Œ๋Š” ๋ณดํ†ต ์ด๋ฆ„์„ handle..๋กœ ์ง“๋Š”๋‹ค.

  • ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ์—๋Š” this.setState๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    this๋Š” ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”๋ฐ, ์ปค์Šคํ…€ ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ this๋ฅผ ์กฐํšŒํ•ด๋ณด๋ฉด undefined๊ฐ€ ๋‚˜์˜จ๋‹ค.
    ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด constructor์—์„œ bind๋ฅผ ํ•ด์ฃผ๊ฑฐ๋‚˜, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
constructor(props) {
	super(props);
	this.handleIncrease = this.handleIncrease.bind(this);
  	this.handDecrease = this.handleDecrease.bind(this);
}

handleIncrease = () => {
	console.log('increase');
  	console.log(this);
};

handleDecrease = () => {
	console.log('decrease');
};

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” CRA๋กœ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์—๋Š” ์ ์šฉ์ด ๋˜์–ด ์žˆ๋Š” ๋ฌธ๋ฒ•(class-properties ๋ฌธ๋ฒ•)์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์ถ”๊ฐ€์ ์ธ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.

  • ์ƒํƒœ ์„ ์–ธํ•˜๊ธฐ :
    ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ์„ ์–ธํ•  ๋•Œ๋Š” constructor ๋‚ด๋ถ€์—์„œ this.state๋ฅผ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
constructor(props) {
	super(props);
  	this.state = {
    	counter: 0
    };
}

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ state๋Š” ๋ฌด์กฐ๊ฑด ๊ฐ์ฒดํ˜•ํƒœ์—ฌ์•ผ ํ•œ๋‹ค.

class-properties ๋ฌธ๋ฒ•์ด ์ ์šฉ๋˜์–ด ์žˆ๋‹ค๋ฉด(ex. CRA๋กœ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ) constructor๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด state๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Counter extends Component {
	state = {
    	counter: 0
    };
  • ์ƒํƒœ ์—…๋ฐ์ดํŠธ :
    • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ state์—์„œ๋„ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ฉฐ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.
    • setState์—์„œ๋„ useState์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
      ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋Š” ๋ณดํ†ต ํ•œ ํ•จ์ˆ˜์—์„œ setState๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ์— ๊ฑธ์ณ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•˜๋‹ค.
      setState๋Š” ๋‹จ์ˆœํžˆ ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ, ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ”๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์„ฑ๋Šฅ ์ƒ์˜ ์ด์œ ๋กœ ์ƒํƒœ๊ฐ€ ๋ฐ”๋กœ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๊ณ  ๋น„๋™๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งŒ์•ฝ ์ƒํƒœ ์—…๋ฐ์ดํŠธ ํ›„์— ์–ด๋–ค ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, setState์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๊ฑฐ๋‚˜, ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

LifeCycle Method (์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ)

  • LifeCycle Method : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์ƒ์— ๋‚˜ํƒ€๋‚˜๊ณ , ์—…๋ฐ์ดํŠธ๋˜๊ณ , ์‚ฌ๋ผ์งˆ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋“ค (+์ปดํฌ๋„ŒํŠธ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋„ ์žˆ์Œ)
    LifeCycle ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋งˆ์šดํŠธ :

    • constructor : ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ์‹œ ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ. ์ƒ์„ฑ์ž ๋ฉ”์„œ๋“œ
    • getDerivedStateFromProps : props๋กœ ๋ฐ›์•„์˜จ ๊ฐ’์„ state์— ๋„ฃ์–ด์ฃผ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ
    • render : ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฉ”์„œ๋“œ
    • componentDidMount : ์ปดํฌ๋„ŒํŠธ์˜ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง ์ข…๋ฃŒ ํ›„์— ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ. ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์—๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚œ ์ƒํƒœ์ด๋‹ค.
      ์ฃผ๋กœ DOM์„ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ฐ๋™์ด๋‚˜, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์š”์ฒญ์„ ์œ„ํ•œ axios, fetch ๋“ฑ ajax ์š”์ฒญ, ๋˜๋Š” DOM์˜ ์†์„ฑ์„ ์ฝ๊ฑฐ๋‚˜ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ์ž‘์—…์„ ํ•œ๋‹ค.
  • ์—…๋ฐ์ดํŠธ :

    • getDerivedStateFromProps : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ปดํฌ๋„ŒํŠธ์˜ props๋‚˜ state๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋„ ํ˜ธ์ถœ๋œ๋‹ค.
    • shouldComponentUpdate : ์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ๋ Œ๋”๋ง ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ. ์ฃผ๋กœ ์ตœ์ ํ™”ํ•  ๋•Œ ์‚ฌ์šฉ
    • render
    • getSnapshotBeforeUpdate : ์ปดํฌ๋„ŒํŠธ์— ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜๊ธฐ ์ง์ „ DOM ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์™€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ. ๋‹ค์Œ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” componentDidUpdate์—์„œ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
      (DOM์— ๋ณ€ํ™”๊ฐ€ ๋ฐ˜์˜๋˜๊ธฐ ์ง์ „์— DOM ์†์„ฑ์„ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ)
    • componentDidUpdate : ๋ฆฌ๋ Œ๋”๋ง์ด ๋๋‚˜๊ณ  ํ™”๋ฉด์— ๋ณ€ํ™”๊ฐ€ ๋ชจ๋‘ ๋ฐ˜์˜๋œ ํ›„ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ. getSanpshotBeforeUpdate์—์„œ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์–ธ๋งˆ์šดํŠธ :

    • componentWillUnmount : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋œ๋‹ค.
      ์ฃผ๋กœ DOM์— ๋“ฑ๋กํ–ˆ๋˜ ์ด๋ฒคํŠธ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , setTimeout ๋“ฑ์„ clearํ•˜๊ฑฐ๋‚˜, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. (= ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— dispose ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ)

์—๋Ÿฌ ํ•ธ๋“ค๋ง

  • props ์„ค์ •์ด ์ œ๋Œ€๋กœ ๋˜์ง€ ์•Š์•„ null/undefined ๊ฐ’์ด ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ (null๊ฐ’ ์ฐธ์กฐ)๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ๋ฐœ์ƒํ•œ๋‹ค.
function User({ user }) {
	if (!user) {
    	return null;
    }
  	// ...
} 
  • ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ํ†ตํ•˜์—ฌ ๋‚˜์ค‘์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๊ฒŒ ๋˜๋Š” ์ƒํ™ฉ์—์„œ๋Š”
    ์ด๋ ‡๊ฒŒ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด null์„ ๋ณด์—ฌ์ฃผ๊ฑฐ๋‚˜, ์•„๋‹ˆ๋ฉด <div>๋กœ๋”ฉ์ค‘</div>๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฌผ์„ ๋ Œ๋”๋งํ•˜๋ฉด ๋œ๋‹ค.

  • props๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ์˜ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด defaultProps ์„ค์ •์„ ํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.

Users.defaultProps = {
	onToggle: () => {
    	console.warn('onToggle is missing!');
    }
};
  • ๋˜๋Š” ์‹ค์ˆ˜๋กœ props ์ „๋‹ฌ์„ ๊นœ๋นกํ–ˆ์„ ๋•Œ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ ๊ฒฝ๊ณ ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก PropTypes๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ TypeScript, Flow๋ฅผ ์‚ฌ์šฉํ•ด ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

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

componentDidCatch(error, info) {
	console.log('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.');
  	console.log({
    	error,
      	info
    });
  	this.setState({
    	error: true
    });
  	if (process.env.NODE_ENV === 'production') {
       Sentry.captureException(error, { extra: info });
    }
}

process.env.NODE_ENV ๊ฐ’์„ ์กฐํšŒํ•ด ํ˜„์žฌ ํ™˜๊ฒฝ(๊ฐœ๋ฐœ ํ™˜๊ฒฝ/๋ฐฐํฌ ํ™˜๊ฒฝ)์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
Sentry์™€ ์—ฐ๋™์„ ํ•ด๋‘๋ฉด ๋ฒ„๊ทธ ๊ด€๋ฆฌ์— ๋งค์šฐ ๋„์›€์ด ๋˜๋ฏ€๋กœ ์—ฐ๋™ํ•ด๋‘๋Š” ๊ฒƒ์„ ์ถ”์ฒœ!

๋ฒจ๋กœํผํŠธ์™€ ํ•จ๊ป˜ํ•˜๋Š” ๋ชจ๋˜ ๋ฆฌ์•กํŠธ(https://react.vlpt.us)๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

profile
Good things take time

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