1.JSX

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

JSX ์—†์ด React ๋งŒ๋“ค๊ธฐ

main.ts

import React from 'react';
import ReactDOM from 'react-dom/client';

import App from './App';

function main() {
  const container = document.getElementById('root');
  if (!container) {
    return;
  }

  const root = ReactDOM.createRoot(container);
  root.render(React.createElement(App, null));
}

main();

App.ts

import React, { useState } from 'react';

import Greeting from './components/Greeting';

type ImageProps = {
  src: string;
  alt?: string;
  width?: number;
}

function Image({ src, alt = '', width }: ImageProps) {
  return (
    React.createElement('img', { src, alt, width: width ?? 'auto' })
  );
}

export default function App() {
  const [count, setCount] = useState(0);

  const handleClick = (value: number) => {
    setCount(count + value);
  };

  return (
    React.createElement(
      'div',
      null,
      React.createElement(Greeting, { name: 'wholeman!' }),
      React.createElement(Image,
      {
        src: '/images/test.jpg',
        alt: 'Test Image',
        width: 200
      }),
      React.createElement('p', null, 'Count: ', count),
      [1, 2, 3, 4, 5].map((i) => React.createElement('button',
      { type: 'button', key: i, onClick: () => handleClick(i) },
      '+',
      i)),
    )
  );
}

components/Greeting.ts

import React from 'react';

export default function Greeting({ name }: {
  name: string;
}) {
  return (
    React.createElement('p', null, 'Hello, ', name)
  );
}

React์—์„œ JSX๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์ 

๊ทผ๋ณธ์ ์œผ๋กœ, JSX๋Š” React.createElement(component, props, ...children) ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๋ฌธ๋ฒ•์  ์„คํƒ•์„ ์ œ๊ณตํ•  ๋ฟ์ด๋‹ค.

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

๋‘ ์˜ˆ์‹œ๋Š” ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด์ค€๋‹ค.

ํ•˜์ง€๋งŒ React.createElement๋กœ ์ž‘์„ฑํ•˜์˜€์„ ๋•Œ ๋ณด๋‹ค JSX๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์ง๊ด€์ ์ด๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹๊ณ  JSX๋Š” ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ HTML์„ ๋™์‹œ์— ์ž‘์„ฑ ํ•  ์ˆ˜ ์žˆ๋Š” ์ ์ด ์žฅ์ ์ด๋‹ค.

Syntactic sugar

์ง๊ด€์ ์ด์ง€๋Š” ์•Š์ง€๋งŒ ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ฌธ๋ฒ•์ ์ธ ์„คํƒ•์„ ์˜๋ฏธํ•œ๋‹ค.

๋Œ€ํ‘œ์ ์ธ Syntactic sugar

1. Ternary Operator(์‚ผํ•ญ ์—ฐ์‚ฐ์ž)

  ์‚ผํ•ญ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ ์ „

  setProviderList(prev => prev.map(item => (
    if (item.id === search.provider) {
      return { ...item, isChecked: !item.isChecked }
    } else {
      return item
    }
  )));


  ์‚ผํ•ญ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ ํ›„

  setProviderList(prev => prev.map(item => (
    item.id === search.provider ? { ...item, isChecked: !item.isChecked } : item
  )));

  ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์‚ฌ์šฉ ์ „๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

