We want to hear from you!Take our 2021 Community Survey!
This site is no longer updated.Go to react.dev

์ž์Šต์„œ: React ์‹œ์ž‘ํ•˜๊ธฐ

These docs are old and wonโ€™t be updated. Go to react.dev for the new React docs.

The updated Tutorial teaches modern React and includes live examples.

์ด ์ž์Šต์„œ๋Š” React์— ๋Œ€ํ•œ ์–ด๋–ค ์ง€์‹๋„ ๊ฐ€์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ž์Šต์„œ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

์šฐ๋ฆฌ๋Š” ์ด ์ž์Šต์„œ์—์„œ ์ž‘์€ ๊ฒŒ์ž„์„ ๋งŒ๋“ค๊ฒ๋‹ˆ๋‹ค. ๊ฒŒ์ž„์„ ๋งŒ๋“ค๊ณ  ์‹ถ์ง€ ์•Š์•„์„œ ์ž์Šต์„œ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ํ•œ๋ฒˆ ํ•ด๋ณด์„ธ์š”! ์ž์Šต์„œ๋ฅผ ํ†ตํ•ด React ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ธฐ๋ณธ์ ์ธ ์‚ฌํ•ญ๋“ค์„ ๋ฐฐ์›๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๋งˆ์Šคํ„ฐํ•˜๋ฉด React๋ฅผ ๋” ๊นŠ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒ

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

์ž์Šต์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ช‡ ๊ฐ€์ง€ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ž์Šต์„œ๋ฅผ ์ตํžˆ๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ๋ถ€๋ถ„์„ ํ•œ ๋ฒˆ์— ์™„๋ฃŒํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ํ•œ๋‘ ๊ตฌ์—ญ์ด๋ผ๋„ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด ์‹œ๋„ํ•ด ๋ณด์„ธ์š”.

์ด ์ž์Šต์„œ๋ฅผ ๋”ฐ๋ผ ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ๋Š” ๊ฒƒ๋„ ๊ดœ์ฐฎ์ง€๋งŒ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ ์ ๊ธฐ๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ๋ชธ์œผ๋กœ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒ๊ณผ ๋” ๊ฐ•ํ•œ ์ดํ•ด์— ๋„์›€์„ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌด์—‡์„ ๋งŒ๋“ค๊ฒŒ ๋ ๊นŒ์š”?

์šฐ๋ฆฌ๋Š” React๋กœ ๋Œ€ํ™”ํ˜• ํ‹ฑํƒํ†  ๊ฒŒ์ž„์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค๋“œ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์€ ์ด ํŽ˜์ด์ง€์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ฝ”๋“œ์˜ ๋ฌธ๋ฒ•์— ์ต์ˆ™ํ•˜์ง€ ์•Š๋”๋ผ๋„ ๊ฑฑ์ •๋งˆ์„ธ์š”! ์ž์Šต์„œ์˜ ๋ชฉ์ ์€ React์™€ React ๋ฌธ๋ฒ•์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ๋•๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ž์Šต์„œ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์ „์— ํ‹ฑํƒํ†  ๊ฒŒ์ž„์„ ์ฒดํ—˜ํ•ด๋ณด๊ธธ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋ชฉํ• ๋งŒํ•œ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ๊ฒŒ์ž„ํŒ ์˜ค๋ฅธ์ชฝ์— ๋ฒˆํ˜ธ๊ฐ€ ๋งค๊ฒจ์ง„ ๋ชฉ๋ก์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชฉ๋ก์€ ๊ฒŒ์ž„์—์„œ ์ผ์–ด๋‚œ ๋ชจ๋“  ์ด๋™์˜ ๊ธฐ๋ก์„ ๋ณด์—ฌ์ฃผ๋ฉฐ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋ฉด ์—…๋ฐ์ดํŠธ ๋ฉ๋‹ˆ๋‹ค.

ํ‹ฑํƒํ†  ๊ฒŒ์ž„์— ์ต์ˆ™ํ•ด์กŒ๋‹ค๋ฉด ์ข…๋ฃŒํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ž์Šต์„œ์˜ ๊ฐ„๋‹จํ•œ ํ…œํ”Œ๋ฆฟ์—์„œ ์‹œ์ž‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ๋Š” ๊ฒŒ์ž„ ๊ตฌํ˜„์„ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ์„ ์ˆ˜ ์ง€์‹

HTML๊ณผ JavaScript์— ์–ด๋А ์ •๋„ ์ต์ˆ™ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์ž์Šต์„œ๋ฅผ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ•จ์ˆ˜, ๊ฐ์ฒด, ๋ฐฐ์—ด, ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ํด๋ž˜์Šค ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์— ์ต์ˆ™ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

JavaScript๋ฅผ ๋‹ค์‹œ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ๊ฐ€์ด๋“œ๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. JavaScript์˜ ์ตœ์‹  ๋ฒ„์ „์ธ ES6์˜ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์— ์ฃผ๋ชฉํ•ด์ฃผ์„ธ์š”. ์ž์Šต์„œ์—์„œ๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜, ํด๋ž˜์Šค, let, const๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Babel REPL์„ ์‚ฌ์šฉํ•˜์—ฌ ES6 ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ปดํŒŒ์ผ๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž์Šต์„œ ํ™˜๊ฒฝ์„ค์ •

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

์„ ํƒ 1: ๋ธŒ๋ผ์šฐ์ €์— ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

์ด ์˜ต์…˜์€ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค!

๋จผ์ € ์ƒˆ ํƒญ์—์„œ ์ดˆ๊ธฐ ์ฝ”๋“œ๋ฅผ ์—ด์–ด์ฃผ์„ธ์š”. ์ƒˆ ํƒญ์€ ๋น„์–ด์žˆ๋Š” ํ‹ฑํƒํ†  ๊ฒŒ์ž„ํŒ๊ณผ React ์ฝ”๋“œ๋ฅผ ๋ณด์—ฌ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ž์Šต์„œ์—์„œ React ์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ๋‘ ๋ฒˆ์งธ ์„ค์ • ์˜ต์…˜์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๊ฐœ์š” ๋‹จ๋ฝ์œผ๋กœ ๋„˜์–ด๊ฐ€์„œ React์— ๋Œ€ํ•œ ๊ฐœ์š”๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

์„ ํƒ 2: ์ž์‹ ์˜ ์ปดํ“จํ„ฐ์—์„œ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

์ด ๋ฐฉ์‹์€ ์™„์ „ํžˆ ์„ ํƒ์‚ฌํ•ญ์ด๋ฉฐ ์ด ์ž์Šต์„œ์— ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค!


์„ ํƒ ์‚ฌํ•ญ: ์„ ํ˜ธํ•˜๋Š” ํ…์ŠคํŠธ ํŽธ์ง‘๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ง€์นจ

์ด ์„ค์ •์—์„œ๋Š” ๋” ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์„ ํ˜ธํ•˜๋Š” ํŽธ์ง‘๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์Šต์„œ๋ฅผ ์™„์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ผ์ฃผ์„ธ์š”.

  1. ์ตœ์‹  ๋ฒ„์ „์˜ Node.js๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”.
  2. Create React App ์„ค์น˜ ์ง€์นจ์„ ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
npx create-react-app my-app
  1. ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ์˜ src/ ํด๋”์— ์žˆ๋Š” ๋ชจ๋“  ํŒŒ์ผ์„ ์‚ญ์ œํ•ด ์ฃผ์„ธ์š”.

์ฃผ์˜

src ํด๋” ์ „์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ํด๋” ๋‚ด๋ถ€์˜ ๊ธฐ์กด ์†Œ์Šค ํŒŒ์ผ๋“ค๋งŒ ์‚ญ์ œํ•ด ์ฃผ์„ธ์š”. ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ธฐ๋ณธ ์†Œ์Šค ํŒŒ์ผ์„ ์ด ํ”„๋กœ์ ํŠธ์˜ ์˜ˆ์‹œ๋กœ ๋ฐ”๊ฟ€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

cd my-app
cd src

# Mac ๋˜๋Š” Linux ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ
rm -f *

# Windows ์‚ฌ์šฉ์ž
del *

# ๋‹ค์‹œ ํ”„๋กœ์ ํŠธ ํด๋”๋กœ ๋Œ์•„๊ฐ€์„ธ์š”.
cd ..
  1. src/ ํด๋”์— index.css๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ด CSS ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
  2. src/ ํด๋”์— index.js๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ด JS ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
  3. ์œ„์—์„œ ์ƒ์„ฑํ•œ index.js์˜ ์ƒ๋‹จ์— ์•„๋ž˜ ์„ธ ์ค„์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';

