๐Ÿ“œ reactjs ๊ณต์‹ ๋ฌธ์„œ ์ฝ๊ธฐ - Main Concepts 1~4

BOHYEON SEOยท2020๋…„ 6์›” 28์ผ
0
post-thumbnail

์ง€์†์ ์œผ๋กœ ์ฐธ๊ณ ํ•˜๊ณ  ์‹ถ์€ ๋ฆฌ์•กํŠธ์˜ ์ฒ ํ•™์ ์ธ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ

1. Hello World

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ React ์˜ˆ์ œ

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

2. Introducing JSX

JSX

const element = <h1>Hello, world!</h1>;

why JSX?

์„ ์ฒœ์ ์œผ๋กœ ๋ Œ๋”๋ง ๋กœ์ง์€ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๋กœ์ง๋“ค๊ณผ ์—ฐ๊ฒฐ์ด ๋˜์–ด์žˆ๋‹ค. (์ด๋ฒคํŠธ ๊ด€๋ฆฌ, ์‹œ๊ฐ„์— ๋”ฐ๋ฅธ state ๋ณ€ํ™”, ๋ฐ์ดํ„ฐ ์ค€๋น„ ์ƒํ™ฉ ๋“ฑ) React๋Š” ์ด ์‚ฌ์‹ค์„ ํฌ์šฉํ•˜๋Š” ์˜๋ฏธ์—์„œ JSX๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋กœ์ง๊ณผ ๋งˆํฌ์—…์„ ํ•œ ๊ณณ์— ๋‹ด๊ณ ์ž ํ•œ ๊ฒƒ์ด๋‹ค. (๋กœ์ง๊ณผ ๋งˆํฌ์—…์„ ํ•œ ๊ณณ์— ๋ฌถ์€ ๊ณณ์ด ๋ฐ”๋กœ "components"์ด๋‹ค.)

๊ทธ๋ž˜์„œ JSX๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„ ๋” ํŽธํ•˜๊ฒŒ ์—ฌ๊ธธ ๋”ฐ๋ฆ„์ด๋‹ค.

JSX๋„ ํ‘œํ˜„์‹์ด๋‹ค.

๋ณ€ํ™˜ ํ›„์—๋Š” JSX๋„ ๋‹จ์ง€ ํ•˜๋‚˜์˜ JavaScript object์ผ ๋ฟ์ด๋‹ค. ๋”ฐ๋ผ์„œ if๋ฌธ, for๋ฌธ, ๋ณ€์ˆ˜ ํ• ๋‹น, arguments, return ๋“ฑ๋“ฑ ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

JSX์—์„œ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ

string literal๋กœ ์†์„ฑ์„ ๋ช…์‹œํ•œ๋‹ค.

const element = <div tabIndex="0"></div>;

์ค‘๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ JavaScript ํ‘œํ˜„์‹์„ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

const element = <img src={user.avatarUrl}></img>;

* ํ•œ ์†์„ฑ์„ ๋ช…์‹œํ•  ๋•Œ ๋”ฐ์˜ดํ‘œ(string literal)์ด๋‚˜ ์ค‘๊ด„ํ˜ธ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
* ์†์„ฑ ๊ฐ’์€ camelCase๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. JSX๋Š” HTML๋ณด๋‹ค๋Š” JavaScript์— ๊ฐ€๊น๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ธ์ ์…˜ ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•ด์ค€๋‹ค.

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

React๋Š” JSX์•ˆ์˜ ์–ด๋–ค ๊ฐ’์ด๋“  escapeํ•œ๋‹ค. ๋ชจ๋“  ๊ฒƒ๋“ค์€ ๋ Œ๋”๋ง ๋˜๊ธฐ์ „ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ์ ์…˜ ๊ณต๊ฒฉ์„ ํ•  ์ˆ˜ ์—†๋‹ค. XSS(cross-site-scripting) ๊ณต๊ฒฉ๋„ ๋ง‰์•„์ค€๋‹ค.

JSX๋Š” Object์ด๋‹ค.

Babel์€ JSX๋ฅผ React.createElement()๋กœ ์ปดํŒŒ์ผ ํ•œ๋‹ค.

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

์œ„ ๋‘ ์˜ˆ์ œ๋Š” ์™„์ „ํžˆ ๋™์ผํ•˜๋‹ค.

๊ทธ๋ฆฌ๊ณ  React.createElement()๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š”์ง€ ๋ช‡ ๊ฐ€์ง€ ์ฒดํฌ๋ฅผ ํ•œ ํ›„, ์•„๋ž˜์™€ ๊ฐ™์€ object๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค.

