Back
Featured image of post ReactλŠ” μ™œ μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ„ 지ν–₯ν• κΉŒ?

ReactλŠ” μ™œ μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ„ 지ν–₯ν• κΉŒ?

πŸ’„Β UI μƒνƒœ κ΄€λ¦¬μ—μ„œ μ‚΄νŽ΄λ³΄λŠ” μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ μž₯점에 λŒ€ν•΄μ„œ μ†Œκ°œν•©λ‹ˆλ‹€.

κ°œμš”

Declarative React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.

Reactμ—μ„œλŠ” Reactλ₯Ό 선언적이라고 잘 μ„€λͺ…ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. “μ„ μ–Έν˜• λ·°λŠ” μ½”λ“œλ₯Ό 예츑 κ°€λŠ₯ν•˜κ³ , 디버깅을 μ‰½κ²Œ λ§Œλ“ λ‹€” 라고 μ„€λͺ…ν•˜κ³  있으며, Reactκ°€ μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ νŒ¨λŸ¬λ‹€μž„μ„ 지ν–₯ν•˜λŠ” μ΄μœ μ™€ νŠΉμ§•μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°

μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ„ μ•ŒκΈ° μœ„ν•΄ κΈ°μ‘΄ λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ νŠΉμ§•μ„ κ°„λž΅ν•˜κ²Œ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°(Imperative Programming)은 λͺ…λ Ήμ–΄λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜μ—¬ ν”„λ‘œκ·Έλž¨ λ™μž‘ μƒνƒœλ₯Ό λ³€κ²½ μ‹œν‚€λŠ” ν”„λ‘œκ·Έλž˜λ° 방식 μž…λ‹ˆλ‹€. ν”„λ‘œκ·Έλž¨μ˜ λ™μž‘μ˜ 흐름에 쀑점을 λ‘λŠ” νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€.

//DOM에 λ…ΈμΆœμ‹œν‚¬ 리슀트 λ³€μˆ˜λ₯Ό μƒμ„±ν•œλ‹€.
const list = ['foo', 'bar'];

//ν•˜μœ„ li μš”μ†Œλ₯Ό μΆ”κ°€μ‹œν‚€κΈ° μœ„ν•œ ul μš”μ†Œλ₯Ό μƒμ„±ν•œλ‹€.
const $ul = document.createElement('ul');

//list의 길이 만큼 μˆœνšŒν•˜λ©° listItem μš”μ†Œλ₯Ό 생성
for (let index = 0; index < list.length; index++) {
  const item = document.createTextNode(list[index]);
  const $listItem = document.createElement('li');

  $listItem.appendChild(item);
  $ul.appendChild($listItem);
}

//html body에 λ Œλ”λ§
document.body.appendChild($ul);

μœ„μ˜ μ˜ˆμ‹œ μ½”λ“œλŠ” λͺ…λ Ήν˜• λ°©μ‹μ˜ 리슀트λ₯Ό λ Œλ”λ§ν•΄μ£ΌλŠ” μ½”λ“œ μž…λ‹ˆλ‹€. λͺ…λ Ήν˜• μ½”λ“œμ˜ νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • λ³„λ„μ˜ λͺ¨λ“ˆ 뢄리 없이 연속적인 계산 κ³Όμ •μœΌλ‘œ 이루어져 μžˆμ–΄ μ‹€ν–‰ 속도가 λΉ λ¦…λ‹ˆλ‹€.
  • 세뢀적인 λ™μž‘ 사항이 λͺ…λ Ήλ¬Έμ˜ μ—°μ†μœΌλ‘œ κ΅¬μ„±λ˜μ–΄ 있기 λ•Œλ¬Έμ—, λ³΅μž‘λ„κ°€ 증가할 수둝 μ΄ν•΄ν•˜λŠ” 데 μ‹œκ°„κ³Ό λΉ„μš©μ΄ μƒλŒ€μ μœΌλ‘œ 더 많이 λ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • κΈ°λŠ₯을 λ³€κ²½ν•  λ•Œ λ³€μˆ˜ κ°’ ν• λ‹Ή/μˆ˜μ •μ΄ λΆˆκ°€ν”Όν•˜κ²Œ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ—, μ‹€ν–‰ 흐름과 λΆ€μˆ˜ 효과(Side Effect)에 영ν–₯을 λ―ΈμΉ  수 μžˆμŠ΅λ‹ˆλ‹€.