์ด์ œ ํ”„๋กœ์ ํŠธ ํด๋”์—์„œ npm start ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:3000๋ฅผ ์—ด๋ฉด ๋น„์–ด์žˆ๋Š” ํ‹ฑํƒํ†  ํ•„๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—๋””ํ„ฐ์—์„œ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ํ‘œ์‹œ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ง€์นจ์„ ๋”ฐ๋ฅด๊ธธ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋„์›€์ด ํ•„์š”ํ•  ๋•Œ!

๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์ƒ๊ฒผ๋‹ค๋ฉด ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ง€์›ํ•˜๋Š” ์ž๋ฃŒ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”. ํŠนํžˆ Reactiflux Chat์€ ๋น ๋ฅด๊ฒŒ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๋‹ต์„ ์–ป์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ ๊ณ„์† ๋ง‰ํžŒ ์ƒํƒœ๋ผ๋ฉด ์ด์Šˆ๋ฅผ ์ œ์ถœํ•ด์ฃผ์„ธ์š”. ์šฐ๋ฆฌ๊ฐ€ ๋„์™€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐœ์š”

์ด์ œ ์„ค์ •์„ ์™„๋ฃŒํ–ˆ์œผ๋‹ˆ React์˜ ๊ฐœ์š”๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

React๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

React๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ์„ ์–ธ์ ์ด๊ณ  ํšจ์œจ์ ์ด๋ฉฐ ์œ ์—ฐํ•œ JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. โ€œ์ปดํฌ๋„ŒํŠธโ€๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ž‘๊ณ  ๊ณ ๋ฆฝ๋œ ์ฝ”๋“œ์˜ ํŒŒํŽธ์„ ์ด์šฉํ•˜์—ฌ ๋ณต์žกํ•œ UI๋ฅผ ๊ตฌ์„ฑํ•˜๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.

React๋Š” ๋ช‡ ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ง€์ง€๋งŒ ์šฐ๋ฆฌ๋Š” React.Component์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// ์‚ฌ์šฉ ์˜ˆ์ œ: <ShoppingList name="Mark" />

XML๊ณผ ์œ ์‚ฌํ•œ ์žฌ๋ฐŒ๋Š” ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React์—๊ฒŒ ํ™”๋ฉด์— ํ‘œํ˜„ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ React๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๋‹ค์‹œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ShoppingList๋Š” React ์ปดํฌ๋„ŒํŠธ ํด๋ž˜์Šค ๋˜๋Š” React ์ปดํฌ๋„ŒํŠธ ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ๋Š” props๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์˜ค๊ณ  render ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ‘œ์‹œํ•  ๋ทฐ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

render ํ•จ์ˆ˜๋Š” ํ™”๋ฉด์—์„œ ๋ณด๊ณ ์ž ํ•˜๋Š” ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. React๋Š” ์„ค๋ช…์„ ์ „๋‹ฌ๋ฐ›๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ render๋Š” ๋ Œ๋”๋งํ•  ๋‚ด์šฉ์„ ๊ฒฝ๋Ÿ‰ํ™”ํ•œ React ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์ˆ˜์˜ React ๊ฐœ๋ฐœ์ž๋Š” โ€œJSXโ€๋ผ๋Š” ํŠน์ˆ˜ํ•œ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ React์˜ ๊ตฌ์กฐ๋ฅผ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. <div /> ๊ตฌ๋ฌธ์€ ๋นŒ๋“œํ•˜๋Š” ์‹œ์ ์—์„œ React.createElement('div')๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์œ„์—์„œ ๋ณธ ์˜ˆ์‹œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€ํ™”ํ•ฉ๋‹ˆ๋‹ค.

return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);

์ „์ฒด ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์„œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

createElement()์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด API ์ฐธ์กฐ์—์„œ ์ž์„ธํ•œ ์„ค๋ช…์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ž์Šต์„œ์—์„œ๋Š” ์ด ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ JSX๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

JSX๋Š” JavaScript์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. JSX ๋‚ด๋ถ€์˜ ์ค‘๊ด„ํ˜ธ ์•ˆ์— ์–ด๋–ค JavaScript ํ‘œํ˜„์‹๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React ์—˜๋ฆฌ๋จผํŠธ๋Š” JavaScript ๊ฐ์ฒด์ด๋ฉฐ ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ๊ทธ๋žจ ์—ฌ๊ธฐ์ €๊ธฐ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ShoppingList ์ปดํฌ๋„ŒํŠธ๋Š” <div />์™€ <li /> ๊ฐ™์€ ๋‚ด๊ฐ DOM ์ปดํฌ๋„ŒํŠธ๋งŒ์„ ๋ Œ๋”๋งํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ปค์Šคํ…€ React ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด <ShoppingList />๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋ชจ๋“  ์‡ผํ•‘ ๋ชฉ๋ก์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React ์ปดํฌ๋„ŒํŠธ๋Š” ์บก์Аํ™”๋˜์–ด ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ๋‹จ์ˆœํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ UI๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ์ฝ”๋“œ ์‚ดํŽด๋ณด๊ธฐ

๋ธŒ๋ผ์šฐ์ €์—์„œ ์ž์Šต์„œ ์ž‘์„ฑ์„ ํ•˜๋Š” ๊ฒฝ์šฐ ์ƒˆ ํƒญ์—์„œ ์ดˆ๊ธฐ ์ฝ”๋“œ๋ฅผ ์—ด์–ด์ฃผ์„ธ์š”. ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ์ง„ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ ํด๋”์—์„œ src/index.js๋ฅผ ์—ด์–ด์ฃผ์„ธ์š”(์ด ํŒŒ์ผ์€ ์„ค์ •์—์„œ ๋‹ค๋ฃฌ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค).

์ดˆ๊ธฐ ์ฝ”๋“œ๋Š” ์ œ์ž‘ํ•  ํ‹ฑํƒํ† ์˜ ๊ธฐ๋ณธ ํ‹€์ž…๋‹ˆ๋‹ค. CSS ์Šคํƒ€์ผ์€ ์ œ๊ณต๋˜๊ธฐ ๋•Œ๋ฌธ์— React๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ฒƒ๊ณผ ๊ฒŒ์ž„์„ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋Š” ๋ฐ์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์„ธ ๊ฐ€์ง€ React ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Square
  • Board
  • Game

Square ์ปดํฌ๋„ŒํŠธ๋Š” <button>์„ ๋ Œ๋”๋งํ•˜๊ณ  Board๋Š” ์‚ฌ๊ฐํ˜• 9๊ฐœ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. Game ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฒŒ์ž„ํŒ์„ ๋ Œ๋”๋งํ•˜๋ฉฐ ๋‚˜์ค‘์— ์ˆ˜์ •ํ•  ์ž๋ฆฌ ํ‘œ์‹œ์ž ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

Props๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ „๋‹ฌํ•˜๊ธฐ

๋ณธ๊ฒฉ์ ์œผ๋กœ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด Board ์ปดํฌ๋„ŒํŠธ์—์„œ Square ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด ๋ด…์‹œ๋‹ค.

์ž์Šต์„œ๋ฅผ ๋”ฐ๋ฅผ ๋•Œ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์†์œผ๋กœ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธธ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋ชธ์œผ๋กœ ๊ธฐ์–ตํ•˜๊ณ  ์ดํ•ด๋ ฅ์„ ๋” ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Square์— value prop์„ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด Board์˜ renderSquare ํ•จ์ˆ˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”.

class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i} />;  }
}

๊ฐ’์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด Square์˜ render ํ•จ์ˆ˜์—์„œ {/* TODO */}๋ฅผ {this.props.value}๋กœ ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”.

class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}      </button>
    );
  }
}

๋ณ€๊ฒฝ ์ „์—๋Š”

React Devtools

๋ณ€๊ฒฝ ํ›„์—๋Š” ๋ Œ๋”๋ง ๋œ ๊ฒฐ๊ณผ์—์„œ ๊ฐ ์‚ฌ๊ฐํ˜•์— ์ˆซ์ž๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

React Devtools

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๋ถ€๋ชจ Board ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ Square ์ปดํฌ๋„ŒํŠธ๋กœ โ€œprop์„ ์ „๋‹ฌโ€ํ–ˆ์Šต๋‹ˆ๋‹ค. props ์ „๋‹ฌํ•˜๊ธฐ๋Š” React ์•ฑ์—์„œ ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ์ •๋ณด๊ฐ€ ์–ด๋–ป๊ฒŒ ํ˜๋Ÿฌ๊ฐ€๋Š”์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

