๐Ÿ“š Taniarascia์˜ getting-started-with-react

์ด ๊ธ€์€ Taniarascia์˜ getting-started-with-react๋ฅผ ํ•œ๊ตญ์–ด๋กœ ์š”์•ฝํ•œ ์ •๋ฆฌ ๊ธ€์ž…๋‹ˆ๋‹ค. ๊ณต๋ถ€ ๋ชฉ์ ์œผ๋กœ ์š”์•ฝํ•œ ์ฃผ๊ด€์ ์ธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜€

๋ฆฌ์•กํŠธ๋ž€?

  • ๋ฆฌ์•กํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.(ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์•„๋‹ˆ๋‹ค.)
  • ๋ฆฌ์•กํŠธ๋Š” ํŽ˜์ด์Šค๋ถ(ํ˜„ ๋ฉ”ํƒ€)์—์„œ ๊ฐœ๋ฐœ๋œ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ์ด๋‹ค.
  • ๋ฆฌ์—‘ํŠธ๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ User Interface(UI)๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
  • ๋ฆฌ์•กํŠธ๋Š” MVC(Model View Controller) ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ View๋ฅผ ๋‹ด๋‹นํ•œ๋‹ค.

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

๋ฆฌ์•กํŠธ ์•ฑ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

npm๊ณผ yarn ๋ชจ๋‘ ๋ฆฌ์•กํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ œ์ž‘์„ ์ง€์›ํ•œ๋‹ค.

npx create-react-app [์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฆ„]
yarn create react-app [์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฆ„]

๊ธฐ๋ณธ์ ์œผ๋กœ index.html ๋‚ด๋ถ€์— id๊ฐ€ root์ธ div ํƒœ๊ทธ๊ฐ€ ๋ฆฌ์•กํŠธ์˜ ์‹œ์ž‘์ ์ด ๋œ๋‹ค. ๋˜ํ•œ, index.js๋ฅผ ๋ณด๋ฉด

class App extends React.Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

// ์œ„๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ๊ธฐ์ค€์ด๋‹ค. ์ตœ๊ทผ์—๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ ์ด๋Š” ์ง์ ‘ ์ฐพ์•„๋ณด๊ธธ!

์ฆ‰, App ์ปดํฌ๋„ŒํŠธ๋Š” root ์š”์†Œ์— ๋ Œ๋”๋ง ๋˜๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ด App ์ปดํฌ๋„ŒํŠธ์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

๋ฆฌ์•กํŠธ DevTools

๋ฆฌ์•กํŠธ DevTools

๋ฆฌ์•กํŠธ์™€ ๊ด€๋ จ๋œ ๊ฐœ๋ฐœ๋„๊ตฌ๋ฅผ ํ™•์žฅ์‹œ์ผœ์ฃผ๋Š” ํฌ๋กฌ extension์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ๋‚ด์šฉ๊ณผ props, state์˜ ํ๋ฆ„์„ ๋ณด๊ธฐ ์‰ฝ๊ฒŒ ๋„์™€์ค€๋‹ค.

JSX : JavaScript + XML

๋ฆฌ์•กํŠธ ์ฝ”๋“œ์—์„œ HTML๊ณผ ์œ ์‚ฌํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด์•˜์„ ๊ฒƒ์ด๋‹ค. ์ด ๋ถ€๋ถ„์€ HTML๊ณผ ์œ ์‚ฌํ•˜๊ธด ํ•˜์ง€๋งŒ, ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด JSX๋กœ JavaScript์˜ ํ™•์žฅ ๋ฌธ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด JavaScript์—์„œ HTML์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

const heading = <h1 className="site-heading">Hello, React</h1>;

๋˜ํ•œ, JSX๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์จ๋„ ๋œ๋‹ค.

const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!');

(๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ์ฝ”๋“œ๋Š” ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ ธ ์ง๊ด€์ ์ด์ง€ ์•Š๋‹ค. ์‚ฌ์‹ค์ƒ JSX๋Š” ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํ•„์ˆ˜์ ์ธ ๋…€์„์ด๋‹ค.)

JSX์˜ ํŠน์ง• ๋ฐ ์ฃผ์˜์‚ฌํ•ญ