2. Object Spread / Array Spread (๊ฐ์ฒด ์ „๊ฐœ / ๋ฐฐ์—ด ์ „๊ฐœ)

  setProviderList(prev => prev.map(item => (
    item.id === search.provider ? { ...item, isChecked: !item.isChecked } : item
  )));

  ์œ„์˜ map ์•ˆ์—์„œ ๊ฐ์ฒด์˜ ์ผ๋ถ€๋ถ„์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ { ...item, isChecked: !item.isChecked }
  ์™€ ๊ฐ™์ด ๊ธฐ์กด์˜ ๊ฐ์ฒด์•ˆ์˜ ๊ฐ’์„ ์ „๊ฐœํ•˜๊ณ  ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ’์„ ๋ณ€๊ฒฝํ•œ๋‹ค.

  const DEFAULT_CONFIG = {
    preserveWhitespace: true,
    noBreaks: false,
    foo: "bar",
  };

  const USER_CONFIG = {
    noBreaks: true,
  }

  const config = { ...DEFAULT_CONFIG, ...USER_CONFIG };

  ์œ„์™€ ๊ฐ™์ด ๋‘ ๊ฐ์ฒด๋ฅผ ๋ชจ๋‘ ์ „๊ฐœํ•ด์„œ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด๋•Œ ๊ฐ™์€ key ๊ฐ’์— value๊ฐ€
  ๋‹ค๋ฅผ ๊ฒฝ์šฐ ๋’ค์— ๋“ค์–ด์˜ค๋Š” ๊ฐ์ฒด์˜ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

  ๋ฐฐ์—ด๋„ ๊ฐ์ฒด์˜ ์˜ˆ์ œ์™€ ๋™์ผํ•˜๊ฒŒ ์ „๊ฐœ ํ›„ ํ•˜๋‚˜์˜ ๋ฐฐ์—ด๋กœ ๋ณ‘ํ•ฉํ•˜๋Š”๊ฒŒ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋‹ค๋งŒ ๋ฐฐ์—ด์˜ ๊ฒฝ์šฐ๋Š” key๊ฐ€ ์—†๊ธฐ
  ๋•Œ๋ฌธ์— ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฐฐ์—ด์„ ์ „๊ฐœํ•ด์„œ ๋ณ‘ํ•ฉ ํ•  ๋•Œ ์ค‘๋ณต๋˜๋Š” ๊ฐ’๋„ ๋ชจ๋‘ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

  const arr1 = ['a', 'b', 'c'];
  const arr2 = ['c', 'd', 'e'];
  const arr3 = [...arr1, ...arr2];
  // console.log(arr3) => ['a', 'b', 'c', 'c', 'd', 'e']

3. Object Destructuring / Array Destructuring (๊ฐ์ฒด ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น / ๋ฐฐ์—ด ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น)

  export default function LectureBody({ classroomLecture }: Props): ReactElement {

    const {
      moduleList, classroomId, lastSectionId, lastSectionType,
    } = classroomLecture;
  ...
  }

  ์ปดํฌ๋„ŒํŠธ props๋กœ ์ „๋‹ฌ๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๊ตฌ์กฐ ๋ถ„ํ•ดํ•˜์—ฌ ํ•„์š”ํ•œ ๊ฐ’๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  // ์ด๋ฆ„๊ณผ ์„ฑ์„ ์š”์†Œ๋กœ ๊ฐ€์ง„ ๋ฐฐ์—ด
  let arr = ["Bora", "Lee"]

  // ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น์„ ์ด์šฉํ•ด
  // firstName์—” arr[0]์„
  // surname์—” arr[1]์„ ํ• ๋‹นํ•˜์˜€๋‹ค.
  let [firstName, surname] = arr;

  ๋ฐฐ์—ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ตฌ์กฐ ๋ถ„ํ•ดํ•˜์—ฌ ๋ณ€์ˆ˜๋กœ ํ• ๋‹นํ•˜์—ฌ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  // ๋‘ ๋ฒˆ์งธ ์š”์†Œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Œ
  let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

  alert( title ); // Consul

  ์ถ”๊ฐ€๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐฐ์—ด์˜ ๊ฐ’์€ ์‰ผํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์†Œ๋ฅผ ๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.

4. Object Rest / Array Rest (๊ฐ์ฒด ๋‚˜๋จธ์ง€ ์—ฐ์‚ฐ์ž, ๋ฐฐ์—ด ๋‚˜๋จธ์ง€ ์—ฐ์‚ฐ์ž)

  const {
    moduleList, classroomId, lastSectionId, lastSectionType, ...rest,
  } = classroomLecture;

  let [name1, name2, ...rest] = ['a', 'b', 'c', 'c', 'd', 'e'];

  console.log(rest); // ['c', 'c', 'd', 'e'];

  rest๋Š” ๋‚˜๋จธ์ง€ ๋ฐฐ์—ด ์š”์†Œ๋“ค์ด ์ €์žฅ๋œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์ด ๋œ๋‹ค.
  rest ๋Œ€์‹ ์— ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด๋„ ๋˜๋Š”๋ฐ, ๋ณ€์ˆ˜ ์•ž์˜ ์  ์„ธ ๊ฐœ(...)์™€ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•ด์•ผ ํ•œ๋‹ค.

  function sum(...theArgs) {
    let total = 0;
    for (const arg of theArgs) {
      total += arg;
    }
    return total;
  }

  console.log(sum(1, 2, 3));
  // Expected output: 6

  console.log(sum(1, 2, 3, 4));
  // Expected output: 10

  ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌ ํ• ๋•Œ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

5. Nullish coalescing (null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž)