Square ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ฆญํ•˜๋ฉด โ€œXโ€๊ฐ€ ์ฒดํฌ๋˜๋„๋ก ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ๋จผ์ € Square ์ปดํฌ๋„ŒํŠธ์˜ render() ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฒ„ํŠผ ํƒœ๊ทธ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.

class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={function() { console.log('click'); }}>        {this.props.value}
      </button>
    );
  }
}

Square๋ฅผ ํด๋ฆญํ•˜๋ฉด โ€˜clickโ€™์ด ๋ธŒ๋ผ์šฐ์ € ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ์ฝ˜์†”์— ์ถœ๋ ฅ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜

ํƒ€์ดํ•‘ ํšŸ์ˆ˜๋ฅผ ์ค„์ด๊ณ  this์˜ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋™์ž‘์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜๋ถ€ํ„ฐ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

class Square extends React.Component {
 render() {
   return (
     <button className="square" onClick={() => console.log('click')}>       {this.props.value}
     </button>
   );
 }
}

onClick={() => console.log('click')}์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๋ฉด onClick prop์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. React๋Š” ํด๋ฆญํ–ˆ์„ ๋•Œ์—๋งŒ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. () =>์„ ์žŠ์–ด๋ฒ„๋ฆฌ๊ณ  onClick={console.log('click')}์ด๋ผ๊ณ  ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์‹ค์ˆ˜์ด๋ฉฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ๊ฒฝ๊ณ  ์ฐฝ์„ ๋„์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„๋กœ Square ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ฆญํ•œ ๊ฒƒ์„ โ€œ๊ธฐ์–ตํ•˜๊ฒŒโ€ ๋งŒ๋“ค์–ด โ€œXโ€ ํ‘œ์‹œ๋ฅผ ์ฑ„์›Œ ๋„ฃ์œผ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์–ธ๊ฐ€๋ฅผ โ€œ๊ธฐ์–ตํ•˜๊ธฐโ€์œ„ํ•ด component๋Š” state๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

React ์ปดํฌ๋„ŒํŠธ๋Š” ์ƒ์„ฑ์ž์— this.state๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ state๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. this.state๋Š” ์ •์˜๋œ React ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด ๋น„๊ณต๊ฐœ๋กœ ๊ฐ„์ฃผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ Square์˜ ํ˜„์žฌ ๊ฐ’์„ this.state์— ์ €์žฅํ•˜๊ณ  Square๋ฅผ ํด๋ฆญํ•˜๋Š” ๊ฒฝ์šฐ ๋ณ€๊ฒฝํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ์„  ํด๋ž˜์Šค์— ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ state๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

class Square extends React.Component {
  constructor(props) {    super(props);    this.state = {      value: null,    };  }
  render() {
    return (
      <button className="square" onClick={() => console.log('click')}>
        {this.props.value}
      </button>
    );
  }
}

์ฃผ์˜

JavaScript ํด๋ž˜์Šค์—์„œ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•  ๋•Œ ํ•ญ์ƒ super๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  React ์ปดํฌ๋„ŒํŠธ ํด๋ž˜์Šค๋Š” ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์งˆ ๋•Œ super(props) ํ˜ธ์ถœ ๊ตฌ๋ฌธ๋ถ€ํ„ฐ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ Square๋ฅผ ํด๋ฆญํ•  ๋•Œ ํ˜„์žฌ state ๊ฐ’์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด render ํ•จ์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • <button> ํƒœ๊ทธ ์•ˆ this.props.value๋ฅผ this.state.value๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.
  • onClick={...} ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ onClick={() => this.setState({value: 'X'})}๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.
  • ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด className๊ณผ onClick props๋ฅผ ๋ณ„๋„์˜ ์ค„์— ๋„ฃ์–ด์ฃผ์„ธ์š”.

์ด์™€ ๊ฐ™์€ ๋ณ€๊ฒฝ ํ›„์— Square์˜ render ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” <button> ํƒœ๊ทธ๋Š” ์•„๋ž˜์˜ ํ˜•ํƒœ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button
        className="square"        onClick={() => this.setState({value: 'X'})}      >
        {this.state.value}      </button>
    );
  }
}

Square์˜ render ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ onClick ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด this.setState๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์œผ๋กœ React์—๊ฒŒ <button>์„ ํด๋ฆญํ•  ๋•Œ Square๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์•Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ ์ดํ›„์— Square์˜ this.state.value๋Š” 'X'๊ฐ€ ๋˜์–ด ๊ฒŒ์ž„ ํŒ์—์„œ X๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค Square๋ฅผ ํด๋ฆญํ•˜๋˜ X๊ฐ€ ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ์—์„œ setState๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด React๋Š” ์ž๋™์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ ์—ญ์‹œ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

๊ฐœ๋ฐœ์ž ๋„๊ตฌ

Chrome๊ณผ Firefox์˜ React Devtools ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ € ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ React ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React Devtools

React DevTools๋ฅผ ํ†ตํ•ด React ์ปดํฌ๋„ŒํŠธ์˜ props์™€ state๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React DevTools๋ฅผ ์„ค์น˜ํ•œ ํ›„์— ํŽ˜์ด์ง€์˜ ๋ชจ๋“  ์—˜๋ฆฌ๋จผํŠธ์— ์˜ค๋ฅธ์ชฝ ํด๋ฆญ์„ ํ•˜๊ณ  โ€œ์š”์†Œ ๊ฒ€์‚ฌโ€๋ฅผ ํด๋ฆญํ•˜์—ฌ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ์—ด๋ฉด ํƒญ์˜ ์˜ค๋ฅธ์ชฝ ๋์— React ํƒญ(โ€œโš›๏ธ Componentsโ€์™€ โ€œโš›๏ธ Profilerโ€)์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด โ€œโš›๏ธ Componentsโ€๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.

๊ทธ๋Ÿฌ๋‚˜ CodePen์—์„œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  ๋ช‡ ๊ฐ€์ง€ ๋‹จ๊ณ„๊ฐ€ ์ถ”๊ฐ€๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋กœ๊ทธ์ธํ•˜์„ธ์š”. ๋˜๋Š” ๊ฐ€์ž… ํ›„ ์ด๋ฉ”์ผ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š” (์ŠคํŒธ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ํ•„์š”).
  2. โ€œForkโ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”.
  3. โ€œChange Viewโ€๋ฅผ ํด๋ฆญํ•˜์—ฌ โ€œDebug modeโ€๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”.
  4. ์ƒˆ ํƒญ์ด ์—ด๋ฆฌ๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ React ํƒญ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

๊ฒŒ์ž„ ์™„์„ฑํ•˜๊ธฐ

์ด์ œ ํ‹ฑํƒํ†  ๊ฒŒ์ž„์„ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์™„์ „ํ•œ ๊ฒŒ์ž„์„ ์œ„ํ•ด ๊ฒŒ์ž„ํŒ์˜ โ€œXโ€์™€ โ€œOโ€๋ฅผ ๋ฒˆ๊ฐˆ์•„ ํ‘œ์‹œํ•  ํ•„์š”๊ฐ€ ์žˆ์œผ๋ฉฐ ์Šน์ž๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

State ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ

ํ˜„์žฌ ๊ฒŒ์ž„์˜ state๋ฅผ ๊ฐ๊ฐ์˜ Square ์ปดํฌ๋„ŒํŠธ์—์„œ ์œ ์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์Šน์ž๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด 9๊ฐœ ์‚ฌ๊ฐํ˜•์˜ ๊ฐ’์„ ํ•œ ๊ณณ์— ์œ ์ง€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Board๊ฐ€ ๊ฐ Square์— Square์˜ state๋ฅผ ์š”์ฒญํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  React์—์„œ ์ด๋Ÿฐ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ๋Š” ํ•˜์ง€๋งŒ ์ด ๋ฐฉ์‹์€ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ณ  ๋ฒ„๊ทธ์— ์ทจ์•ฝํ•˜๋ฉฐ ๋ฆฌํŒฉํ† ๋ง์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ฒœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ Square๊ฐ€ ์•„๋‹Œ ๋ถ€๋ชจ Board ์ปดํฌ๋„ŒํŠธ์— ๊ฒŒ์ž„์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๊ฐ Square์— ์ˆซ์ž๋ฅผ ๋„˜๊ฒจ์ฃผ์—ˆ์„ ๋•Œ์™€ ๊ฐ™์ด Board ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐ Square์—๊ฒŒ prop์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฌด์—‡์„ ํ‘œ์‹œํ•  ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

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

state๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์€ React ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•  ๋•Œ ํ”ํžˆ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธฐํšŒ์— ์‹œํ—˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Board์— ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  9๊ฐœ์˜ ์‚ฌ๊ฐํ˜•์— ํ•ด๋‹นํ•˜๋Š” 9๊ฐœ์˜ null ๋ฐฐ์—ด์„ ์ดˆ๊ธฐ state๋กœ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

class Board extends React.Component {
  constructor(props) {    super(props);    this.state = {      squares: Array(9).fill(null),    };  }
  renderSquare(i) {
    return <Square value={i} />;
  }

๋‚˜์ค‘์— board๋ฅผ ์ฑ„์šฐ๋ฉด this.state.squares ๋ฐฐ์—ด์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

[
  'O', null, 'X',
  'X', 'X', 'O',
  'O', null, null,
]

Board์˜ renderSquare ํ•จ์ˆ˜๋Š” ํ˜„์žฌ ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

  renderSquare(i) {
    return <Square value={i} />;
  }

์ฒ˜์Œ์—๋Š” ๋ชจ๋“  Square์—์„œ 0๋ถ€ํ„ฐ 8๊นŒ์ง€ ์ˆซ์ž๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด Board์—์„œ value prop์„ ์ž์‹์œผ๋กœ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ์ด์ „ ๋‹จ๊ณ„์—์„œ๋Š” ์ˆซ์ž๋ฅผ Square์˜ ์ž์ฒด state์— ๋”ฐ๋ผ โ€œXโ€ ํ‘œ์‹œ๋กœ ๋ฐ”๊พธ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ Square๋Š” Board์—์„œ ์ „๋‹ฌํ•œ value prop์„ ๋ฌด์‹œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ prop์„ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค์‹œ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ Square์—๊ฒŒ ํ˜„์žฌ ๊ฐ’('X', 'O', ๋˜๋Š” null)์„ ํ‘œํ˜„ํ•˜๋„๋ก Board๋ฅผ ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Board์˜ ์ƒ์„ฑ์ž์—์„œ squares ๋ฐฐ์—ด์„ ์ด๋ฏธ ์„ ์–ธํ–ˆ์œผ๋ฉฐ renderSquare ํ•จ์ˆ˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  renderSquare(i) {
    return <Square value={this.state.squares[i]} />;  }

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

Square๋Š” ์ด์ œ ๋นˆ ์‚ฌ๊ฐํ˜•์— 'X', 'O', ๋˜๋Š” null์ธ value prop์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ Square๋ฅผ ํด๋ฆญํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ณ€ํ™”๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. Board ์ปดํฌ๋„ŒํŠธ๋Š” ์–ด๋–ค ์‚ฌ๊ฐํ˜•์ด ์ฑ„์›Œ์กŒ๋Š”์ง€๋ฅผ ์—ฌ๋ถ€๋ฅผ ๊ด€๋ฆฌํ•˜๋ฏ€๋กœ Square๊ฐ€ Board๋ฅผ ๋ณ€๊ฒฝํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹ ์ด ์ •์˜ํ•œ state์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Square์—์„œ Board์˜ state๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋Œ€์‹ ์— Board์—์„œ Square๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ  Square๋Š” ์‚ฌ๊ฐํ˜•์„ ํด๋ฆญํ•  ๋•Œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ Board์˜ renderSquare ํ•จ์ˆ˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.

  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}      />
    );
  }

์ฃผ์˜

๋ฐ˜ํ™˜๋˜๋Š” ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์—ฌ๋Ÿฌ ์ค„๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ€๋…์„ฑ์„ ํ™•๋ณดํ•˜์˜€๊ณ  ๊ด„ํ˜ธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ JavaScript๊ฐ€ return ๋’ค์— ์„ธ๋ฏธ์ฝœ๋ก ์„ ์‚ฝ์ž…ํ•˜์ง€ ์•Š์•„๋„ ์ฝ”๋“œ๊ฐ€ ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด์ œ Board์—์„œ Square๋กœ value์™€ onClick ๋‘ ๊ฐœ์˜ props๋ฅผ ์ „๋‹ฌํ•˜์˜€์Šต๋‹ˆ๋‹ค. onClick prop์€ Square๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. Square๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.

  • Square์˜ render ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this.state.value๋ฅผ this.props.value๋กœ ๋ฐ”๊พธ์–ด์ฃผ์„ธ์š”.
  • Square์˜ render ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this.setState()๋ฅผ this.props.onClick()์œผ๋กœ ๋ฐ”๊พธ์–ด์ฃผ์„ธ์š”.
  • Square๋Š” ๊ฒŒ์ž„์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— constructor๋ฅผ ์ง€์›Œ์ฃผ์„ธ์š”.

์ด๋ ‡๊ฒŒ ๋ฐ”๊พผ ํ›„์— Square๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ชจ์Šต์ด ๋ฉ๋‹ˆ๋‹ค.

class Square extends React.Component {  render() {    return (
      <button
        className="square"
        onClick={() => this.props.onClick()}      >
        {this.props.value}      </button>
    );
  }
}

Square๋ฅผ ํด๋ฆญํ•˜๋ฉด Board์—์„œ ๋„˜๊ฒจ๋ฐ›์€ onClick ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์ผ์–ด๋‚˜๋Š” ์ผ์„ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. ๋‚ด์žฅ๋œ DOM <button> ์ปดํฌ๋„ŒํŠธ์— ์žˆ๋Š” onClick prop์€ React์—๊ฒŒ ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์„ค์ •ํ•˜๋ผ๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
  2. ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด React๋Š” Square์˜ render() ํ•จ์ˆ˜์— ์ •์˜๋œ onClick ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” this.props.onClick()๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. Square์˜ onClick prop์€ Board์—์„œ ์ •์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  4. Board์—์„œ Square๋กœ onClick={() => this.handleClick(i)}๋ฅผ ์ „๋‹ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Square๋ฅผ ํด๋ฆญํ•˜๋ฉด Board์˜ handleClick(i)๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  5. ์•„์ง handleClick()๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ๊นจ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์‚ฌ๊ฐํ˜•์„ ํด๋ฆญํ•˜๋ฉด โ€œthis.handleClick is not a functionโ€๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•˜๋Š” ๋ถ‰์€ ์—๋Ÿฌ ํ™”๋ฉด์„ ๋ณด๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์˜

DOM <button> ์—˜๋ฆฌ๋จผํŠธ์˜ onClick ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” ๋‚ด์žฅ๋œ ์ปดํฌ๋„ŒํŠธ๋ผ๋Š” ์ ์—์„œ React์—๊ฒŒ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Square๊ฐ™์€ ์‚ฌ์šฉ์ž ์ •์˜ ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ ์ด๋ฆ„ ์ง€์ •์€ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค. Square์˜ onClick prop์ด๋‚˜ Board์˜ handleClick ํ•จ์ˆ˜์—๋Š” ์–ด๋–ค ์ด๋ฆ„๋„ ๋ถ™์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ฝ”๋“œ๋Š” ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. React์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” prop์—๋Š” on[Event], ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜์—๋Š” handle[Event]๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.