μš”μ•½ν•˜μžλ©΄, κ°„λ‹¨ν•˜κ³  λ‹¨μˆœ 계산 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—λŠ” λΉ λ₯Έ μ‹€ν–‰κ³Ό κ°€λ…μ„±μœΌλ‘œ μΈν•œ μž₯점이 μžˆμ§€λ§Œ, λ³΅μž‘ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μΌ 수둝 관리가 μ–΄λ ΅λ‹€λŠ” νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€.

μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°

이제 μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ νŠΉμ§•μ„ λ§μ”€λ“œλ¦¬λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€. μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ€ 좔상화 계측과 μ œμ–΄ 흐름을 λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜μ§€ μ•Šκ³ , ν”„λ‘œκ·Έλž¨μ΄ μˆ˜ν–‰ν•˜λŠ” μž‘μ—…μ„ μ„€λͺ…ν•˜λŠ” 데 쀑점을 λ‘” νŒ¨λŸ¬λ‹€μž„ μž…λ‹ˆλ‹€. JavaScriptμ—μ„œλŠ” λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ μž‘μ„±λœ μ½”λ“œλ₯Ό 좔상화λ₯Ό 톡해 μ„ μ–Έν˜• μ½”λ“œλ‘œ λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. (닀쀑 νŒ¨λŸ¬λ‹€μž„ μ–Έμ–΄)

좔상화λ₯Ό ν†΅ν•œ μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°

//DOM에 λ…ΈμΆœμ‹œν‚¬ 리슀트 λ³€μˆ˜λ₯Ό μƒμ„±ν•œλ‹€.
const list = ['foo', 'bar'];

//μš”μ†Œλ₯Ό μƒμ„±ν•œλ‹€.
const createElement = (element) => {
  return document.createElement(element);
};

//list의 길이 만큼 μˆœνšŒν•˜λ©° listItem μš”μ†Œλ₯Ό 생성
const createListItem = (list) => {
  const $ul = createElement('ul');
  list.forEach((item) => {
    const $item = createElement('li');
    $item.appendChild(document.createTextNode(item));
    $ul.appendChild($item);
  });
  return $ul;
};

//λ Œλ”λ§ν•œλ‹€.
const render = (element, attachElement) => {
  return attachElement.appendChild(element);
};

render(createListItem(list), document.body);

μœ„μ— μž‘μ„±ν–ˆλ˜ μ½”λ“œλ₯Ό μ„ μ–Έν˜• μ½”λ“œλ‘œ μž¬κ΅¬μ„±ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. λ³„λ„μ˜ ν•¨μˆ˜λ‘œ λΆ„λ¦¬ν•˜μ—¬ 좔상화λ₯Ό ν•˜μ˜€μœΌλ©°, μ΄λŠ” 곧 μž¬μ‚¬μš©μ„±μ΄ μ¦κ°€ν•œλ‹€λŠ” νŠΉμ§•μ„ κ°–κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ νŠΉμ§•μ€ 좔상화 레벨이 λ†’μ„μˆ˜λ‘, μ‚¬μš©ν•˜λŠ” μž…μž₯μ—μ„œλŠ” λ‚΄λΆ€λ₯Ό 신경쓰지 μ•Šμ•„λ„ λ©λ‹ˆλ‹€.

높은 레벨의 좔상화

//render
const render = (initialState, createElement) => {
  const renderToApp = (element) => {
    const $app = document.getElementById("app");
    $app.innerHTML = element;
  };

//setStateν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” μˆœκ°„ renderToApp 호좜
  const setState = (state) => {
    renderToApp(createElement(state, setState));
  };

  setState(initialState);
};