๊ธฐ์กด ๋ฌธ๋ฒ•
const name = user.name || 'Guest';

null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž ๋ฌธ๋ฒ•
const name = user.name ?? 'Guest';

๊ธฐ์กด ๋ฌธ๋ฒ•์˜ ๊ฒฝ์šฐ ์กด์žฌํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ null, undefined, 0 ๋˜๋Š” ๋นˆ ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์€ ์ž˜๋ชป๋œ ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’ 'Guest'๊ฐ€ name ๋ณ€์ˆ˜์— ํ• ๋‹น๋œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ๊ธฐ์กด ๋ฌธ๋ฒ•์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ name ์†์„ฑ์ด ์กด์žฌํ•˜์ง€๋งŒ ์ž˜๋ชป๋œ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„ ๊ธฐ๋ณธ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž(??)๋Š” ํŠน๋ณ„ํžˆ null ๋˜๋Š” undefined ๊ฐ’๋งŒ ํ™•์ธํ•˜๋Š” ๊ธฐ์กด ๊ตฌ๋ฌธ์˜ ๋Œ€์•ˆ์ด๋‹ค. ๊ฐ’์ด null ๋˜๋Š” undefined์ธ ๊ฒฝ์šฐ์—๋งŒ ๊ธฐ๋ณธ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ  ๊ฐ’์ด falsy์ธ ๊ฒฝ์šฐ์—๋Š” ํ• ๋‹นํ•˜์ง€ ์•Š๋Š”๋‹ค.

5. Arrow function (ํ™”์‚ดํ‘œ ํ•จ์ˆ˜)

function add(a, b) {
  return a + b;
}

const add = (a, b) => a + b;

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” function ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ํ™”์‚ดํ‘œ(=>)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

6. Template literals(ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด)

const name = 'John';
console.log('Hello, ' + name + '!');