handleClick์„ ์•„์ง ์ •์˜ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— Square๋ฅผ ํด๋ฆญํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ Board ํด๋ž˜์Šค์— handleClick์„ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }

  handleClick(i) {    const squares = this.state.squares.slice();    squares[i] = 'X';    this.setState({squares: squares});  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const status = 'Next player: X';

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

์ด์ œ ์ด์ „๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Square๋ฅผ ํด๋ฆญํ•˜์—ฌ ์‚ฌ๊ฐํ˜•์„ ์ฑ„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์ œ๋Š” state๊ฐ€ ๊ฐ Square ์ปดํฌ๋„ŒํŠธ ๋Œ€์‹ ์— Board ์ปดํฌ๋„ŒํŠธ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. Board์˜ ์ƒํƒœ๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ Square ์ปดํฌ๋„ŒํŠธ๋Š” ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. Board ์ปดํฌ๋„ŒํŠธ์˜ ๋ชจ๋“  ์‚ฌ๊ฐํ˜•์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ดํ›„์— ์Šน์ž๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Square ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋” ์ด์ƒ state๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Square ์ปดํฌ๋„ŒํŠธ๋Š” Board ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ’์„ ๋ฐ›์•„ ํด๋ฆญ๋  ๋•Œ Board ์ปดํฌ๋„ŒํŠธ๋กœ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. React ์šฉ์–ด๋กœ Square ์ปดํฌ๋„ŒํŠธ๋Š” ์ด์ œ ์ œ์–ด๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. Board๋Š” ์ด๋“ค์„ ์™„์ „ํžˆ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

handleClick์—์„œ๋Š” .slice()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธฐ์กด ๋ฐฐ์—ด์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  squares ๋ฐฐ์—ด์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•˜์—ฌ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•ด์ฃผ์„ธ์š”. ์™œ squares ๋ฐฐ์—ด์˜ ์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•˜์˜€๋Š”์ง€ ๋‹ค์Œ ๋‹จ๋ฝ์—์„œ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ถˆ๋ณ€์„ฑ์ด ์™œ ์ค‘์š”ํ• ๊นŒ์š”?

์ด์ „ ์ฝ”๋“œ ์˜ˆ์‹œ์—์„œ ๊ธฐ์กด ๋ฐฐ์—ด์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ .slice() ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ squares ๋ฐฐ์—ด์˜ ์‚ฌ๋ณธ ๋งŒ๋“ค๊ธฐ๋ฅผ ์ถ”์ฒœํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๋ถ€ํ„ฐ ๋ถˆ๋ณ€์„ฑ์ด ๋ฌด์—‡์ธ์ง€์™€ ์™œ ๋ถˆ๋ณ€์„ฑ์ด ์ค‘์š”ํ•œ์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ๋Š” ์›ํ•˜๋Š” ๋ณ€๊ฒฝ ๊ฐ’์„ ๊ฐ€์ง„ ์ƒˆ๋กœ์šด ์‚ฌ๋ณธ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ์ฒด ๋ณ€๊ฒฝ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ

var player = {score: 1, name: 'Jeff'};
player.score = 2;
// ์ด์ œ player๋Š” {score: 2, name: 'Jeff'}์ž…๋‹ˆ๋‹ค.

๊ฐ์ฒด ๋ณ€๊ฒฝ ์—†์ด ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ

var player = {score: 1, name: 'Jeff'};

var newPlayer = Object.assign({}, player, {score: 2});
// ์ด์ œ player๋Š” ๋ณ€ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ newPlayer๋Š” {score: 2, name: 'Jeff'}์ž…๋‹ˆ๋‹ค.

// ๊ฐ์ฒด spread ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
// var newPlayer = {...player, score: 2};

์ตœ์ข… ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜์ง€๋งŒ ์ง์ ‘์ ์ธ ๊ฐ์ฒด ๋ณ€๊ฒฝ์ด๋‚˜ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•„๋ž˜์— ๊ธฐ์ˆ ๋œ ๋ช‡ ๊ฐ€์ง€ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณต์žกํ•œ ํŠน์ง•๋“ค์„ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ฆ

๋ถˆ๋ณ€์„ฑ์€ ๋ณต์žกํ•œ ํŠน์ง•๋“ค์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ž์Šต์„œ์—์„œ๋Š” โ€œ์‹œ๊ฐ„ ์—ฌํ–‰โ€ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์—ฌ ํ‹ฑํƒํ†  ๊ฒŒ์ž„์˜ ์ด๋ ฅ์„ ํ™•์ธํ•˜๊ณ  ์ด์ „ ๋™์ž‘์œผ๋กœ โ€œ๋˜๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹คโ€. ์ด ๊ธฐ๋Šฅ์€ ๊ฒŒ์ž„์—๋งŒ ๊ตญํ•œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŠน์ • ํ–‰๋™์„ ์ทจ์†Œํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ผ๋ฐ˜์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ ์ž…๋‹ˆ๋‹ค. ์ง์ ‘์ ์ธ ๋ฐ์ดํ„ฐ ๋ณ€์ด๋ฅผ ํ”ผํ•˜๋Š” ๊ฒƒ์€ ์ด์ „ ๋ฒ„์ „์˜ ๊ฒŒ์ž„ ์ด๋ ฅ์„ ์œ ์ง€ํ•˜๊ณ  ๋‚˜์ค‘์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•จ

๊ฐ์ฒด๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ์ˆ˜์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์ œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด์—์„œ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๊ฐ์ง€๋Š” ๋ณต์ œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋ฅผ ์ด์ „ ์‚ฌ๋ณธ๊ณผ ๋น„๊ตํ•˜๊ณ  ์ „์ฒด ๊ฐ์ฒด ํŠธ๋ฆฌ๋ฅผ ๋Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ถˆ๋ณ€ ๊ฐ์ฒด์—์„œ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๊ฒƒ์€ ์ƒ๋‹นํžˆ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๊ฐ€ ์ด์ „ ๊ฐ์ฒด์™€ ๋‹ค๋ฅด๋‹ค๋ฉด ๊ฐ์ฒด๋Š” ๋ณ€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React์—์„œ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋Š” ์‹œ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•จ

๋ถˆ๋ณ€์„ฑ์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์€ React์—์„œ ์ˆœ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋ณ€๊ฒฝ์ด ์ด๋ฃจ์–ด์กŒ๋Š”์ง€ ์‰ฝ๊ฒŒ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋งํ• ์ง€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

shouldComponentUpdate()์™€ ์ˆœ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™”ํ•˜๊ธฐ๋ฅผ ๋ณด์„ธ์š”.

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ

์ด์ œ Square๋ฅผ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ”๊ฟ”๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

React์—์„œ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ state ์—†์ด render ํ•จ์ˆ˜๋งŒ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. React.Component๋ฅผ ํ™•์žฅํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๋Œ€์‹  props๋ฅผ ์ž…๋ ฅ๋ฐ›์•„์„œ ๋ Œ๋”๋งํ•  ๋Œ€์ƒ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ž˜์Šค๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Square ํด๋ž˜์Šค๋ฅผ ์•„๋ž˜์˜ ํ•จ์ˆ˜๋กœ ๋ฐ”๊ฟ”๋ณด์„ธ์š”.

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

๋ชจ๋“  this.props๋ฅผ props๋กœ ๋ณ€๊ฒฝํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

์ฃผ์˜

Square๋ฅผ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋กœ ์ˆ˜์ •ํ–ˆ์„ ๋•Œ onClick={() => this.props.onClick()}์„ onClick={props.onClick}๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์–‘์ชฝ ๋ชจ๋‘ ๊ด„ํ˜ธ๊ฐ€ ์‚ฌ๋ผ์ง„ ๊ฒƒ์— ์ฃผ๋ชฉํ•ด์ฃผ์„ธ์š”.

์ˆœ์„œ ๋งŒ๋“ค๊ธฐ

์šฐ๋ฆฌ์˜ ํ‹ฑํƒํ†  ๊ฒŒ์ž„์ด ๊ฐ€์ง„ ํฐ ๋ฌธ์ œ์ ์„ ๊ณ ์น  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ๊ฒŒ์ž„ํŒ์—์„œ โ€œOโ€๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ์ ์ด์ฃ .

์ฒซ ๋ฒˆ์งธ ์ฐจ๋ก€๋ฅผ โ€œXโ€๋กœ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Board ์ƒ์„ฑ์ž์˜ ์ดˆ๊ธฐ state๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,    };
  }

ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ˆ˜๋ฅผ ๋‘˜ ๋•Œ๋งˆ๋‹ค xIsNext (boolean ๊ฐ’)์ด ๋’ค์ง‘ํ˜€ ๋‹ค์Œ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋ˆ„๊ตฐ์ง€ ๊ฒฐ์ •ํ•˜๊ณ  ๊ฒŒ์ž„์˜ state๊ฐ€ ์ €์žฅ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Board์˜ handleClick ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ xIsNext ๊ฐ’์„ ๋’ค์ง‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,    });
  }

์ด์ œ โ€œXโ€์™€ โ€œOโ€๋Š” ๋ฒˆ๊ฐˆ์•„ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ์‹œ๋„ํ•ด๋ณด์„ธ์š”!