//render 호좜
render({ list: ["foo", "bar"] }, (state, setState) => {
    setState({ list: [...state.list, "jiny"] });
    return `<ul>
        ${state.list.map((item) => {
          return `<li>${item}</li>`;
        })}
    </ul>`;
  });
});
  • 좔상화 레벨이 λ†’μ„μˆ˜λ‘, ν˜ΈμΆœν•˜λŠ” λΆ€λΆ„μ—μ„œ ꡬ체적인 λ™μž‘μ— λŒ€ν•œ 정보λ₯Ό μ•Œ ν•„μš”κ°€ μ—†μ–΄μ§‘λ‹ˆλ‹€. (가독성과 이해도 ν–₯상)
  • μΆ”μƒν™”λœ ν•¨μˆ˜λ₯Ό μž¬μ‚¬μš©ν•¨μœΌλ‘œμ¨ 선언적인 μ½”λ“œλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν•¨μˆ˜ 호좜 λ°©μ‹μœΌλ‘œ 인해 λ©”λͺ¨λ¦¬ ν• λ‹ΉλŸ‰μ΄ μ¦κ°€ν•˜λŠ” 단점은 μžˆμŠ΅λ‹ˆλ‹€.

React와 μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°

이제 μœ„ λͺ…λ Ήν˜•κ³Ό μ„ μ–Έν˜• νŒ¨λŸ¬λ‹€μž„μ„ μ΄ν•΄ν•˜κ³ , Reactμ—μ„œ μ„€λͺ…ν•˜κ³  μžˆλŠ” μ„ μ–Έν˜•μ˜ μž₯점을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. Reactμ—μ„œλŠ” μ‚¬μš©μžκ°€ UIλ₯Ό 상황에 따라 μ–΄λ–»κ²Œ ν‘œν˜„ν• μ§€ μ„ μ–Έλ§Œ ν•˜λ©΄ 되며, 선언적인 μ½”λ“œλ‘œ μž‘μ„±λ˜μ–΄ μžˆμ–΄ UI μ—…λ°μ΄νŠΈλŠ” React λ‚΄λΆ€μ—μ„œ μ²˜λ¦¬λ©λ‹ˆλ‹€. λ§Œμ•½μ— 이 방식을 λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ μž‘μ„±ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

/** κ°„λ‹¨ν•œ ν…μŠ€νŠΈ 폼을 μ œμΆœν•˜λŠ” UI */

const loadingMessage = 'λ‘œλ”©μ€‘μž…λ‹ˆλ‹€..';
const successMessage = 'μ œμΆœμ„ μ„±κ³΅ν•˜μ˜€μŠ΅λ‹ˆλ‹€.';
const $form = document.getElementById('form');
const $textarea = document.getElementById('textarea');
let $status = document.getElementById('status');

//display μƒνƒœ 관리
const setHideElement = (element, state) => {
  element.style.display = state ? 'none' : '';
};

//text μƒνƒœ 관리
const setStatusElementText = (element, state) => {
  element.textContent = state;
};

//network 상황을 κ°€μ •ν•œ form 제좜
const fetchForm = (formText) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (formText.length) {
        resolve();
        return;
      }
      reject(new Error('Form text is empty'));
    }, 2000);
  });
};

//submit event
const handleSubmit = async (e) => {
  e.preventDefault();
  setHideElement($status, false);
  try {
    await fetchForm($textarea.value);
    setStatusElementText($status, `${successMessage} λ‚΄μš©: ${$textarea.value}`);
  } catch (error) {
    setStatusElementText($status, error.message);
  }
};

$form.onsubmit = handleSubmit;