JSX๋Š” ๋ณด์ด๊ธฐ์—” HTML์ด์ง€๋งŒ ์‹ค์ƒ JavaScript ์ฝ”๋“œ์ด๋‹ค.

  • CSS ์Šคํƒ€์ผ์„ ์œ„ํ•œ class๋Š” className์œผ๋กœ ํ‘œ๊ธฐํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด JavaScript์—๋Š” ์ด๋ฏธ class๋ผ๋Š” ์˜ˆ์•ฝ์–ด๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ๋Š” CamelCase๋กœ ์ž‘์„ฑํ•œ๋‹ค. ex) onclick => onClick
  • Self-closing tags๋Š” ๋ฐ˜๋“œ์‹œ ์Šฌ๋ž˜์‰ฌ๊ฐ€ ๋’ค์— ์˜จ๋‹ค. ex) <img />
  • JSX ๋‚ด์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ‘œํ˜„์€ {}๋กœ ํ•  ์ˆ˜ ์žˆ๋‹ค.(๋งˆ์น˜ ๋ฌธ์ž ๋ฆฌํ„ฐ๋Ÿด๋‚ด์—์„œ ${} ์‚ฌ์šฉํ•˜๋“ฏ์ด)

Components(์ปดํฌ๋„ŒํŠธ)

๋ฆฌ์•กํŠธ๋Š” ๋ชจ๋‘ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ๋” ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ๋“ค์–ด์žˆ๊ณ , ๊ทธ ์ปดํฌ๋„ŒํŠธ๋“ค ๋‚ด๋ถ€๋„ ๋”๋”๋” ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋“ค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

  • class component
import React, { Component } from 'react';

class ClassComponent extends Component {
  render() {
    return <div>Example</div>;
  }
}

export default ClassComponent;
  • simple component(ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ)
const SimpleComponent = () => {
  return <div>Example</div>;
};

export default SimpleComponent;

Props

๋ฆฌ์•กํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ porps๋ผ๊ณ  ํ•˜๋Š” ์†์„ฑ๊ณผ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
(๊ธฐ์กด ๊ธ€์—์„œ๋Š” class component ์˜ˆ์‹œ์ด์ง€๋งŒ, ์ €๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋กœ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.)

function ParentComponent() {
  const characters = [
    {
      name: 'Charlie',
      job: 'Janitor',
    },
    {
      name: 'Mac',
      job: 'Bouncer',
    },
    {
      name: 'Dee',
      job: 'Aspring actress',
    },
    {
      name: 'Dennis',
      job: 'Bartender',
    },
  ];

  return <ChildComponent characterData={characters} />;
}

function ChildComponent(props) {
  return (
    <>
      {props.characterData.map((v, i) => (
        <div key={i}>
          <p>{v.name}</p>
          <p>{v.job}</p>
        </div>
      ))}
    </>
  );
}
  • ์œ„์™€ ๊ฐ™์ด ๋ฐฐ์—ด ํ•จ์ˆ˜(map)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ JSX ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ๋Š” ๋ฐ์ดํ„ฐ๋งˆ๋‹ค์˜ ๊ณ ์œ ํ•œ ๊ฐ’์„ ํ†ตํ•ด key๊ฐ’์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.(๋žœ๋”๋ง ์‹œ ๊ฐ ํ•ญ๋ชฉ์„ ์‹๋ณ„ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ ์‚ฌ์‹ค ์œ„์™€๊ฐ™์ด ๋ฐฐ์—ด์˜ ์ˆœ์„œ์ธ i๋ฅผ ์ฃผ๋Š” ๊ฒƒ๋„ ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค.)
  • ์—ฌ๊ธฐ์„œ ์˜๋ฌธ์ด ์ƒ๊น๋‹ˆ๋‹ค. props๋ฅผ ํ†ตํ•ด ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๋Š” ๊ฑด ์ข‹์•˜๋Š”๋ฐ, ๊ทธ๋ ‡๋‹ค๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹ค๋ฃจ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

State

state๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ—ค๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •(์ถ”๊ฐ€ ํ˜น์€ ์‚ญ์ œ ๋“ฑ)์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” useState()๋ผ๋Š” ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํšŒ๊ณ 

์•„๋ฌด๋ž˜๋„ ์˜ค๋ž˜์ „์— ๋ฆฌ์•กํŠธ์˜ ํฐ ๊ฐœ๋…์„ ์ •๋ฆฌํ•œ ๊ธ€์ด๋ผ์„œ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋กœ ์„ค๋ช…ํ•˜๋Š” ๋‚ด์šฉ์ด ์—†์—ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ ์ž…์žฅ์—์„œ๋Š” ์ •๋ง ๋‹น์—ฐํ•˜๊ณ  ๊ธฐ๋ณธ์ ์ธ ๋‚ด์šฉ์ด์ง€๋งŒ, ๋ง‰์—ฐํ•˜๊ฒŒ โ€˜๋ฆฌ์•กํŠธ์—์„œ ์ƒํƒœ๊ฐ€ ๋ญ์ง€??โ€™์™€ ๊ฐ™์€ ์˜๋ฌธ์ด ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ์ข‹์€ ๊ธ€์ธ ๊ฒƒ ๊ฐ™๋‹ค.