Board์˜ render ์•ˆ์— ์žˆ๋Š” โ€œstatusโ€ ํ…์ŠคํŠธ๋„ ๋ฐ”๊ฟ”์„œ ์–ด๋А ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋‹ค์Œ ์ฐจ๋ก€์ธ์ง€ ์•Œ๋ ค์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    return (
      // ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ ์šฉํ•˜๋ฉด Board ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();    squares[i] = this.state.xIsNext ? 'X' : 'O';    this.setState({      squares: squares,      xIsNext: !this.state.xIsNext,    });  }

  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

์Šน์ž ๊ฒฐ์ •ํ•˜๊ธฐ

์ด์ œ ์–ด๋–ค ์„ ์ˆ˜๊ฐ€ ๋‹ค์Œ ์ฐจ๋ก€์ธ์ง€ ์•Œ๋ ค์ฃผ์—ˆ์œผ๋‹ˆ ์Šน๋ถ€๊ฐ€ ๋‚˜๋Š” ๋•Œ์™€ ๋” ์ด์ƒ ๋‘˜ ๊ณณ์ด ์—†์„ ๋•Œ๋ฅผ ์•Œ๋ ค์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์˜ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ํŒŒ์ผ ์ตœํ•˜๋‹จ์— ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”.

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

9๊ฐœ์˜ ์‚ฌ๊ฐํ˜•์˜ ๋ฐฐ์—ด์„ ๊ฐ€์ง€๊ณ  ํ•จ์ˆ˜๋Š” ์Šน์ž๋ฅผ ํ™•์ธํ•˜์—ฌ ์ ์ ˆํ•œ ๊ฐ’์œผ๋กœ 'X', 'O', ๋˜๋Š” null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์šฐ์Šนํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด Board์˜ render ํ•จ์ˆ˜์—์„œ calculateWinner(squares)๋ฅผ ํ˜ธ์ถœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ด๊ธด๋‹ค๋ฉด โ€œWinner: Xโ€ ๋˜๋Š” โ€œWinner: Oโ€ ๊ฐ™์€ ๋ฌธ๊ตฌ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Board์˜ render ํ•จ์ˆ˜์—์„œ ์„ ์–ธํ•œ status๋ฅผ ์•„๋ž˜ ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ”์ฃผ์„ธ์š”.

  render() {
    const winner = calculateWinner(this.state.squares);    let status;    if (winner) {      status = 'Winner: ' + winner;    } else {      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');    }
    return (
      // ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์Šน๋ฆฌํ•˜๊ฑฐ๋‚˜ Square๊ฐ€ ์ด๋ฏธ ์ฑ„์›Œ์กŒ๋‹ค๋ฉด Board์˜ handleClick ํ•จ์ˆ˜๊ฐ€ ํด๋ฆญ์„ ๋ฌด์‹œํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {      return;    }    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š” ํ‹ฑํƒํ†  ๊ฒŒ์ž„์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  React์˜ ๊ธฐ๋ณธ๋„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ง„์ •ํ•œ ์Šน์ž๋Š” ์—ฌ๋Ÿฌ๋ถ„์ธ ๊ฒƒ ๊ฐ™๋„ค์š”.

์‹œ๊ฐ„ ์—ฌํ–‰ ์ถ”๊ฐ€ํ•˜๊ธฐ

๋งˆ์ง€๋ง‰ ์—ฐ์Šต์œผ๋กœ ๊ฒฝ๊ธฐ์—์„œ ์ด์ „ ์ฐจ๋ก€๋กœ โ€œ์‹œ๊ฐ„์„ ๋˜๋Œ๋ฆฌ๊ธฐโ€๋ฅผ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

๋™์ž‘์— ๋Œ€ํ•œ ๊ธฐ๋ก ์ €์žฅํ•˜๊ธฐ

squares ๋ฐฐ์—ด์„ ์ง์ ‘ ๋ณ€๊ฒฝํ–ˆ๋‹ค๋ฉด ์‹œ๊ฐ„ ์—ฌํ–‰์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์› ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ slice()๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งค ๋™์ž‘ ์ดํ›„์— squares ๋ฐฐ์—ด์˜ ์ƒˆ๋กœ์šด ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์—ˆ๊ณ  ์ด๋ฅผ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ์ทจ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ณผ๊ฑฐ์˜ squares ๋ฐฐ์—ด์˜ ๋ชจ๋“  ๋ฒ„์ „์„ ์ €์žฅํ•˜๊ณ  ์ด๋ฏธ ์ง€๋‚˜๊ฐ„ ์ฐจ๋ก€๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณผ๊ฑฐ์˜ squares ๋ฐฐ์—ด๋“ค์„ history๋ผ๋Š” ๋‹ค๋ฅธ ๋ฐฐ์—ด์— ์ €์žฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. history ๋ฐฐ์—ด์€ ์ฒซ ๋™์ž‘๋ถ€ํ„ฐ ๋งˆ์ง€๋ง‰ ๋™์ž‘๊นŒ์ง€ ๋ชจ๋“  ๊ฒŒ์ž„ํŒ์˜ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

history = [
  // ์ฒซ ๋™์ž‘์ด ๋ฐœ์ƒํ•˜๊ธฐ ์ „
  {
    squares: [
      null, null, null,
      null, null, null,
      null, null, null,
    ]
  },
  // ์ฒซ ๋™์ž‘์ด ๋ฐœ์ƒํ•œ ์ดํ›„
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, null,
    ]
  },
  // ๋‘ ๋ฒˆ์งธ ๋™์ž‘์ด ๋ฐœ์ƒํ•œ ์ดํ›„
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, 'O',
    ]
  },
  // ...
]

์ด์ œ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๊ฐ€ history state๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ State ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ

์ด์ „ ๋™์ž‘์— ๋Œ€ํ•œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋ ค๋ฉด ์ตœ์ƒ์œ„ ๋‹จ๊ณ„์˜ Game ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. history๋ฅผ ์ด์šฉํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ƒ์œ„ ๋‹จ๊ณ„ Game ์ปดํฌ๋„ŒํŠธ์— history state๋ฅผ ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

history state๋ฅผ Game ์ปดํฌ๋„ŒํŠธ์— ๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž์‹ Board ์ปดํฌ๋„ŒํŠธ์—์„œ squares state๋ฅผ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. Square ์ปดํฌ๋„ŒํŠธ์—์„œ Board ์ปดํฌ๋„ŒํŠธ๋กœ โ€œstate๋ฅผ ๋Œ์–ด์˜ฌ๋ ธ๋˜ ๊ฒƒโ€ ์ฒ˜๋Ÿผ ์ด๋ฒˆ์—๋Š” Board์—์„œ ์ตœ์ƒ์œ„ ๋‹จ๊ณ„ Game ์ปดํฌ๋„ŒํŠธ๋กœ state๋ฅผ ๋Œ์–ด์˜ฌ๋ ธ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Game ์ปดํฌ๋„ŒํŠธ๋Š” Board์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์™„๋ฒฝํžˆ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ history์— ์ €์žฅ๋œ ๊ณผ๊ฑฐ์˜ ์ฐจ๋ก€๋ฅผ Board๊ฐ€ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์šฐ์„  Game ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ์„ฑ์ž ์•ˆ์— ์ดˆ๊ธฐ state๋ฅผ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

class Game extends React.Component {
  constructor(props) {    super(props);    this.state = {      history: [{        squares: Array(9).fill(null),      }],      xIsNext: true,    };  }
  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
        <div className="game-info">
          <div>{/* status */}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }
}

๋‹ค์Œ์œผ๋กœ Game ์ปดํฌ๋„ŒํŠธ์—์„œ Board ์ปดํฌ๋„ŒํŠธ๋กœ squares์™€ onClick props๋ฅผ ์ „๋‹ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Board์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ Square์— ์“ฐ์ผ ๋‹จ์ผ ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์กŒ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ Square์˜ ์œ„์น˜๋ฅผ onClick ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ๋„˜๊ฒจ์ฃผ์–ด ์–ด๋–ค Square๋ฅผ ํด๋ฆญํ–ˆ๋Š”์ง€ ํ‘œ์‹œํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Board ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • constructor๋ฅผ Board์—์„œ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”.
  • Board์˜ renderSquare ์•ˆ์˜ this.state.squares[i]๋ฅผ this.props.squares[i]๋กœ ๋ฐ”๊ฟ”์ฃผ์„ธ์š”.
  • Board์˜ renderSquare ์•ˆ์˜ this.handleClick(i)์„ this.props.onClick(i)์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์„ธ์š”.

์ด์ œ Board ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

class Board extends React.Component {
  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}        onClick={() => this.props.onClick(i)}      />
    );
  }

  render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

Game ์ปดํฌ๋„ŒํŠธ์˜ render ํ•จ์ˆ˜๋ฅผ ๊ฐ€์žฅ ์ตœ๊ทผ ๊ธฐ๋ก์„ ์‚ฌ์šฉํ•˜๋„๋ก ์—…๋ฐ์ดํŠธํ•˜์—ฌ ๊ฒŒ์ž„์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ํ‘œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  render() {
    const history = this.state.history;    const current = history[history.length - 1];    const winner = calculateWinner(current.squares);    let status;    if (winner) {      status = 'Winner: ' + winner;    } else {      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');    }
    return (
      <div className="game">
        <div className="game-board">
          <Board            squares={current.squares}            onClick={(i) => this.handleClick(i)}          />        </div>
        <div className="game-info">
          <div>{status}</div>          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }

Game ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฒŒ์ž„์˜ ์ƒํƒœ๋ฅผ ๋ Œ๋”๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์— Board์˜ render ํ•จ์ˆ˜์—์„œ ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌํŽ™ํ† ๋ง ์ดํ›„์— Board์˜ render ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  render() {    return (      <div>        <div className="board-row">          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }

๋งˆ์ง€๋ง‰์œผ๋กœ handleClick ํ•จ์ˆ˜๋ฅผ Board์—์„œ Game ์ปดํฌ๋„ŒํŠธ๋กœ ์ด๋™ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ Game ์ปดํฌ๋„ŒํŠธ์˜ state๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— handleClick์„ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Game์˜ handleClick ํ•จ์ˆ˜์—์„œ ์ƒˆ๋กœ์šด ๊ธฐ๋ก ๋ชฉ๋ก์„ history๋กœ ์—ฐ๊ฒฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  handleClick(i) {
    const history = this.state.history;    const current = history[history.length - 1];    const squares = current.squares.slice();    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{        squares: squares,      }]),      xIsNext: !this.state.xIsNext,
    });
  }