μ΄λ ‡κ²Œ UI μƒνƒœλ₯Ό ν‘œν˜„ν•˜λŠ” 것도 이미 μ½”λ“œκ°€ λ³΅μž‘ν•œλ°, 더 λ³΅μž‘ν•œ UI일수둝 μƒνƒœ 별 ν‘œν˜„ν•΄μ•Όν•˜λŠ” 관리 μ†ŒμŠ€λŠ” λ”μš± λ³΅μž‘ν•΄μ§€κ²Œλ©λ‹ˆλ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄, Reactμ—μ„œλŠ” μ—¬λŸ¬ 경우의 ν•˜λ‚˜μ˜ μƒνƒœλ‘œ λ‘λ©΄μ„œ 데이터 흐름을 단방ν–₯ μ»΄ν¬λ„ŒνŠΈλ‘œ 흐λ₯΄κ²Œ ν•˜μ˜€μŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ νŒ¨ν„΄μ„ Single Source of Truth라고 ν•©λ‹ˆλ‹€.

  • 각각의 UI별 μƒνƒœλ₯Ό λͺ…λ Ήν˜• μ½”λ“œλ‘œ κ΅¬μ„±ν–ˆμ„ λ•Œ μƒνƒœ 관계와 μ°Έμ‘°ν•˜λŠ” DOM Tree κ΅¬μ‘°λŠ” λ³΅μž‘ν•΄μ Έ κ΄€λ¦¬ν•˜κΈ° μ–΄λ €μ›Œμ§‘λ‹ˆλ‹€.
  • μƒˆλ‘œμš΄ UI μš”μ†Œλ‚˜ μƒν˜Έμž‘μš©μ„ μœ„ν•œ 이벀트λ₯Ό μˆ˜μ •ν•˜κ±°λ‚˜ μΆ”κ°€ν•˜λ €λ©΄ κΈ°μ‘΄ μƒν˜Έμž‘μš©μ΄ 잘 μ΄λ£¨μ–΄μ ΈμžˆλŠ”μ§€ μ„Έλ°€ν•œ 디버깅이 ν•„μš”λ‘œν•˜κ²Œλ©λ‹ˆλ‹€.

Reactκ°€ μ œμ‹œν•œ 선언적 UI μ œμ–΄

prop을 ν™œμš©ν•œ μ‹œκ° μƒνƒœ 식별

μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚¬μš©ν•˜λ©΄ props을 톡해 λ‹€μ–‘ν•œ UI μƒνƒœλ₯Ό 식별할 수 μžˆμŠ΅λ‹ˆλ‹€. Reactμ—μ„œλŠ” 이미 높은 좔상화 μˆ˜μ€€μ„ λ‹¬μ„±ν–ˆκΈ° λ•Œλ¬Έμ—, μ‚¬μš©μžλŠ” JSX 문법을 톡해 UI μƒνƒœλ₯Ό μ œμ–΄ν•˜κΈ° μœ„ν•œ 속성 κ°’κ³Ό μƒνƒœλ³„λ‘œ μ–΄λ–»κ²Œ ν‘œν˜„ν• μ§€ μž‘μ„±ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

export default Form = ({ status = 'empty' }) => {
  if (status === 'success') {
    return <h1>이미 폼을 μ œμΆœν•˜μ˜€μŠ΅λ‹ˆλ‹€.</h1>;
  }
  return (
    <>
      <h2>Form</h2>
      <form>
        <textarea disabled={status === 'submitting'} />
        <br />
        <button disabled={status === 'empty' || status === 'submitting'}>Submit</button>
        {status === 'error' && <p className="Error">μ—λŸ¬κ°€ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.</p>}
      </form>
    </>
  );
};

μœ„μ˜ μ»΄ν¬λ„ŒνŠΈ μ½”λ“œλŠ” λ‚΄λΆ€μ μœΌλ‘œ μ•„λž˜μ™€ 같이 λ³€ν™˜μ΄ λ©λ‹ˆλ‹€.

const Form = ({ status = 'empty' }) => {
  if (status === 'success') {
    return React.createElement('h1', null, '이미 폼을 μ œμΆœν•˜μ˜€μŠ΅λ‹ˆλ‹€.');
  }
  return React.createElement(
    React.Fragment,
    null,
    React.createElement('h2', null, 'Form'),
    React.createElement(
      'form',
      null,
      React.createElement('textarea', { disabled: status === 'submitting' }),
      React.createElement('br'),
      React.createElement('button', { disabled: status === 'empty' || status === 'submitting' }, 'Submit'),
      status === 'error' && React.createElement('p', { className: 'Error' }, 'μ—λŸ¬κ°€ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.')
    )
  );
};

export default Form;

선언적인 hook을 ν†΅ν•œ μƒνƒœ μ œμ–΄