const name = 'John';
console.log(`Hello, ${name}!`);

ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ž‘์€๋”ฐ์˜ดํ‘œ๋‚˜ ํฐ๋”ฐ์˜ดํ‘œ ๋Œ€์‹  ๋ฐฑํ‹ฑ(`)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ž์—ด ์•ˆ์— ๋ณ€์ˆ˜์™€ ํ‘œํ˜„์‹์„ ๋” ์‰ฝ๊ฒŒ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

7. Optional chaining(์„ ํƒ์  ์—ฐ๊ฒฐ)

// ๊ธฐ์กด ๋ฌธ๋ฒ•
const person = { name: 'John', address: { city: 'New York' } };
const city = person.address && person.address.city;

// Optional chaining ๋ฌธ๋ฒ•
const person = { name: 'John', address: { city: 'New York' } };
const city = person.address?.city;

Optional chaining์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ์กด์žฌ ์—ฌ๋ถ€์— ๋Œ€ํ•œ ๊ฑฑ์ • ์—†์ด ๊ฐ์ฒด์˜ ์†์„ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค. ์†์„ฑ์ด ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋Œ€์‹  ๊ฒฐ๊ณผ๊ฐ€ ์ •์˜๋˜์ง€ ์•Š๋‹ค

์œ„์˜ ๋‚ด์šฉ ๋ง๊ณ  ๋ฐฐ์—ด ๋งค์†Œ๋“œ๋„ ๋Œ€ํ‘œ์ ์ธ ๋ฌธ๋ฒ•์ ์ธ ์„คํƒ•์— ํฌํ•จ๋œ๋‹ค.

const arr = [1, 2, 3, 4, 5];
const doubled = arr.map(x => x * 2);
const evens = arr.filter(x => x % 2 === 0);
const sum = arr.reduce((acc, x) => acc + x, 0);

React.createElement

React.createElement๋Š” React์—์„œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

React.createElement ํ•จ์ˆ˜๋Š” ์„ธ ๊ฐœ์˜ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

  1. ์š”์†Œ์˜ ์œ ํ˜• (๋ฌธ์ž์—ด ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜)

  2. ์š”์†Œ์˜ ์†์„ฑ (๋˜๋Š” "props") ๋˜๋Š” null

  3. ์ž์‹ ์š”์†Œ๋“ค

React.createElement('div', { className: 'test' }, 'Hello, World!')

์œ„ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ React ์š”์†Œ๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค.

<div className="test">Hello, World!</div>

React.createElement ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜๋ฅผ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋ฌธ์ž์—ด๋กœ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ ES6์˜ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์†์„ฑ ๋ฐ ์ž์‹ ์š”์†Œ๋“ค์€ ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ๋‹ค.

function MyComponent(props) {
  return React.createElement('div', { className: 'test' }, props.message);
}

React.createElement(MyComponent, { message: 'Hello, World!' });
<div className="test">Hello, World!</div>

React Element

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
  type: T;
  props: P;
  key: Key | null;
}

React Element์˜ ์†์„ฑ(property)

  • type: ์š”์†Œ์˜ ์œ ํ˜•, ์˜ˆ๋ฅผ ๋“ค์–ด "div" ๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜์ด๋‹ค.

  • props: ์š”์†Œ์˜ ์†์„ฑ, ์˜ˆ๋ฅผ ๋“ค์–ด className, style, onClick ๋“ฑ์˜ ์†์„ฑ์ด ํฌํ•จ๋œ๋‹ค.

  • key: ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ React๊ฐ€ ์š”์†Œ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ณ ์œ ํ•œ ์‹๋ณ„์ž์ด๋‹ค.

  • ref: React ์š”์†Œ์— ๋Œ€ํ•œ ์ฐธ์กฐ(reference)๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

React Element๋Š” React์—์„œ ๋ Œ๋”๋ง๋˜๋Š” ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„์ด๊ณ , JavaScript ๊ฐ์ฒด๋กœ, React ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. React ์š”์†Œ๋Š” ํ™”๋ฉด์— ๋ Œ๋”๋ง๋˜๋Š” ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋‹ค๋ฅธ React ์š”์†Œ๋“ค๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ React ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

React Element๋Š” ๋ถˆ๋ณ€๊ฐ์ฒด(immutable object)์ด๋ฉฐ, ํ•œ ๋ฒˆ ์ƒ์„ฑ๋˜๋ฉด ์ˆ˜์ •๋  ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฌํ•œ ๋ถˆ๋ณ€์„ฑ์€ React์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ๊ธฐ์—ฌํ•˜๋Š”๋ฐ React๋Š” ๋ณ€ํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด React Element๋ฅผ ๋งŒ๋“ค๊ณ  ๊ธฐ์กด์˜ Element์™€ ์ƒˆ Element๋ฅผ ๋น„๊ตํ•˜์—ฌ ์ตœ์†Œํ•œ์˜ ๋ณ€๊ฒฝ๋งŒ ์ ์šฉํ•˜๋ฏ€๋กœ ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

React StrictMode

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ง€ํ•˜๊ณ  ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ StrictMode๋Š” ๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ๋งŒ ๋™์ž‘ํ•˜๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋Š”๋‹ค.

StrictMode๋ฅผ ํ†ตํ•ด์„œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ํšจ๊ณผ

  • ๋ถ€์ˆ˜ํšจ๊ณผ ๊ฒ€์‚ฌ: React ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ถ€์ˆ˜ํšจ๊ณผ(์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ, useEffect ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ ˆ๊ฑฐ์‹œ ๋ฌธ์ž์—ด ref ๊ฒฝ๊ณ : ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ref๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค. ๋ฌธ์ž์—ด ref๋Š” ๋” ์ด์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ, ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ref๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ๋ ˆ๊ฑฐ์‹œ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ ๊ฒฝ๊ณ : ๋ ˆ๊ฑฐ์‹œ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ(componentWillMount, componentWillReceiveProps, componentWillUpdate)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๋Š” ๋” ์ด์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ, ๋Œ€์‹ ์— componentDidMount, componentDidUpdate, getDerivedStateFromProps ๋ฐ getSnapshotBeforeUpdate ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ ๊ฒฝ๊ณ : ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ(UNSAFE_componentWillMount, UNSAFE_componentWillReceiveProps, UNSAFE_componentWillUpdate)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๋Š” ํ–ฅํ›„ React ์—…๋ฐ์ดํŠธ์—์„œ ์‚ญ์ œ๋  ์˜ˆ์ •์ด๋ฉฐ, ๋Œ€์‹ ์— getDerivedStateFromProps ๋ฐ getSnapshotBeforeUpdate ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

StrictMode๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐœ๋ฐœ ๋ฐ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ๋ณด๋‹ค ์•ˆ์ „ํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

VDOM(Virtual DOM)์ด๋ž€?

Virtual DOM(๊ฐ€์ƒ DOM)์€ React์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ด๋‹ค. Virtual DOM์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ์‹ค์ œ DOM๊ณผ๋Š” ๋ณ„๋„๋กœ, JavaScript ๊ฐ์ฒด๋กœ ์ด๋ฃจ์–ด์ง„ ๊ฐ์ฒด ๋ชจ๋ธ์ด๋‹ค.

React์—์„œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ, ์‹ค์ œ DOM์„ ์กฐ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, Virtual DOM์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ์ด์ „๊ณผ ์ƒˆ๋กœ์šด Virtual DOM์„ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ DOM์— ์ ์šฉํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด DOM ์กฐ์ž‘ ํšŸ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ณ , ๋น ๋ฅธ ๋ Œ๋”๋ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

React์—์„œ๋Š” ์ด๋Ÿฌํ•œ Virtual DOM์„ ๊ตฌํ˜„ํ•˜๊ณ , ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์™€ ์†์„ฑ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค Virtual DOM์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์ตœ์ ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์‹ค์ œ DOM์— ์ ์šฉํ•˜์—ฌ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

DOM์ด๋ž€?

DOM(Document Object Model)์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์›น ํŽ˜์ด์ง€์˜ HTML ๋ฌธ์„œ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ํŒŒ์‹ฑํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ์ฒด ๋ชจ๋ธ์ด๋‹ค. ์ฆ‰, HTML, XML ๋˜๋Š” XHTML ๋ฌธ์„œ๋ฅผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด ๋ชจ๋ธ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ(HTML ๋ฌธ์„œ๋ฅผ ์ด๋ฃจ๋Š” ๋ชจ๋“  ์š”์†Œ๋“ค์€ ๊ฐ์ฒด๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋“ค์€ ์„œ๋กœ ๊ณ„์ธต์ ์ธ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.), ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์„œ์˜ ๊ตฌ์กฐ, ์Šคํƒ€์ผ, ์ฝ˜ํ…์ธ  ๋“ฑ์„ ๋™์ ์œผ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

DOM๊ณผ Virtual DOM์˜ ์ฐจ์ด

DOM์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ ์กฐ์ž‘๋˜๋Š” ์‹ค์ œ ๊ฐ์ฒด์ด๋ฏ€๋กœ, DOM ์กฐ์ž‘ ์ž‘์—…์€ ๋ธŒ๋ผ์šฐ์ €์˜ ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

๋ฐ˜๋ฉด, Virtual DOM์€ React์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š” ๊ฒƒ์œผ๋กœ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ง์ ‘ ์กฐ์ž‘ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ DOM ์กฐ์ž‘ ์ž‘์—…์˜ ๋น„์šฉ์„ ํฌ๊ฒŒ ์ ˆ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Reconciliation(์žฌ์กฐ์ •) ๊ณผ์ •์€ ๋ฌด์—‡์ธ๊ฐ€?

React์—์„œ Reconciliation(์žฌ์กฐ์ •)์€ Virtual DOM์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ๊ณผ์ •์œผ๋กœ, ์ด์ „ ์ƒํƒœ์™€ ํ˜„์žฌ ์ƒํƒœ์˜ Virtual DOM์„ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ DOM์— ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.

Reconciliation์€ Virtual DOM์˜ ๋…ธ๋“œ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์ด์ „ ์ƒํƒœ์™€ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์„ ์ฐพ๋Š”๋‹ค. ์ด ๊ณผ์ •์—์„œ React๋Š” ํšจ์œจ์ ์œผ๋กœ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ Œ๋”๋ง๋  ๋•Œ, React๋Š” ์ด์ „ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ์™€ ํ˜„์žฌ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

Reconciliation์˜ ์ด์ ์€ ์„ฑ๋Šฅ๊ณผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ ์ด๋‹ค. React๋Š” Virtual DOM์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ, ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ DOM ์กฐ์ž‘๋งŒ ์ˆ˜ํ–‰๋˜์–ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋˜๊ณ , ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธ๋˜๋ฏ€๋กœ, ๋ถˆํ•„์š”ํ•œ ํ™”๋ฉด ๊นœ๋นก์ž„์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Aha Moment

์ „๊ฐœ ๊ตฌ๋ฌธ์— ๋Œ€ํ•ด์„œ MDN์„ ํ™•์ธํ–ˆ์„ ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ์ถ”๊ฐ€๋กœ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

apply() ๋Œ€์ฒด

์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐฐ์—ด์˜ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ Function.prototype.apply() ๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

  function myFunction(x, y, z) { }
  let args = [0, 1, 2];
  myFunction.apply(null, args);

  ์ „๊ฐœ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด ์œ„ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค.

  function myFunction(x, y, z) { }
  let args = [0, 1, 2];
  myFunction(...args);

๋ฐฐ์—ด ๋ณต์‚ฌ

  let arr = [1, 2, 3];
  let arr2 = [...arr]; // arr.slice() ์™€ ์œ ์‚ฌ
  arr2.push(4);

  // arr2 ์€ [1, 2, 3, 4] ์ด ๋จ
  // arr ์€ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ณ  ๋‚จ์•„ ์žˆ์Œ

๋ฐฐ์—ด ๋ณ‘ํ•ฉ

  let arr1 = [0, 1, 2];
  let arr2 = [3, 4, 5];
  // arr2 ์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์„ arr1 ์— ๋ถ™์ž„
  arr1 = arr1.concat(arr2);

  ์ „๊ฐœ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์™€ ๋™์ผํ•˜๊ฒŒ ๋ณ€๊ฒฝ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  let arr1 = [0, 1, 2];
  let arr2 = [3, 4, 5];
  arr1 = [...arr1, ...arr2]; // arr1 ์€ ์ด์ œ [0, 1, 2, 3, 4, 5]

๋ฐฐ์—ด ๋ณ‘ํ•ฉ ๋ฐ ์ˆœ์„œ๋ณ€๊ฒฝ

  let arr1 = [0, 1, 2];
  let arr2 = [3, 4, 5];
  // arr2 ์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์„ arr1 ์˜ ์•ž์— ๋ถ™์ž„
  Array.prototype.unshift.apply(arr1, arr2) // arr1 ์€ ์ด์ œ [3, 4, 5, 0, 1, 2] ๊ฐ€ ๋จ

  ์ „๊ฐœ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์™€ ๋™์ผํ•˜๊ฒŒ ๋ณ€๊ฒฝ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  let arr1 = [0, 1, 2];
  let arr2 = [3, 4, 5];
  arr1 = [...arr2, ...arr1]; // arr1 ์€ ์ด์ œ [3, 4, 5, 0, 1, 2] ๊ฐ€ ๋จ

์ฐธ๊ณ : unshift()์™€ ๋‹ฌ๋ฆฌ, ์ „๊ฐœ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉ์‹œ์—๋Š” ์ƒˆ๋กœ์šด arr1์„ ๋งŒ๋“ค๋ฉฐ ๊ธฐ์กด ๋ฐฐ์—ด์„ ๋ณ€ํ˜•ํ•˜์ง€ ์•Š๋‹ค.

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

์ด๋ฒˆ์— ๋ฐ๋ธŒ๋…ธํŠธ ํ‚ค์›Œ๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•ด๋ณด๋ฉด์„œ ๋Š๋‚€ ๋ถ€๋ถ„์€ React๊ฐ€ ์–ด๋–ค ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ JSX๋ฅผ ๋„์ž…ํ•˜๊ณ  VDOM์„ ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ๋Š”์ง€ ์ƒ๊ฐํ•ด๋ณด๋Š” ๊ณ„๊ธฐ๊ฐ€ ๋˜์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ํ˜„์žฌ ์‹ค๋ฌด์—์„œ ์ž‘์—…ํ•˜๋ฉด์„œ๋„ ์ด ๊ธฐ์ˆ ์ด ์™œ ๋‚˜์˜ค๊ฒŒ ๋˜์—ˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๊นŠ๊ฒŒ ๊ณ ๋ฏผ ํ•ด๋ณธ์ ์ด ์—†๊ณ  ๋Œ€๋žต์ ์ธ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋งŒ ์•Œ๊ณ  ์žˆ์—ˆ๋‹ค๋ฉด ์ด๋ฒˆ์— React์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ๋‚ด์šฉ์„ ์ฐพ์•„๋ณด๊ณ  ์ •๋ฆฌํ•˜๋ฉด์„œ React์™€ ์ „๋ณด๋‹ค ๋” ๊ฐ€๊นŒ์›Œ์ง„ ๋Š๋‚Œ์ด ๋“ค์—ˆ๋‹ค. ์ด๋ฒˆ์— ์ •๋ฆฌํ•œ ๋…ธํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง€์†์ ์œผ๋กœ ๋จธ๋ฆฟ์†์— ์ง‘์–ด ๋„ฃ๋Š” ๊ณผ์ •์„ ํ†ตํ•ด์„œ ๊ธฐ๋ณธ์„ ์ž˜ ๊ธฐ์–ตํ•˜๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค.

Reference

Last updated