์ฃผ์˜

๋ฐฐ์—ด push() ํ•จ์ˆ˜์™€ ๊ฐ™์ด ๋” ์ต์ˆ™ํ•œ ๋ฐฉ์‹๊ณผ ๋‹ฌ๋ฆฌ concat() ํ•จ์ˆ˜๋Š” ๊ธฐ์กด ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋” ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ์‹œ์ ์—์„œ Board ์ปดํฌ๋„ŒํŠธ๋Š” renderSquare์™€ render ํ•จ์ˆ˜๋งŒ์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒŒ์ž„์˜ ์ƒํƒœ์™€ handleClick ํ•จ์ˆ˜๋Š” Game ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

๊ณผ๊ฑฐ์˜ ์ด๋™ ํ‘œ์‹œํ•˜๊ธฐ

ํ‹ฑํƒํ†  ๊ฒŒ์ž„์˜ ์ด๋™ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ œ ํ”Œ๋ ˆ์ด์–ด์—๊ฒŒ ๊ณผ๊ฑฐ์˜ ์ด๋™์„ ๋ชฉ๋ก์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ž์—์„œ React ์—˜๋ฆฌ๋จผํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šคํ˜• JavaScript ๊ฐ์ฒด๋ผ๋Š” ๊ฒƒ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. React ์—˜๋ฆฌ๋จผํŠธ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์•„์ดํ…œ์„ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JavaScript์—์„œ ๋ฐฐ์—ด์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๋งคํ•‘ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” map() ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

map ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋™ ๊ธฐ๋ก์„ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” React ๋ฒ„ํŠผ ์—˜๋ฆฌ๋จผํŠธ๋กœ ๋งตํ•‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ณผ๊ฑฐ์˜ ์ด๋™์œผ๋กœ โ€œ๋Œ์•„๊ฐ€๋Š”โ€ ๋ฒ„ํŠผ ๋ชฉ๋ก์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ์ž„์˜ render ํ•จ์ˆ˜์—์„œ history๋ฅผ map ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {      const desc = move ?        'Go to move #' + move :        'Go to game start';      return (        <li>          <button onClick={() => this.jumpTo(move)}>{desc}</button>        </li>      );    });
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>        </div>
      </div>
    );
  }

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

history ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉด์„œ step ๋ณ€์ˆ˜๋Š” ํ˜„์žฌ history ์š”์†Œ์˜ ๊ฐ’์„ ์ฐธ์กฐํ•˜๋ฉฐ move๋Š” ํ˜„์žฌ history ์š”์†Œ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ move์—๋งŒ ๊ด€์‹ฌ์ด ์žˆ์œผ๋ฏ€๋กœ step์€ ๋‹ค๋ฅธ ๊ณณ์— ํ• ๋‹น๋˜์ง„ ์•Š์Šต๋‹ˆ๋‹ค.

ํ‹ฑํƒํ†  ๊ฒŒ์ž„ ๊ธฐ๋ก์˜ ๊ฐ๊ฐ ์ด๋™๋งˆ๋‹ค ๋ฒ„ํŠผ <button>์„ ํฌํ•จํ•˜๋Š” ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ <li>๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„ํŠผ์€ this.jumpTo() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” onClick ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ง์€ jumpTo() ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ์ƒํƒœ์—์„œ ๊ฒŒ์ž„์˜ ์ด๋™ ๋ชฉ๋ก์€ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ๊ณ ๋ฅผ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์ฝ˜์†”์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๊ฒฝ๊ณ  ๋ฐฐ์—ด์ด๋‚˜ ์ดํ„ฐ๋ ˆ์ดํ„ฐ์˜ ์ž์‹๋“ค์€ ๊ณ ์œ ์˜ โ€œkeyโ€ prop์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. โ€œGameโ€์˜ render ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

์œ„์˜ ๊ฒฝ๊ณ ๊ฐ€ ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์–˜๊ธฐํ•ด๋ด…์‹œ๋‹ค.

Key ์„ ํƒํ•˜๊ธฐ

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

์•„๋ž˜์˜ ์ฝ”๋“œ๊ฐ€

<li>Alexa: 7 tasks left</li>
<li>Ben: 5 tasks left</li>

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค.

<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>

์‚ฌ๋žŒ์˜ ๋ˆˆ์—๋Š” task ๊ฐœ์ˆ˜๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์—ˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ Alexa์™€ Ben์˜ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๊ณ  Claudia๊ฐ€ ๋‘ ์‚ฌ๋žŒ ์‚ฌ์ด์— ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ React๋Š” ์ปดํ“จํ„ฐ ํ”„๋กœ๊ทธ๋žจ์ด๋ฉฐ ์‚ฌ๋žŒ์ด ์˜๋„ํ•œ ๋ฐ”๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์— key prop์„ ์ง€์ •ํ•˜์—ฌ ๊ฐ ์•„์ดํ…œ์ด ๋‹ค๋ฅธ ์•„์ดํ…œ๋“ค๊ณผ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ‚ค๋ฅผ ์ง€์ •ํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ alexa, ben, claudia ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ํ‘œ์‹œํ•œ๋‹ค๋ฉด Alexa, Ben, Claudia์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ID๊ฐ€ ํ‚ค๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>

๋ชฉ๋ก์„ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋ฉด React๋Š” ๊ฐ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์˜ ํ‚ค๋ฅผ ๊ฐ€์ ธ๊ฐ€๋ฉฐ ์ด์ „ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์—์„œ ์ผ์น˜ํ•˜๋Š” ํ‚ค๋ฅผ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฆฌ์ŠคํŠธ์—์„œ ์ด์ „์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด React๋Š” ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ด์ „ ๋ฆฌ์ŠคํŠธ์— ์กด์žฌํ–ˆ๋˜ ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด React๋Š” ๊ทธ ํ‚ค๋ฅผ ๊ฐ€์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํ‚ค๊ฐ€ ์ผ์น˜ํ•œ๋‹ค๋ฉด ํ•ด๋‹น ๊ตฌ์„ฑ์š”์†Œ๋Š” ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ํ‚ค๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ React์—๊ฒŒ ๋‹ค์‹œ ๋ Œ๋”๋งํ•  ๋•Œ state๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ ํ‚ค๊ฐ€ ๋ณ€ํ•œ๋‹ค๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” ์ œ๊ฑฐ๋˜๊ณ  ์ƒˆ๋กœ์šด state์™€ ํ•จ๊ป˜ ๋‹ค์‹œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

React์—์„œ key๋Š” ์‹ฌํ™” ๊ธฐ๋Šฅ์ธ ref์™€ ๋™์ผํ•˜๊ฒŒ ํŠน๋ณ„ํ•˜๊ณ  ๋ฏธ๋ฆฌ ์ง€์ •๋œ prop์ž…๋‹ˆ๋‹ค. ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด React๋Š” key ์†์„ฑ์„ ์ถ”์ถœํ•˜์—ฌ ๋ฐ˜ํ™˜๋˜๋Š” ์—˜๋ฆฌ๋จผํŠธ์— ์ง์ ‘ ํ‚ค๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. key๊ฐ€ props์— ์†ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ this.props.key๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. React๋Š” ์ž๋™์œผ๋กœ key๋ฅผ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ง€ ํŒ๋‹จํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” key๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

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