Reactμ—μ„œλŠ” hook을 ν†΅ν•΄μ„œ μ»΄ν¬λ„ŒνŠΈ κ°„ μƒνƒœλ“€μ„ κ³΅μœ ν•˜κ³ , μƒνƒœ μ œμ–΄λ₯Ό ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 뢀뢄이 μ–΄λ–»κ²Œ μ„ μ–Έν˜•μœΌλ‘œ μ΄λ£¨μ–΄μ ΈμžˆλŠ”μ§€ μ‚΄νŽ΄λ³΄λ„λ‘ν•˜κ² μŠ΅λ‹ˆλ‹€.
ui-state μš°μ„  μƒνƒœ κ΄€λ¦¬λŠ” μ™œ ν•„μš”ν• κΉŒμš”? μ›Ήμ—μ„œλŠ” μƒνƒœ λ³€ν™”κ°€ λ°œμƒν•˜λŠ” 상황은 크게 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • μš”μ†Œ 클릭, form 제좜 λ“± μ‚¬μš©μž ν–‰μœ„μ— μ˜ν•œ UI μƒνƒœ λ³€ν™”
  • HTTP μš”μ²­ 및 응닡과 같은 μ»΄ν“¨νŒ… μš”μ†Œμ— μ˜ν•œ UI μƒνƒœ λ³€ν™”

이와 같이 μ»΄ν¬λ„ŒνŠΈ 별 λ°œμƒν•˜λŠ” μ—¬λŸ¬ μƒνƒœ λ³€ν™”λ₯Ό Reactμ—μ„œλŠ” hook을 톡해 μƒνƒœ λ³€μˆ˜λ₯Ό μœ μ§€μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. useStateλ₯Ό 톡해 μƒνƒœ μ œμ–΄λ₯Ό μ„ μ–Έν•  수 있으며, useEffectλ₯Ό 톡해 React 생λͺ…μ£ΌκΈ°μ—μ„œ μΌμ–΄λ‚˜λŠ” μƒνƒœ 변화도 감지할 수 μžˆμŠ΅λ‹ˆλ‹€.

const [inputContent, setInputContent] = useState('');
const [error, setError] = useState(null);

hook의 νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜ λ‚΄μ—μ„œ λ Œλ”λ§ κ°„ μƒνƒœλ₯Ό μœ μ§€μ‹œν‚€κ³  λ³΄κ΄€ν•œλ‹€.
각 μƒνƒœ λ³€μˆ˜μ˜ μΈμŠ€ν„΄μŠ€λŠ” κ³ λ¦½λ˜μ–΄ μžˆμœΌλ―€λ‘œ, 각 μ»΄ν¬λ„ŒνŠΈμ—μ„œ μƒνƒœ λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  μ—¬λŸ¬ 번 ν˜ΈμΆœν•˜μ—¬ μƒνƒœλ₯Ό λ³€κ²½ν•˜λ”λΌλ„ λ‹€λ₯Έ μ»΄ν¬λ„ŒνŠΈμ—κ²Œ 영ν–₯을 주지 μ•ŠμŠ΅λ‹ˆλ‹€.

μƒνƒœ μ„€μ • ν•¨μˆ˜λ₯Ό 톡해 λ³€μˆ˜ μ—…λ°μ΄νŠΈμ™€ μ»΄ν¬λ„ŒνŠΈ λ¦¬λ Œλ”λ§μ„ λ°œμƒ
Reactμ—μ„œλŠ” hook 호좜 κ·œμΉ™μ„ 톡해 μƒνƒœλ₯Ό μ²΄κ³„μ μœΌλ‘œ κ΄€λ¦¬ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λ©”λͺ¨λ¦¬μ™€ hook의 연관성을 μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ‚¬μš©μžλŠ” Reactμ—μ„œ 제곡된 hook을 μ‚¬μš©ν•˜κΈ°λ§Œν•˜λ©΄ λ©λ‹ˆλ‹€. λ¬Όλ‘ , React λ‚΄λΆ€μ—μ„œλŠ” μ•„λž˜μ™€ 같이 μƒνƒœ 감지λ₯Ό μœ„ν•΄ useState ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•΄λ†“μ•˜μŠ΅λ‹ˆλ‹€.

//react@16.13.1/
function useState(initialState) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}