// ๊ฐ„๋žตํ•œ ๋ฒ„์ „์ž„
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

์ด object๋ฅผ "React elements"๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. React๋Š” ์ด object์˜ ๋‚ด์šฉ์„ ์ฝ์–ด DOM์„ ๊ทธ๋ฆฌ๊ณ  ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

3. Rendering Elements

element

const element = <h1>Hello, world</h1>;

element๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ

React elements๋Š” immutableํ•˜๋‹ค. ์ผ๋‹จ element๋ฅผ ์ƒ์„ฑํ–ˆ์œผ๋ฉด, children์ด๋‚˜ attribute๋ฅผ ์ˆ˜์ •ํ•˜๋Š”๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. element๋Š” ์˜ํ™”์—์„œ ํ•˜๋‚˜์˜ ํ”„๋ ˆ์ž„๊ณผ ๊ฐ™๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๋งค๋ฒˆ ReactDOM.render๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ํ˜„์žฌ๊นŒ์ง€ ์•„๋Š” ์œ ์ผํ•œ UI ์—…๋ฐ์ดํŠธ ๋ฐฉ๋ฒ•์ด๋‹ค.

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);
| ๋‹ค๋งŒ, ์‹ค์ œ React App์€ ReactDOM.render()๋ฅผ ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•œ๋‹ค. state๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ ๋’ค์— ๋‚˜์˜จ๋‹ค.

4. Components and Props

์ปดํฌ๋„ŒํŠธ๋Š” UI๋ฅผ ๋…๋ฆฝ์ ์ด๊ณ , ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ„๊ฒŒ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์กฐ๊ฐ์„ ๋…๋ฆฝ์ ์œผ๋กœ ์—ฌ๊ธฐ๊ฒŒ ํ•œ๋‹ค. ๊ฐœ๋…์ ์œผ๋กœ, components๋Š” JavaScript ํ•จ์ˆ˜์™€ ๊ฐ™๋‹ค.

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ์˜ˆ์‹œ

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

์ปดํฌ๋„ŒํŠธ์˜ ์‚ฌ์šฉ

const element = <Welcome name="Sara" />;

React๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋‚˜๋ฉด, JSX ์†์„ฑ๊ณผ children์„ "props"๋ผ๋Š” ์ด๋ฆ„์˜ object์— ๋‹ด์•„ ์ „๋‹ฌํ•œ๋‹ค.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;

ReactDOM.render(
  element,
  document.getElementById('root')
);

!!์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์€ ๋ฌด์กฐ๊ฑด ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค.!!

์ปดํฌ๋„ŒํŠธ ๊ตฌ์„ฑ

ํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ์˜ˆ๋ฅผ๋“ค์–ด button, form, dialog ๋“ฑ์„ ์–ด๋Š ๋‹จ๊ณ„์—์„œ๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Welcome ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•œ App component

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

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

๋งŒ์•ฝ, ๊ธฐ์กด์˜ ์•ฑ์„ React๋กœ ๋Œ€์ฒดํ•œ๋‹ค๋ฉด bottom-up์œผ๋กœ ๊ฐ€์žฅ ์ž‘์€ ์ปดํฌ๋„ŒํŠธ ๋ถ€ํ„ฐ ์กฐ์„ฑํ•ด๋‚˜๊ฐ€๋ฉด์„œ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

Props are Read-only

์•„๋ž˜ ํ•จ์ˆ˜๋Š” "pure"ํ•˜๋‹ค. ์ž…๋ ฅ๊ฐ’์„ ๋ณ€ํ™”์‹œํ‚ค์ง€ ์•Š๊ณ  ๊ฐ™์€ ์ž…๋ ฅ๊ฐ’์— ํ•ญ์ƒ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋‚ด๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

function sum(a, b) {
  return a + b;
}
  • "pure"ํ•˜์ง€ ์•Š์€ ์˜ˆ์‹œ
function withdraw(account, amount) {
  account.total -= amount;
}

React์—๋Š” ์œ ์—ฐํ•˜์ง€๋งŒ ํ•˜๋‚˜์˜ ์—„๊ฒฉํ•œ ๊ทœ์น™์ด ์žˆ๋‹ค.

All React components must act like pure functions with respect to their props.

๋‹ค๋งŒ UI๋Š” ๋‹ค์ด๋‚˜๋ฏนํ•˜๊ฒŒ ๋ณ€ํ™”ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ž˜์„œ state๋ฅผ ์ด์šฉํ•  ๊ฒƒ์ด๋‹ค.

profile
FE Developer @Medistream

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