ํ‚ค๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ React๋Š” ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•˜๋ฉฐ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๊ธฐ๋ณธ ํ‚ค๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ์•„์ดํ…œ์„ ์ถ”๊ฐ€/์ œ๊ฑฐ ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ key={i}๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๊ฒฝ๊ณ ๊ฐ€ ๋‚˜ํƒ€๋‚˜์ง€๋Š” ์•Š์ง€๋งŒ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ์ถ”์ฒœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ‚ค๋Š” ์ „์—ญ์—์„œ ๊ณ ์œ ํ•  ํ•„์š”๋Š” ์—†์œผ๋ฉฐ ์ปดํฌ๋„ŒํŠธ์™€ ๊ด€๋ จ ์•„์ดํ…œ ์‚ฌ์ด์—์„œ๋Š” ๊ณ ์œ ํ•œ ๊ฐ’์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„ ์—ฌํ–‰ ๊ตฌํ˜„ํ•˜๊ธฐ

ํ‹ฑํƒํ†  ๊ฒŒ์ž„์˜ ๊ธฐ๋ก์—์„œ ๊ณผ๊ฑฐ์˜ ์ด๋™ ์ •๋ณด๋Š” ์ด๋™์˜ ์ˆœ์ฐจ์ ์ธ ์ˆซ์ž๋ฅผ ๊ณ ์œ ํ•œ ID๋กœ ๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค. ์ด๋™์€ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜๊ฑฐ๋‚˜ ์ค‘๊ฐ„์— ์‚ฝ์ž…๋  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋™์˜ ์ธ๋ฑ์Šค๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•ด๋„ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

Game ์ปดํฌ๋„ŒํŠธ์˜ render ํ•จ์ˆ˜ ์•ˆ์—์„œ <li key={move}>๋กœ ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด React์˜ ํ‚ค์— ๋Œ€ํ•œ ๊ฒฝ๊ณ ๊ฐ€ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key={move}>          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

jumpTo ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜์–ด์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. jumpTo๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „์— Game ์ปดํฌ๋„ŒํŠธ์˜ state์— stepNumber๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ˜„์žฌ ์ง„ํ–‰ ์ค‘์ธ ๋‹จ๊ณ„๋ฅผ ํ‘œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € Game์˜ constructor ์ดˆ๊ธฐ state๋กœ stepNumber: 0์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      stepNumber: 0,      xIsNext: true,
    };
  }

๋‹ค์Œ์œผ๋กœ Game์˜ stepNumber๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด jumpTo๋ฅผ ์ •์˜ํ•ด์ฃผ์„ธ์š”. ๋˜ํ•œ stepNumber๊ฐ€ ์ง์ˆ˜์ผ ๋•Œ ๋งˆ๋‹ค xIsNext๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  handleClick(i) {
    // ์ด ํ•จ์ˆ˜๋Š” ๋ณ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  }

  jumpTo(step) {    this.setState({      stepNumber: step,      xIsNext: (step % 2) === 0,    });  }
  render() {
    // ์ด ํ•จ์ˆ˜๋Š” ๋ณ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  }

jumpTo ํ•จ์ˆ˜์—์„œ state์˜ history ํ”„๋กœํผํ‹ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์•˜์Œ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. ์ด๋Š” state์˜ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ณ‘ํ•ฉ๋˜๊ฑฐ๋‚˜ ๊ฐ„๋‹จํžˆ ๋งํ•ด React๋Š” ๋‚˜๋จธ์ง€ state๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  setState ํ•จ์ˆ˜์— ์–ธ๊ธ‰๋œ ํ”„๋กœํผํ‹ฐ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด์ œ ์‚ฌ๊ฐํ˜•์„ ํด๋ฆญํ•  ๋•Œ ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” Game์˜ handleClick ํ•จ์ˆ˜์— ๋ช‡ ๊ฐ€์ง€ ๋ณ€ํ™”๋ฅผ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

stepNumber state๋Š” ํ˜„์žฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋˜๋Š” ์ด๋™์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์ด๋™์„ ๋งŒ๋“  ํ›„์— this.setState์˜ ์ธ์ž๋กœ stepNumber: history.length๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ stepNumber๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด ์ด๋™์ด ์ƒ์„ฑ๋œ ํ›„์— ์ด๋™์ด ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ this.state.history๋ฅผ this.state.history.slice(0, this.state.stepNumber + 1)๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ โ€œ์‹œ๊ฐ„์„ ๋˜๋Œ๋ คโ€ ๊ทธ ์‹œ์ ์—์„œ ์ƒˆ๋กœ์šด ์›€์ง์ž„์„ ๋ณด์ด๋ฉด, ์ง€๊ธˆ์€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ โ€œ๋ฏธ๋ž˜โ€์˜ ๊ธฐ๋ก์„ ๋ชจ๋‘ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares
      }]),
      stepNumber: history.length,      xIsNext: !this.state.xIsNext,
    });
  }

๋งˆ์ง€๋ง‰์œผ๋กœ Game ์ปดํฌ๋„ŒํŠธ์˜ render ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ํ•ญ์ƒ ๋งˆ์ง€๋ง‰ ์ด๋™์„ ๋ Œ๋”๋งํ•˜๋Š” ๋Œ€์‹  stepNumber์— ๋งž๋Š” ํ˜„์žฌ ์„ ํƒ๋œ ์ด๋™์„ ๋ Œ๋”๋งํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];    const winner = calculateWinner(current.squares);

    // the rest has not changed

๊ฒŒ์ž„์˜ ๊ธฐ๋ก์—์„œ ์–ด๋–ค ์ฐจ๋ก€๋ฅผ ์„ ํƒํ•œ๋‹ค๋ฉด ํ‹ฑํƒํ†  ๊ฒŒ์ž„ํŒ์„ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธํ•ด์„œ ๊ทธ ๋‹จ๊ณ„๊ฐ€ ๋ฐœ์ƒํ•œ ์งํ›„์˜ ๊ฒŒ์ž„ํŒ์„ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ์ „์ฒด ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ

๋งˆ๋ฌด๋ฆฌ

์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์•„๋ž˜ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํ‹ฑํƒํ†  ๊ฒŒ์ž„์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

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

์ˆ˜๊ณ ํ•˜์…จ์Šต๋‹ˆ๋‹ค! ์ด์ œ React๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜์…จ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ตœ์ข… ๊ฒฐ๊ณผ๋Š” ์—ฌ๊ธฐ์„œ ํ™•์ธํ•ด์ฃผ์„ธ์š”: ์ตœ์ข… ๊ฒฐ๊ณผ.

์‹œ๊ฐ„์ด ๋” ์žˆ๊ฑฐ๋‚˜ ์ƒˆ๋กœ์šด React ๊ธฐ์ˆ ์„ ์—ฐ์Šตํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚œ์ด๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋Š” ํ‹ฑํƒํ†  ๊ฒŒ์ž„ ๊ฐœ์„  ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์„ธ์š”.

  1. ์ด๋™ ๊ธฐ๋ก ๋ชฉ๋ก์—์„œ ํŠน์ • ํ˜•์‹(ํ–‰, ์—ด)์œผ๋กœ ๊ฐ ์ด๋™์˜ ์œ„์น˜๋ฅผ ํ‘œ์‹œํ•ด์ฃผ์„ธ์š”.
  2. ์ด๋™ ๋ชฉ๋ก์—์„œ ํ˜„์žฌ ์„ ํƒ๋œ ์•„์ดํ…œ์„ ๊ตต๊ฒŒ ํ‘œ์‹œํ•ด์ฃผ์„ธ์š”.
  3. ์‚ฌ๊ฐํ˜•๋“ค์„ ๋งŒ๋“ค ๋•Œ ํ•˜๋“œ์ฝ”๋”ฉ ๋Œ€์‹ ์— ๋‘ ๊ฐœ์˜ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜๋„๋ก Board๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.
  4. ์˜ค๋ฆ„์ฐจ์ˆœ์ด๋‚˜ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ด๋™์„ ์ •๋ ฌํ•˜๋„๋ก ํ† ๊ธ€ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
  5. ์Šน์ž๊ฐ€ ์ •ํ•ด์ง€๋ฉด ์Šน๋ถ€์˜ ์›์ธ์ด ๋œ ์„ธ ๊ฐœ์˜ ์‚ฌ๊ฐํ˜•์„ ๊ฐ•์กฐํ•ด์ฃผ์„ธ์š”.
  6. ์Šน์ž๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ฌด์Šน๋ถ€๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด์ฃผ์„ธ์š”.

์ž์Šต์„œ๋ฅผ ํ†ตํ•ด ์—˜๋ฆฌ๋จผํŠธ, ์ปดํฌ๋„ŒํŠธ, props, state๋ฅผ ํฌํ•จํ•œ React์˜ ๊ฐœ๋…์„ ๋‹ค๋ฃจ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ๋ฌธ์„œ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ์ฐธ์กฐํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ ์ •์˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ React.Component API ์ฐธ์กฐ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

Is this page useful?Edit this page