//react-dom@16.13.1
function mountState(initialState) {
  var hook = mountWorkInProgressHook();

  if (typeof initialState === 'function') {
    // $FlowFixMe: Flow doesn't like mixed types
    initialState = initialState();
  }

  hook.memoizedState = hook.baseState = initialState;
  var queue = (hook.queue = {
    pending: null,
    dispatch: null,
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: initialState
  });
  var dispatch = (queue.dispatch = dispatchAction.bind(null, currentlyRenderingFiber$1, queue));
  return [hook.memoizedState, dispatch];
}

resolveDispatch() ν•¨μˆ˜λŠ” ν˜„μž¬ λ Œλ”λ§ 쀑인 μ»΄ν¬λ„ŒνŠΈμ— λŒ€ν•œ λ‚΄λΆ€ μ°Έμ‘°λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 이 ν•¨μˆ˜λ₯Ό 톡해 μ»΄ν¬λ„ŒνŠΈκ°€ 마운트될 λ•Œ mountState ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , λ Œλ”λ§λ  λ•Œ updateState ν•¨μˆ˜λ₯Ό 톡해 μƒνƒœλ₯Ό λ³€κ²½μ‹œν‚΅λ‹ˆλ‹€.

μ€‘μš”ν•œ 것은 λͺ¨λ‘ λ‚΄λΆ€μ μœΌλ‘œ μΌμ–΄λ‚˜κ³  μžˆλŠ” 일이기 λ•Œλ¬Έμ— λͺ¨λ“  과정을 μ•Œ ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 높은 레벨의 좔상화λ₯Ό ν†΅ν•œ 선언적 μ½”λ“œλ₯Ό 이루고 있기 λ•Œλ¬Έμ— κ°œλ°œμžλŠ” μΈν„°νŽ˜μ΄μŠ€ κ·œμΉ™μ— 맞좰 νŽΈν•˜κ²Œ μ‚¬μš©λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

Reactκ°€ μ„ μ–Έμ μž„μœΌλ‘œμ¨ μ–»κ²Œλœ μž₯점듀

가독성과 μœ μ§€λ³΄μˆ˜μ„±

κ°œλ°œμžλŠ” μ›ν•˜λŠ” UI의 μ΅œμ’… μƒνƒœλ₯Ό μ„ μ–Έμ μœΌλ‘œ μž‘μ„±ν•˜κ³ , ReactλŠ” λ‚΄λΆ€μ μœΌλ‘œ ν•΄μ„ν•˜μ—¬ UIλ₯Ό μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ½”λ“œμ˜ μ˜λ„ νŒŒμ•…μ΄ μ‰¬μ›Œμ§€λ©°, λ³€κ²½ 사항에 λŒ€ν•œ μˆ˜μ •μ΄ μš©μ΄ν•΄μ Έ μœ μ§€ λ³΄μˆ˜μ„±μ΄ ν–₯μƒλ©λ‹ˆλ‹€.

μž¬μ‚¬μš©μ„±

선언적인 μ½”λ“œλŠ” 독립적인 μ»΄ν¬λ„ŒνŠΈλ‘œ κ΅¬μ„±λ˜μ–΄ 있으며, μƒνƒœκ°€ λ³€κ²½λ˜μ–΄ μžˆλ”λΌλ„ 고립된 μΈμŠ€ν„΄μŠ€ hook을 톡해 λ‹€λ₯Έ λΆ€λΆ„μ—μ„œ μž¬μ‚¬μš©ν•˜λŠ” 데 λ¬Έμ œκ°€ μ—†μŠ΅λ‹ˆλ‹€.

효율적인 관리

ReactλŠ” 선언적 APIλ₯Ό μ œκ³΅ν•˜κΈ° λ•Œλ¬Έμ— μ—…λ°μ΄νŠΈν•  λ•Œλ§ˆλ‹€ 무엇이 λ³€κ²½λ˜λŠ”μ§€μ— λŒ€ν•΄ μ‹ κ²½ μ“Έ ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. reconciliation 과정을 톡해 자체적인 diff μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ μ„œλ‘œ λ‹€λ₯Έ 트리λ₯Ό λΉ„κ΅ν•˜κ³  κ°±μ‹ ν•©λ‹ˆλ‹€.

참고 자료