๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

"React" ํƒœ๊ทธ๋กœ ์—ฐ๊ฒฐ๋œ 6๊ฐœ ๊ฒŒ์‹œ๋ฌผ๊ฐœ์˜ ๊ฒŒ์‹œ๋ฌผ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ํƒœ๊ทธ ๋ณด๊ธฐ

ยท ์•ฝ 3๋ถ„

React + TypeScript + Storybook + ESLint ์„ธํŒ…#

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ#

yarn create react-app my-app-name --template typescript

CRA + ESLint + Prettier#

Create-React-App with TypeScript, ESLint, Prettier, and Github Actions

Husky + lint-staged#

์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ ์ง€์šฐ๊ธฐ#

.gitignore#

.gitignore ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์ค‘์š”ํ•œ ๊ฒƒ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ž์ฒด์—์„œ ์ƒ์„ฑํ•œ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋‚˜์—ดํ•ด์•ผ ํ•œ๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ์˜ˆ๋Š” ์บ์‹œ ํŒŒ์ผ, ๋กœ๊ทธ, ๋กœ์ปฌ ๊ตฌ์„ฑ ๋“ฑ์ด๋‹ค.

.vscode , .idea , .DS_Store ๋“ฑ์€ ํ”„๋กœ์ ํŠธ์˜ .gitignore ๋ณด๋‹ค ์ปดํ“จํ„ฐ์˜ ๊ธ€๋กœ๋ฒŒ .gitignore ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๊ธ€๋กœ๋ฒŒ .gitignore ๋Š” home ๋””๋ ‰ํ† ๋ฆฌ์˜ .gitconfig ์„ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋‹ค.

[core]    excludesfile = /Users/{home}/.gitignore_global

Don't put .idea and .vscode directories to project's .gitignore

ํด๋” ๊ตฌ์„ฑํ•˜๊ธฐ#

โ””โ”€โ”€ src    โ”œโ”€โ”€ components        โ””โ”€โ”€ src    โ”œโ”€โ”€ pages    โ”œโ”€โ”€ App.tsx    โ””โ”€โ”€ index.tsx

Storybook ์„ค์น˜ํ•˜๊ธฐ#

npx sb init

https://storybook.js.org/docs/react/get-started/install


์›น ํฐํŠธ ์‚ฌ์šฉ#

NAVER D2


free illustration#

unDraw - Open source illustrations for any idea


Styled Components#

The Advanced Way to Style with Styled Components

Thoughts around design systems: implementationโ€Š-โ€ŠReact, Styled-Components, and more

How does the ampersand work in styled-components?

The Sass Ampersand | CSS-Tricks

Type Guard#

https://www.typescriptlang.org/docs/handbook/advanced-types.html

validate css unit value#

https://www.reddit.com/r/learnjavascript/comments/8u5pew/function_that_can_validate_if_a_string_is_a_valid/

ยท ์•ฝ 12๋ถ„

๋ชจ๋ฐ”์ผ ์‚ฌํŒŒ๋ฆฌ ๋””๋ฒ„๊น…#

  • ์•„์ดํฐ์„ ๋งฅ๋ถ์— ์—ฐ๊ฒฐํ•œ๋‹ค.

  • ์•„์ดํฐ์—์„œ ๋””๋ฒ„๊น…ํ•˜๊ณ ์ž ํ•˜๋Š” ์›นํŽ˜์ด์ง€๋ฅผ Safari์— ๋„์šด๋‹ค.

  • ๋งฅ๋ถ์—์„œ Safari๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

  • ๊ฐœ๋ฐœ์ž์šฉ > iPhone > Safari ์›น ํŽ˜์ด์ง€ ์„ ํƒ

    2020-11-10-201110-image-0

  • ์š”์†Œ, ์ฝ˜์†”, ์†Œ์Šค, ๋„คํŠธ์›Œํฌ ๋“ฑ ์‚ฌํŒŒ๋ฆฌ์˜ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋กœ ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ๋‹ค.

    2020-11-10-201110-image-1

Debugging Your iPhone Mobile Web App With Safari Dev Tools

๋ชจ๋ฐ”์ผ ์‚ฌํŒŒ๋ฆฌ๋ฅผ ๋งฅ์˜ Chrome์—์„œ ๋””๋ฒ„๊น…ํ•˜๊ธฐ#

๋ชจ๋ฐ”์ผ Safari๋ฅผ ๋งฅ์˜ Chrome์—์„œ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ์— ์•Œ์•„๋ด์•ผ๊ฒ ๋‹ค.

Jon Sadka - How to debug an issue in Chrome for iOS using remote debugging

๋ฆฌ์•กํŠธ#

  • ๋ฆฌ์•กํŠธ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—˜๋ฆฌ๋จผํŠธ๋“ค์„ ํŠธ๋ฆฌ ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

  • ์ด๋ฅผ Virtual-DOM์œผ๋กœ ๋ถ€๋ฅด๋Š”๋ฐ, ์ด๋Š” JavaScript ์ผ๋ฐ˜ ๊ฐ์ฒด์ด๋‹ค. (Plain Object)

  • ๊ธฐ์กด VanillaJS๋Š” UI๋ฅผ ๋ช…๋ นํ˜•์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•˜์ง€๋งŒ, React๋Š” ์„ ์–ธํ˜•์œผ๋กœ UI๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ#

  • ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ ๊ฐ’์ธ state ์™€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‚ด๋ ค ์ฃผ๋Š”์†์„ฑ ๊ฐ’ props ๋ฅผ ๊ฐ€์ง„๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ๋Š” state , props ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด render() ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์–ด ํ™”๋ฉด์„ ๊ฐฑ์‹ ํ•œ๋‹ค.

  • UI ๋ฐ์ดํ„ฐ(์ƒํƒœ๊ฐ’๊ณผ ์†์„ฑ๊ฐ’)๋กœ ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ด ๋ฆฌ์•กํŠธ์˜ ํ•ต์‹ฌ์ด๋‹ค.

  • setState ๋Š” ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•œ๋‹ค.

๋ฆฌ์•กํŠธ์˜ ๋ Œ๋”๋ง ๊ณผ์ •#

  • ์ปดํฌ๋„ŒํŠธ์˜ Props๋‚˜ State์˜ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๋•Œ, ์ปดํฌ๋„ŒํŠธ์˜ ์ด์ „ ์ƒํƒœ ์—˜๋ฆฌ๋จผํŠธ์™€ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง„ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋น„๊ตํ•˜๊ณ  ์‹ค์ œ DOM์˜ ์—…๋ฐ์ดํŠธ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ๋น„๊ตํ•˜์—ฌ์ฐพ์€ ๋ณ€๊ฒฝ ์ ์— ๋Œ€ํ•ด์„œ๋งŒ ๊ฐฑ์‹ ํ•œ๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์˜ setState ๋ฉ”์„œ๋“œ๊ฐ€ ์ˆ˜ํ–‰๋˜๋ฉด, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ Dirty ์ฒดํฌํ•˜๊ณ , ๋‹ค์Œ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ๋ฐฐ์น˜ ์ž‘์—…์œผ๋กœ ๋Œ€์ƒ ์ปดํฌ๋„ŒํŠธ๋“ค์˜ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค. (๋น„๋™๊ธฐ )

  • ์ด๋Ÿฌํ•œ ๋ฆฌ์•กํŠธ์˜ ๋ Œ๋”๋ง ๊ณผ์ •์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ชผ๊ฐค ์ˆ˜ ์žˆ๋‹ค.

    • ๋ณ€๊ฒฝ ์ ์„ ์ฐพ๋Š” Reconciliation์˜ Diffing ์•Œ๊ณ ๋ฆฌ์ฆ˜ (render or reconciliation phase)

    • ๋ณ€๊ฒฝ ์ ์„ ์‹ค์ œ UI์— ์ ์šฉํ•˜๋Š” ReactDOMComponent.updateComponent (commit phase)

Reconciliation: The diffing algorithm#

Reconciliation์€ ์–ด๋–ค ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์ „/ํ›„ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ๋น„๊ต(Diff)ํ•˜์—ฌ, ๊ฐฑ์‹ ์ดํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ์„ ์ฐพ์•„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ธŒ๋ผ์šฐ์ €์˜ DOM ์กฐ์ž‘์„์ตœ์†Œํ™”์‹œํ‚จ๋‹ค.

๋‹ค์‹œ ์ •๋ฆฌ

  • render() ์—์„œ ์ƒˆ๋กœ์šด ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑ

  • ์ด์ „ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ์™€ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ ์ ์„ ์ฐพ์•„ ์—…๋ฐ์ดํŠธ

๊ทธ๋Ÿฐ๋ฐ Diff ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ O(n^3)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ๋‹ค์Œ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ O(n)์— ๊ทผ์‚ฌํ•œ ํœด๋ฆฌ์Šคํ‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

  • ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๋‘ ์—˜๋ฆฌ๋จผํŠธ๋Š” ๋‹ค๋ฅธ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.

  • ๊ฐ™์€ ๋ ˆ๋ฒจ์˜ ์—˜๋ฆฌ๋จผํŠธ์— key ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•  ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ‘œ์‹œํ•œ๋‹ค.

โ˜ ํœด๋ฆฌ์Šคํ‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ : ์ง๊ด€์— ์˜์กดํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜. ์ฆ‰ ํœด๋ฆฌ์Šคํ‹ฑ์€ ๋ณดํ†ต ํ•ฉ๋ฆฌ์ ์ธ์‹คํ–‰ ์‹œ๊ฐ„์„ ๊ฐ€์ง€์ง€๋งŒ ๊ทธ๊ฒƒ์ด ํ•ญ์ƒ ๊ทธ๋ ‡๋‹ค๋Š” ์–ด๋– ํ•œ ์ถ”๋ก  ๊ณผ์ •์ด๋‚˜ ์ฆ๋ช…์ด ์—†๋‹ค.

๊ฐ™์€ ์œ„์น˜์—์„œ ์—˜๋ฆฌ๋จผํŠธ์˜ ํƒ€์ž…์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ

  1. ๊ธฐ์กด ํŠธ๋ฆฌ๋ฅผ ์ œ๊ฑฐ ํ›„ ์ƒˆ๋กœ์šด ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค.

  2. ๊ธฐ์กด ํŠธ๋ฆฌ ์ œ๊ฑฐ ์‹œ ํŠธ๋ฆฌ ๋‚ด๋ถ€(ํ•˜์œ„)์˜ ์—˜๋ฆฌ๋จผํŠธ/์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋ชจ๋‘ ์ œ๊ฑฐํ•œ๋‹ค. (์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ ์ œ๊ฑฐ๋˜๋ฉด์„œ componentWillUnmount() ๊ฐ€ ์‹คํ–‰๋จ.) ์ด์ „ ํŠธ๋ฆฌ์˜ ๋ชจ๋“  state๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค.

  3. ์ƒˆ๋กœ์šด ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค ๋•Œ ๋‚ด๋ถ€ ์—˜๋ฆฌ๋จผํŠธ/์ปดํฌ๋„ŒํŠธ๋“ค๋„ ๋ชจ๋‘ ์ƒˆ๋กœ ๋งŒ๋“ ๋‹ค. (์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ componentDidMount() ๊ฐ€ ์‹คํ–‰๋จ.)

๊ฐ™์€ ์œ„์น˜์—์„œ ์—˜๋ฆฌ๋จผํŠธ์˜ ํƒ€์ž…์ด ๊ฐ™์€ ๊ฒฝ์šฐ

  1. ์—˜๋ฆฌ๋จผํŠธ์˜ attributes ๋ฅผ ๋น„๊ตํ•œ๋‹ค.

  2. ๋ณ€๊ฒฝ๋œ attributes ๋งŒ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

  3. ์ž์‹ ์—˜๋ฆฌ๋จผํŠธ๋“ค์— diff ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์žฌ๊ท€์ ์œผ๋กœ ์ ์šฉํ•œ๋‹ค.

๊ฐ™์€ ์œ„์น˜์—์„œ ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ๊ทธ ํƒ€์ž…์ด ๊ฐ™์€ ๊ฒฝ์šฐ

  1. ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค ์ž์ฒด๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค. (state๊ฐ€ ์œ ์ง€๋œ๋‹ค.)

  2. ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค์˜ ์—…๋ฐ์ดํŠธ ์ „ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ ๋“ค์ด ํ˜ธ์ถœ๋˜๋ฉฐ props๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ๋‹ค.

  3. render() ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ์˜ ์ด์ „ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ์™€ ๋‹ค์Œ ์—˜๋ฆฌ๋จผํŠธ ํŠธ๋ฆฌ์—๋Œ€ํ•ด diff ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์žฌ๊ท€์ ์œผ๋กœ ์ ์šฉํ•œ๋‹ค.

์ž์‹ ์—˜๋ฆฌ๋จผํŠธ ์žฌ๊ท€

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

  • ์ •๋ ฌ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ์ทจ์•ฝํ•˜๋‹ค.

keys

  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ์—˜๋ฆฌ๋จผํŠธ๋“ค์ด key๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด key๋ฅผ ํ†ตํ•ด ๊ธฐ์กด ํŠธ๋ฆฌ์™€ ์ดํ›„ ํŠธ๋ฆฌ์˜ ์ž์‹ ๋“ค์ด ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

Avoid Reconciliation#

  • ์ปดํฌ๋„ŒํŠธ์˜ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

    • ShouldComponentUpdate ํ•จ์ˆ˜๊ฐ€ return false ํ•˜๋„๋ก ํ•œ๋‹ค.

    • ์ปดํฌ๋„ŒํŠธ๊ฐ€ PureComponent ๋ฅผ ์ƒ์†๋ฐ›๋„๋ก ํ•œ๋‹ค.

    • ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ React.memo() ๋กœ ๊ฐ์‹ธ์„œ export ํ•œ๋‹ค.

โ˜ ํ•ต์‹ฌ์€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ state , props ๊ฐ€ ๋ณ€๊ฒฝ ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋ Œ๋”๋งํ•˜๋„๋กํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ๋ฆฌ์•กํŠธ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ์ด์ง•ํ•˜๋Š”๊ฒƒ์ด๋‹ค.

๊ฐ€์žฅ ์ข‹์€ ์ผ€์ด์Šค๋Š” ๊ฐ™์€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด ๊ฐ™์€ props ๋กœ ์ž์ฃผ ๋ Œ๋”๋ง ๋ ๋•Œ์ด๋‹ค. ์ด์ „ ๋ฉ”๋ชจ์ด์ง• ๊ฒฐ๊ณผ์™€ props ๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๋‚ด๋ถ€๋ฅผ ๋น„๊ตํ•˜์ง€ ์•Š๊ณ  ๋ฉ”๋ชจ์ด์ง•๋œ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

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

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

UI ๋Ÿฐํƒ€์ž„์œผ๋กœ์„œ์˜ React

์žฌ์กฐ์ • (Reconciliation) - React

์„ฑ๋Šฅ ์ตœ์ ํ™” - React

React ๋ Œ๋”๋ง๊ณผ ์„ฑ๋Šฅ ์•Œ์•„๋ณด๊ธฐ : TOAST Meetup

React.memo() ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

๋ฆฌ์•กํŠธ ํ›…(Hook)#

ํ›…(Hook)์ด๋ž€?#

  • ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ React state๋ฅผ ์—ฐ๋™(hook into)ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜.

  • ์ฆ‰ ์ƒํƒœ๋ฅผ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์— ๋™๊ธฐํ™” ํ•ด์ค€๋‹ค. (์ด ๋ง์€ ์ƒํƒœ๊ฐ€ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๋‚ดํฌํ•จ.)

๋™๊ธฐ#

  • ์ปดํฌ๋„ŒํŠธ ์‚ฌ์ด์—์„œ ์ƒํƒœ์™€ ๊ด€๋ จ๋œ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

    • render props, HOC์™€ ๊ฐ™์€ ํŒจํ„ด์€ ๋ž˜ํผ๋ฅผ ๊นŠ๊ฒŒ ๋งŒ๋“ ๋‹ค.
  • ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ ๋“ค์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณต์žกํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.

  • ํด๋ž˜์Šค๋ณด๋‹ค ํ•จ์ˆ˜๊ฐ€ ์ง๊ด€์ ์ด๋‹ค. this ๋ฐ”์ธ๋”ฉ


ํ›…์˜ ๊ทœ์น™#

โ˜ ๋ฆฌ์•กํŠธ๋Š” ํ›…์ด ํ˜ธ์ถœ๋˜๋Š” ์ˆœ์„œ์— ์˜์กดํ•œ๋‹ค. (์ƒํƒœ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœ ์ˆœ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.)

  • ์ตœ์ƒ์œ„(at the Top Level)์—์„œ๋งŒ ํ›…์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. (๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•˜์ง€ ๋ง๋ผ)

    // ๐Ÿ”ด ์กฐ๊ฑด๋ฌธ์— Hook์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ฒซ ๋ฒˆ์งธ ๊ทœ์น™์„ ๊นผ์Šต๋‹ˆ๋‹คif (name !== '') {    useEffect(function persistForm() {        localStorage.setItem('formData', name);    });}
  • ์˜ค์ง React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. (์ผ๋ฐ˜ JS ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœํ•˜์ง€ ๋ง๋ผ)

โ˜ ๋ฆฌ์•กํŠธ์˜ ํ›…์€ ๋ Œ๋”๋ง ๋˜๋Š” ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ์˜ ํ•œ ์ˆ˜์ค€ ์œ„์˜ ์™ธ๋ถ€ ๊ณต๊ฐ„(์‹คํ–‰ ์ปจํ…์ŠคํŠธ)์— ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(๋ฐฐ์—ด)ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜๋Š” ๋ฐ์ดํ„ฐ( state , setter )์ด๋‹ค. ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๊ณต์œ ๋˜์ง€ ์•Š๊ณ , ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ์—‘์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค.

useState#

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

React hooks: not magic, just arrays

useEffect#

  • ๋ Œ๋”๋ง ์ดํ›„(DOM ์—…๋ฐ์ดํŠธ ํ›„)์— ์ˆ˜ํ–‰ํ•  "side effect"๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

Fiber#

  • virtualDOM์˜ ์ฆ๋ถ„ ๋ Œ๋”๋ง์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•จ.

  • requestIdleCallback ์„ ํ™œ์šฉ.

  • ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด๋ถ€ ๊ฐ์ฒด

  • ๋‚ด์žฅ ์Šคํƒ์— ์˜์กดํ•œ ๋™๊ธฐ์‹ ์žฌ๊ท€ ๋ชจ๋ธ์—์„œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์™€ ํฌ์ธํ„ฐ๊ฐ€ ์žˆ๋Š” ๋น„๋™๊ธฐ์‹๋ชจ๋ธ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์žฌ๊ตฌํ˜„ํ•จ.

    • ํ˜ธ์ถœ ์Šคํƒ์„ ๋งˆ์Œ๋Œ€๋กœ ์ค‘๋‹จํ•˜๊ณ  ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์ˆ˜๋™์œผ๋กœ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด

React Fiber Architecture - A Deep Dive

ยท ์•ฝ 12๋ถ„

NPM#

NPM1 - YouTube

Node Package Manager : ์•ฑ์Šคํ† ์–ด์—์„œ ์•ฑ์„ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ NPM์—์„œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ• ์ˆ˜ ์žˆ์Œ.

ํŒจํ‚ค์ง€๋Š” -g (global)์— ์„ค์น˜ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ์˜ ๋ถ€ํ’ˆ์œผ๋กœ์จ ์‚ฌ์šฉํ•˜๋„๋ก์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.


๊ฒ€์ƒ‰๊ณผ ์„ค์น˜#

npm

NPM์„ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์ดํŠธ


๋งŒ์•ฝ local-web-server ๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‹ถ์„ ๋•Œ,

  • npm i local-web-server

  • npm install local-web-server

i๋Š” install์˜ ์•ฝ์ž


์ปดํ“จํ„ฐ์˜ ์ „์—ญ์ ์ธ, ๋…๋ฆฝ์ ์ธ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์„ค์น˜ํ•˜๊ณ  ์‹ถ์„ ๋•Œ,

  • npm install -g local-web-server

g๋Š” global์˜ ์•ฝ์ž

๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด sudo ๋ฅผ ์•ž์— ์ถ”๊ฐ€ํ•œ๋‹ค.


ํŒจํ‚ค์ง€ ๋ชฉ๋ก ๋ณด๊ธฐ์™€ ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ#

ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ์— ์„ค์น˜๋œ ํŒจํ‚ค์ง€ ๋ณด๊ธฐ

npm list

์ „์—ญ์— ์„ค์น˜๋œ ํŒจํ‚ค์ง€ ๋ณด๊ธฐ

npm list -g

์ „์—ญ์— ์„ค์น˜๋œ ํŒจํ‚ค์ง€ ์ค‘ ์ œ์ผ ์ƒ๋‹จ์— ์žˆ๋Š” ํŒจํ‚ค์ง€๋งŒ ๋ณด๊ธฐ

npm list -g --depth=0

์ „์—ญ์— ์žˆ๋Š” ํŒจํ‚ค์ง€ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ

npm update -g local-web-server

์ „์—ญ์— ์žˆ๋Š” ํŒจํ‚ค์ง€ ์‚ญ์ œํ•˜๊ธฐ

npm uninstall -g local-web-server


๐Ÿ“Œ ๋ฐ”ํ€ด๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค์ง€ ๋งˆ๋ผ!


React#

React - YouTube

React ์•ฑ ๋งŒ๋“ค๊ธฐ#

  • npm install -g create-react-app - ์ „์—ญ์— ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•.
npm install -g create-react-appmkdir my-appcd my-appcreate-react-app .

  • npx - ์ž„์‹œ๋กœ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์ง€์šฐ๋Š” ์‹คํ–‰ ๋„๊ตฌ.
npx create-react-app my-appcd my-appnpm start

React ์•ฑ ์‹คํ–‰#

npm run start


์ฝ”๋”ฉํ•˜๊ธฐ#

public ๋””๋ ‰ํ† ๋ฆฌ - static ์ž์›์ด ์œ„์น˜ํ•œ ๊ณณ.#

  • index.html
<div id="root"></div>

์ด root ์•ˆ์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.


src ๋””๋ ‰ํ† ๋ฆฌ - source ์ฝ”๋“œ๊ฐ€ ์žˆ๋Š” ๊ณณ.#

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

<App /> ์ปดํฌ๋„ŒํŠธ๋ฅผ root ์—˜๋ฆฌ๋จผํŠธ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ๋œ๋‹ค.


  • App.js ํด๋ž˜์Šคํ˜• (ํด๋ž˜์Šคํ˜•๊ณผ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋Š”๋ฐ ์ด ๊ฐ•์ขŒ๋Š” ํด๋ž˜์Šคํ˜•์œผ๋กœ์ง„ํ–‰)
import React from 'react';import logo from './logo.svg';import './App.css';
class App extends React.Component {    render() {        return (            <div className="App">                <header className="App-header">                    <img src={logo} className="App-logo" alt="logo" />                    <p>                        Edit <code>src/App.js</code> and save to reload.                    </p>                    <a                        className="App-link"                        href="https://reactjs.org"                        target="_blank"                        rel="noopener noreferrer"                    >                        Learn React                    </a>                </header>            </div>        );    }}
export default App;

โ˜๏ธ ๋ฐ˜๋“œ์‹œ ๋ฆฌ์•กํŠธ๋Š” ๋ฐ˜ํ™˜ํ•  ๋•Œ ํ•˜๋‚˜์˜ ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์–ด์•ผ ํ•œ๋‹ค.


๋ฐฐํฌํ•˜๊ธฐ#

  • npm run build - ๋ฆฌ์•กํŠธ ์•ฑ์„ ๋นŒ๋“œํ•ด์คŒ

  • npx serve -s build - ๋นŒ๋“œํ•œ ์•ฑ์œผ๋กœ ๋กœ์ปฌ ํ˜ธ์ŠคํŒ…


JSX#

๐Ÿ“Œ JSX๋Š” JavaScript๊ฐ€ ์•„๋‹ˆ๋‹ค!

JSX๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” create-react-app์— ์˜ํ•ด JavaScript ์ฝ”๋“œ๋กœ ์ปจ๋ฒ„ํŒ… ๋œ๋‹ค.


Hello World!#

import React from 'react';import './App.css';
class App extends React.Component {    render() {        return <div className="App">Hello World!</div>;    }}
export default App;

App class๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์žฅํ•˜๊ณ  render ๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค. (ํ•„์ˆ˜), ํด๋ž˜์Šค ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ์—์„œ function ํ‚ค์›Œ๋“œ๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค. (ES6)


Components ์™€ props#

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

import React from 'react';import './App.css';
class Subject extends React.Component {    render() {        return (            <header>                <h1>{this.props.title}</h1>                {this.props.sub}            </header>        );    }}
class App extends React.Component {    render() {        return (            <div className="App">                <Subject title="WEB" sub="World Wide Web!" />                <Subject title="React" sub="For UI!" />            </div>        );    }}
export default App;

React Developer Tools#

React Developer Tools


์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ#

App.js

import React from 'react';import Subject from './components/Subject';import Content from './components/Content';import TOC from './components/TOC';import './App.css';
class App extends React.Component {    render() {        return (            <div className="App">                <Subject title="WEB" sub="World Wide Web!" />                <Subject title="React" sub="For UI!" />                <Content text="HTML is FUN!" />                <TOC />            </div>        );    }}
export default App;

import React from 'react'; - ๋ฆฌ์•กํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜.

ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋Š” import ์— ๋ช…์‹œ.

ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก export ์— ๋ช…์‹œ.


props ์™€ state#

2020-03-17-200317-image-0

props ๋Š” ์™ธ๋ถ€์—์„œ, ๋‚ด๋ถ€๋กœ ์ „๋‹ฌ. ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ์— ์†์„ฑ์— ๊ธฐ์ž…ํ•˜๋ฉด ๋‚ด๋ถ€ ์ปดํฌ๋„ŒํŠธ์—์„œ props ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ. ์‚ฌ์šฉํ•˜๋Š” ์ž…์žฅ์—์„œ ์กฐ์ž‘.

state ๋Š” ๋‚ด๋ถ€์˜ ์ƒํƒœ ๊ฐ’.


App.js

import React from 'react';import Subject from './components/Subject';import TOC from './components/TOC';import Content from './components/Content';import './App.css';
class App extends React.Component {    constructor(props) {        super(props);        this.state = {            subject: {title: 'WEB', sub: 'World Wide Web!'},        };    }    render() {        return (            <div className="App">                <Subject                    title={this.state.subject.title}                    sub={this.state.subject.sub}                />                <Subject title="React" sub="For UI!" />                <TOC />                <Content text="HTML is FUN!" />            </div>        );    }}
export default App;

constructor : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜ ( state ๊ฐ’์„ ์ดˆ๊ธฐํ™”)

ํ•ด๋‹น ๊ฐ์ฒด ์•ˆ์—์„œ { this.state.subject.title } ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ.


TOC ๊ฐœ์„ #

TOC.js

import React from 'react';
class TOC extends React.Component {    render() {        var lists = [];        var data = this.props.data;        var i = 0;
        while (i < data.length) {            lists.push(                <li key={data[i].id}>                    <a href={'/content/' + data[i].id}>{data[i].title}</a>                </li>,            );            i = i + 1;        }
        return (            <nav>                <ul>{lists}</ul>            </nav>        );    }}
export default TOC;

TOC.js ์—์„œ ์™ธ๋ถ€์—์„œ data (๊ฐ์ฒด๊ฐ€ ๋‹ด๊ธด ๋ฆฌ์ŠคํŠธ)๋ฅผ props ๋กœ ์ „๋‹ฌ๋ฐ›๊ณ , ํ•ด๋‹น๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ๋“ค์„ ์ˆœ์ฐจ์ ์œผ๋กœ lists ์— ๋‹ด์•„ ์ถœ๋ ฅํ•˜๊ฒŒ ๋ฐ”๊พผ๋‹ค.

์ด ๋•Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ชฉ๋ก์€ key ๋ฅผ ๊ฐ€์ ธ์•ผํ•œ๋‹ค. key={data[i].id} ๊ฐ€ ํ•„์ˆ˜.

ํ‚ค๋ฅผ ๊ธฐ์ž…ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ.

2020-03-17-200317-image-1


App.js

import React from 'react';import Subject from './components/Subject';import TOC from './components/TOC';import Content from './components/Content';import './App.css';
class App extends React.Component {    constructor(props) {        super(props);        this.state = {            subject: {title: 'WEB', sub: 'World Wide Web!'},            contents: [                {id: 1, title: 'HTML', desc: 'HTML is for information'},                {id: 2, title: 'CSS', desc: 'CSS is for Design'},                {id: 3, title: 'JavaScript', desc: 'JavaScript is for Interactive'},            ],        };    }    render() {        return (            <div className="App">                <Subject                    title={this.state.subject.title}                    sub={this.state.subject.sub}                />                <TOC data={this.state.contents} />                <Content text="HTML is FUN!" />            </div>        );    }}
export default App;

์ด๋ ‡๊ฒŒ ์™ธ๋ถ€์—์„œ Contents ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.


์ด๋ฒคํŠธ state , props , render() ํ•จ์ˆ˜#

React ์—์„œ๋Š” props ๋˜๋Š” state ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ render() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋„๋ก ์•ฝ์†๋˜์–ด ์žˆ๋‹ค. โ†’ ํ™”๋ฉด์ด ๋‹ค์‹œ ๊ทธ๋ ค์ง„๋‹ค.


๋™์ ์œผ๋กœ ๋ณ€์ˆ˜ ์ œ์–ด#

Subject.title ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ, this.state.mode ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ๋‹ค. ์ด ๋•Œ Subject.title ์€ <a> ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ ธ ์žˆ๋‹ค.

onClick ์†์„ฑ์œผ๋กœ ํด๋ฆญํ–ˆ์„ ๋•Œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜(์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ)๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ onClick ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ํ™”๋ฉด์ด ์ƒˆ๋กœ๊ณ ์นจ ๋œ๋‹ค. <a> ํƒœ๊ทธ์˜ ๊ธฐ๋ณธ ๋™์ž‘ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ.


...
<h1><a href="/" onClick={function(e){  console.log(e);    // debugger;  e.preventDefault();}}>{this.state.subject.title}</a></h1>
...

โ˜๏ธ debugger; ๋ฅผ ์‚ฝ์ž…ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด ํ•ด๋‹น ์œ„์น˜์—์„œ ๋ฉˆ์ถฐ์ง€๊ณ  ๊ฐœ๋ฐœ์ž๋„๊ตฌ์—์„œ ํ•ด๋‹น์œ„์น˜์˜ ์†Œ์Šค๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Œ


์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ํƒœ๊ทธ์˜ ๊ธฐ๋ณธ์ ์ธ ๋™์ž‘๋ฐฉ๋ฒ•์„ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ๊ฒƒ์ด event ๊ฐ์ฒด์˜ preventDefault() ๋ผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ๊ณ ์นจ๋˜๋Š” ํ˜„์ƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.


state ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ.

return (    <div className="App">        <header>            <h1>                <a                    href="/"                    onClick={function (e) {                        e.preventDefault();                        this.setState({                            mode: 'welcome',                        });                    }.bind(this)}                >                    {this.state.subject.title}                </a>            </h1>            {this.state.subject.sub}        </header>        <TOC data={this.state.contents} />        <Content title={_title} desc={_desc} />    </div>);
  • ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋์„ ๋•Œ ์‹คํ–‰๋˜๋Š” function ๋‚ด๋ถ€์— this ์˜ ๊ฐ’์ด ์•„๋ฌด๊ฒƒ๋„ ์„ธํŒ…๋˜์–ด์žˆ์ง€ ์•Š๋‹ค. โ†’ this ๋ฐ”์ธ๋”ฉ ์‚ฌ์šฉํ•ด์•ผํ•จ. ํ•จ์ˆ˜ ์•ˆ์˜ this ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„ฃ์€ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•จ. ( this = App )

  • state ๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ๋• setState ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ


React์—์„œ ๊ฐ์ฒด ๋˜๋Š” ๋ฐฐ์—ด state ๋ณ€๊ฒฝ#

React์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ state ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ render ํ•จ์ˆ˜์™€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์˜ render ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด reload ํ•˜๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์—๋Š” ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์ด ์—†๋‹ค๋ฉด ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด React.Component ์˜ shouldComponentUpdate ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

shouldComponentUpdate ๋Š” newProps ์™€ newState ๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„๋‹ค. ์—ฌ๊ธฐ์„œ newProps ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ”๋€ props ๊ฐ’์„ ๋งํ•œ๋‹ค.

newProps ์™€ ์ด์ „ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” this.props.data ๋ฅผ ์ด์šฉํ•ด props ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„๋•Œ๋งŒ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ render ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. (๋‘˜์ด ๊ฐ™์œผ๋ฉด false ๋ฆฌํ„ดํ•˜๊ณ  ๋‘˜์ด ๋‹ค๋ฅด๋ฉด true ๋ฅผ ๋ฆฌํ„ดํ•จ์œผ๋กœ ๊ฐ€๋Šฅ)

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ state ์— ๊ฐ์ฒด ๋˜๋Š” ๋ฐฐ์—ด์ด ์žˆ์„ ๊ฒฝ์šฐ์—, ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์˜ ์›๋ณธ์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด state ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ฒŒ ๋˜๋ฉด(์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฐ์—ด์˜ push ํ•จ์ˆ˜๋Š” ์›๋ณธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.) ์›๋ณธ์ด ์ˆ˜์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— newProps ์™€ this.props.data ๋Š” ๊ฐ™์„ ์ˆ˜๋ฐ–์— ์—†๊ณ , ๋”ฐ๋ผ์„œ shouldComponentUpdate ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ์กฐ์ž‘์ด ๋ถˆ๊ฐ€๋Šฅํ•ด์ง€๊ณ  ์ด๋Š” ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฐฐ์—ด์—์„œ๋Š” push ํ•จ์ˆ˜ ๋Œ€์‹  concat , ๊ฐ์ฒด์—์„œ๋Š” Object.assign ํ•จ์ˆ˜ ๋“ฑ์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด๋กœ state ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์œผ๋กœ shouldComponentUpdate ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ์กฐ์ž‘์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์•ฝ 7๋ถ„

๋ฒจ๋กœํผํŠธ์™€ ํ•จ๊ป˜ํ•˜๋Š” ๋ชจ๋˜ ๋ฆฌ์•กํŠธ

React ์ž…๋ฌธ#

Input ์ƒํƒœ ๊ด€๋ฆฌํ•˜๊ธฐ#

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” input ํƒœ๊ทธ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

  • input์— ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜๋ฉด ์•„๋ž˜์˜ ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋จ.

  • ์ดˆ๊ธฐํ™”๋ฅผ ํด๋ฆญํ•˜๋ฉด input ๋‚ด๋ถ€์— ๋‚ด์šฉ๋„ ์ง€์›Œ์ง€๊ณ , ์•„๋ž˜์˜ ๊ฐ’๋„ ์ง€์›Œ์ง.


InputSample.js

import React, {useState} from 'react';
function InputSample() {    const [text, setText] = useState('');
    const onChange = (e) => {        setText(e.target.value);    };
    const onReset = () => {        setText('');    };
    return (        <div>            <input onChange={onChange} value={text} />            <button onClick={onReset}>์ดˆ๊ธฐํ™”</button>            <div>                <b>๊ฐ’: {text}</b>            </div>        </div>    );}
export default InputSample;

App.js

import React from 'react';import InputSample from './InputSample';
function App() {    return <InputSample />;}
export default App;

input ์˜ onChange ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉ. ์ด๋ฒคํŠธ ๊ฐ์ฒด e ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉ . e.target ์€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ DOM์ธ input DOM์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋˜๊ณ , DOM์˜ value ๊ฐ’, e.target.value ๋ฅผ ์กฐํšŒํ•˜๋ฉด ํ˜„์žฌ input ์— ์ž…๋ ฅํ•œ ๊ฐ’์ด ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค .


Event | PoiemaWeb


์—ฌ๋Ÿฌ ๊ฐœ์˜ input ์ƒํƒœ ๊ด€๋ฆฌํ•˜๊ธฐ#

input ์˜ ๊ฐœ์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋˜์—ˆ์„ ๋•Œ ๋‹จ์ˆœํžˆ useState ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์‚ฌ์šฉํ•˜๊ณ  onChange ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค์–ด์„œ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์€ input ์— name ์„ ์„ค์ •ํ•˜๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ด ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด์ œ useState ์—์„œ๋Š” ๋ฌธ์ž์—ด์ด ์•„๋‹ˆ๋ผ ๊ฐ์ฒด ํ˜•ํƒœ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.


InputSample.js

import React, {useState} from 'react';
function InputSample() {    const [inputs, setInputs] = useState({        name: '',        nickname: '',    });
    const {name, nickname} = inputs; // ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ๊ฐ’ ์ถ”์ถœ
    const onChange = (e) => {        const {value, name} = e.target; // ์šฐ์„  e.target ์—์„œ name ๊ณผ value ๋ฅผ ์ถ”์ถœ        setInputs({            ...inputs, // ๊ธฐ์กด์˜ input ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•œ ๋’ค            [name]: value, // name ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ฐ’์„ value ๋กœ ์„ค์ •        });    };
    const onReset = () => {        setInputs({            name: '',            nickname: '',        });    };
    return (        <div>            <input name="name" placeholder="์ด๋ฆ„" onChange={onChange} value={name} />            <input                name="nickname"                placeholder="๋‹‰๋„ค์ž„"                onChange={onChange}                value={nickname}            />            <button onClick={onReset}>์ดˆ๊ธฐํ™”</button>            <div>                <b>๊ฐ’: </b>                {name} ({nickname})            </div>        </div>    );}
export default InputSample;

const onChange = (e) => {    const {value, name} = e.target; // ์šฐ์„  e.target ์—์„œ name ๊ณผ value ๋ฅผ ์ถ”์ถœ    setInputs({        ...inputs, // ๊ธฐ์กด์˜ input ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•œ ๋’ค        [name]: value, // name ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ฐ’์„ value ๋กœ ์„ค์ •    });};

์ด ๋ถ€๋ถ„์„ ํ’€์–ด ์“ฐ๋ฉด

const nextInputs = {    ...inputs,};
nextInputs[name] = value;
setInputs(value);

useRef ๋กœ ํŠน์ • DOM ์„ ํƒํ•˜๊ธฐ#

JavaScript๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํŠน์ • DOM์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•ด getElementById , querySelector ๊ฐ™์€ DOM Selector ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ DOM์„ ์„ ํƒํ•œ๋‹ค.

๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋„ ๊ฐ€๋” DOM์„ ์ง์ ‘ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜์žˆ๋Š”๋ฐ ๊ทธ๋Ÿด ๋•Œ ref ๋ผ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•œ๋‹ค. ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ref ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” useRef ๋ผ๋Š” Hook ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ React.createRef ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋Š” ํ˜„์žฌ ๋ณ„๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š๋‹ค.

InputSample.js ์—์„œ ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ด๋ฆ„ input ์— ํฌ์ปค์Šค๊ฐ€ ์žกํžˆ๋„๋ก ๊ตฌํ˜„ํ•ด๋ณธ๋‹ค.

InputSample.js

import React, {useState, useRef} from 'react';
function InputSample() {    const [inputs, setInputs] = useState({        name: '',        nickname: '',    });    const nameInput = useRef();
    const {name, nickname} = inputs; // ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ๊ฐ’ ์ถ”์ถœ
    const onChange = (e) => {        const {value, name} = e.target; // ์šฐ์„  e.target ์—์„œ name ๊ณผ value ๋ฅผ ์ถ”์ถœ        setInputs({            ...inputs, // ๊ธฐ์กด์˜ input ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•œ ๋’ค            [name]: value, // name ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ฐ’์„ value ๋กœ ์„ค์ •        });    };
    const onReset = () => {        setInputs({            name: '',            nickname: '',        });        nameInput.current.focus();    };
    return (        <div>            <input                name="name"                placeholder="์ด๋ฆ„"                onChange={onChange}                value={name}                ref={nameInput}            />            <input                name="nickname"                placeholder="๋‹‰๋„ค์ž„"                onChange={onChange}                value={nickname}            />            <button onClick={onReset}>์ดˆ๊ธฐํ™”</button>            <div>                <b>๊ฐ’: </b>                {name} ({nickname})            </div>        </div>    );}
export default InputSample;

React ๊ณต๋ถ€๋ฅผ ํ•˜๋ฉฐ ๋Š๋‚€์ #

  • JS ๊ธฐ์ดˆ ๋ฌธ๋ฒ•๋งŒ ๋–ผ๊ณ  ๋ฐ”๋กœ React ์ž…๋ฌธ์œผ๋กœ ๋„˜์–ด์˜ค๋‹ˆ DOM, Event ๊ฐ์ฒด ๋“ฑ JS์—์„œ ๋ถ€์กฑํ–ˆ๋˜ ๊ฐœ๋…์ด ๋“ฑ์žฅํ•  ๋•Œ๋งˆ๋‹ค ๋‚ฏ์„  React ๊ตฌ์กฐ์™€ ํ•จ๊ป˜ ๋จธ๋ฆฌ ์†์„ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค .

  • ์•„์ง React์™€ JavaScript์˜ ๊ด€๊ณ„๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ ์–ด๋–ค ๊ฒƒ์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค. ๊ฐ•์˜๋ฅผ ๋ณด๋ฉด JavaScript๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ React๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋ฉด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„๋“ค์ด ์žˆ๋‹ค . React๋„ ๊ฒฐ๊ตญ JS๋‹ˆ๊นŒ JS๋กœ๋งŒ ํ•ด๋„ ๋‹ค ๋˜๋Š” ๊ฑธ๋กœ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ ์™œ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฑด์ง€ ์ดํ•ด๋˜์ง€ ์•Š๋Š”๋‹ค.

  • ์ข‹์€ React ๊ณต๋ถ€ ์ž๋ฃŒ๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ต๋‹ค. ์ตœ์‹  ๊ธฐ์ˆ ์ด๋ผ ๋น ๋ฅด๊ฒŒ ๋ณ€ํ•˜๊ณ  ์žˆ์–ด์„œ ์ฑ…๋ณด๋‹ค๋Š” ์ธํ„ฐ๋„ท ์ž๋ฃŒ + ์˜จ๋ผ์ธ ๊ฐ•์˜๋กœ ๊ณต๋ถ€ํ•ด์•ผ ํ•œ๋‹ค.

    1. ๊ณต์‹ ๋ฌธ์„œ

    2. ์ƒํ™œ์ฝ”๋”ฉ - 4์‹œ๊ฐ„ 40๋ถ„ ๋ถ„๋Ÿ‰

    3. velopert ๋‹˜ ๊ฐ•์ขŒ - 2์‹œ๊ฐ„ 53๋ถ„ ๋ถ„๋Ÿ‰

    4. zeroCho ๋‹˜ ๊ฐ•์ขŒ - 12์‹œ๊ฐ„ 44๋ถ„ ๋ถ„๋Ÿ‰

    5. Udemy ๊ฐ•์ขŒ - 26์‹œ๊ฐ„ 42 ๋ถ„ ๋ถ„๋Ÿ‰


์•ž์œผ๋กœ ..#

  • zeroCho๋‹˜์˜ JavaScript ์›น๊ฒŒ์ž„ ๊ฐ•์ขŒ์™€ React ์›น๊ฒŒ์ž„ ๊ฐ•์ขŒ๊ฐ€ ์นœ์ ˆํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด์„œ๋„์ƒ๊ฐํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์˜ˆ์ œ๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ๋„์›€์ด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์ด ๋‘ ๊ฐ•์ขŒ๋ฅผ ๋“ฃ๊ณ  ๊ธฐ์ดˆ๋ฅผ ์Œ“๋Š”๋‹ค.

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

ยท ์•ฝ 5๋ถ„

React#

props ๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๊ฐ’ ์ „๋‹ฌํ•˜๊ธฐ (๊ณ„์†)#

defaultProps ๋กœ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •#

Hello.js

import React from 'react';
function Hello({color, name}) {    return <div style={{color}}>์•ˆ๋…•ํ•˜์„ธ์š” {name}</div>;}
Hello.defaultProps = {    name: '์ด๋ฆ„์—†์Œ',};
export default Hello;

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

App.js

import React from 'react';import Hello from './Hello';
function App() {    return (        <>            <Hello name="react" color="red" />            <Hello color="pink" />        </>    );}
export default App;

2020-03-15-200315-image-0

props.children#

์ปดํฌ๋„ŒํŠธ ํƒœ๊ทธ ์‚ฌ์ด์— ๋„ฃ์€ ๊ฐ’์„ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„ ๋•, props.children ์„ ์กฐํšŒํ•˜๋ฉด ๋œ๋‹ค.

props.children ์„ ์‚ฌ์šฉํ•˜๋Š” Wrapper.js ๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

Wrapper.js

import React from 'react';
function Wrapper() {    const style = {        border: '2px solid black',        padding: '16px',    };    return <div style={style}></div>;}
export default Wrapper;

App.js

import React from 'react';import Hello from './Hello';import Wrapper from './Wrapper';
function App() {    return (        <Wrapper>            <Hello name="react" color="red" />            <Hello color="pink" />        </Wrapper>    );}
export default App;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚ด๋ถ€์˜ ๋‚ด์šฉ์ด ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. Wrapper.js ์—์„œ props.children ์„๋ Œ๋”๋งํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

Wrapper.js

import React from 'react';
function Wrapper(props) {    // props ๋Œ€์‹  { children } ์œผ๋กœ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น ํ›„    const style = {        border: '2px solid black',        padding: '16px',    };    return (        <div style={style}>            {props.children} {/* ์—ฌ๊ธฐ์„œ children ์œผ๋กœ๋งŒ ๋ฐ›์•„๋„ ๋œ๋‹ค. */}        </div>    );}
export default Wrapper;

2020-03-15-200315-image-1

์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง#

props ๋ฅผ ์ด์šฉํ•˜์—ฌ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฌผ์„ ๋ Œ๋”๋ง ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

App.js

import React from 'react';import Hello from './Hello';import Wrapper from './Wrapper';
function App() {    return (        <Wrapper>            <Hello name="react" color="red" isSpecial={true} />            <Hello color="pink" />        </Wrapper>    );}
export default App;

isSpecial ์ด๋ผ๋Š” props ๋ฅผ ์ „๋‹ฌํ•˜๊ณ , (์ด ๋•Œ true ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ’์ด๋ฏ€๋กœ์ค‘๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ์•ผํ•œ๋‹ค.

Hello.js

import React from 'react';
function Hello({color, name, isSpecial}) {    return (        <div style={{color}}>            {isSpecial ? <b>*</b> : null}            ์•ˆ๋…•ํ•˜์„ธ์š” {name}        </div>    );}
Hello.defaultProps = {    name: '์ด๋ฆ„์—†์Œ',};
export default Hello;

์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๋‹จ์ถ• ํ‰๊ฐ€ ๋…ผ๋ฆฌ ๊ณ„์‚ฐ๋ฒ•์œผ๋กœ isSpecial && <b>*</b> ๋กœ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋˜ํ•œ props ๊ฐ’์„ ์„ค์ •ํ•  ๋•Œ ์ด๋ฆ„๋งŒ ์ž‘์„ฑํ•˜๊ณ  ๊ฐ’ ์„ค์ •์„ ์ƒ๋žตํ•  ๊ฒฝ์šฐ ์ด๋ฅผ true ๋กœ์„ค์ •ํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

App.js

import React from 'react';import Hello from './Hello';import Wrapper from './Wrapper';
function App() {    return (        <Wrapper>            <Hello name="react" color="red" isSpecial />            <Hello color="pink" />        </Wrapper>    );}
export default App;

Hello.js

import React from 'react';
function Hello({color, name, isSpecial}) {    return (        <div style={{color}}>            {isSpecial ? alert(isSpecial) : null}            ์•ˆ๋…•ํ•˜์„ธ์š”            {name}        </div>    );}
Hello.defaultProps = {    name: '์ด๋ฆ„์—†์Œ',};
export default Hello;

isSpecial ์— ๊ฐ’์„ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  Hello.js ์—์„œ ๋งŒ์•ฝ isSpecial ์ด true ๋ผ๋ฉด isSpecial ์„ alert๋กœ ๋‚ด๋ณด๋‚ด๊ฒŒ ํ–ˆ๋‹ค.

2020-03-15-200315-image-2

true ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.


useState ๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ”๋€Œ๋Š” ๊ฐ’ ๊ด€๋ฆฌํ•˜๊ธฐ#

Counter ์˜ˆ์ œ๋ฅผ react๋กœ ๊ตฌํ˜„ํ•ด ๋ณธ๋‹ค.

App.js

import React from 'react';import Counter from './Counter';
function App() {    return <Counter />;}
export default App;

Counter.js

import React, {useState} from 'react';
function Counter() {    const [number, setNumber] = useState(0);
    const onIncrease = () => {        setNumber(number + 1);    };
    const onDecrease = () => {        setNumber(number - 1);    };
    return (        <div>            <h1>{number}</h1>            <button onClick={onIncrease}>+1</button>            <button onClick={onDecrease}>-1</button>        </div>    );}
export default Counter;

ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ#

์ด ๋•Œ, setNumber ํ•จ์ˆ˜(Setter ํ•จ์ˆ˜)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ  ์‹ถ์€ ์ƒˆ๋กœ์šด ๊ฐ’์„ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ๋Š”๋ฐ, ๊ทธ ๋Œ€์‹  ๊ธฐ์กด์˜ ๊ฐ’์„ ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธ ํ•  ์ง€์— ๋Œ€ํ•œ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ๋„ ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Counter.js

import React, {useState} from 'react';
function Counter() {    const [number, setNumber] = useState(0);
    const onIncrease = () => {        setNumber((prevNumber) => prevNumber + 1);    };
    const onDecrease = () => {        setNumber((prevNumber) => prevNumber - 1);    };
    return (        <div>            <h1>{number}</h1>            <button onClick={onIncrease}>+1</button>            <button onClick={onDecrease}>-1</button>        </div>    );}
export default Counter;

ยท ์•ฝ 5๋ถ„

React#

๋ฒจ๋กœํผํŠธ์™€ ํ•จ๊ป˜ํ•˜๋Š” ๋ชจ๋˜ ๋ฆฌ์•กํŠธ


React Component ๋งŒ๋“ค๊ธฐ#

Hello.js

import React from 'react';
function Hello() {    return <div>Hello World!</div>;}
export default Hello;

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค ๋•

import React from 'react';

๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” XML ํ˜•์‹์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋ฅผ JSX ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

export default Hello;

์ด ์ฝ”๋“œ๋Š” Hello ๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚ด๋ณด๋‚ด๊ฒ ๋‹ค๋Š” ์˜๋ฏธ.

App.js

import React from 'react';import Hello from './Hello';
function App() {    return (        <div>            <Hello />        </div>    );}
export default App;

์‹คํ–‰์‹œ์ผœ๋ณด๋ฉด, ( yarn start or npm start )

2020-03-14-200314-image-0

index.js

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: https://bit.ly/CRA-PWAserviceWorker.unregister();

์—ฌ๊ธฐ์„œ ReactDOM.render ๋ฅผ ๋ณด๋ฉด, id ๊ฐ€ root ์ธ DOM ๋‚ด๋ถ€์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ( <App /> )๋ฅผ ๋ Œ๋”๋งํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์ด DOM์€ public/index.html ๋‚ด๋ถ€์— ์žˆ๋‹ค.

<div id="root"></div>

JSX#

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

return <div>์•ˆ๋…•ํ•˜์„ธ์š”</div>;

Babel ์€ XML ํ˜•ํƒœ์˜ ์ฝ”๋“œ๋ฅผ JS๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค.

๊ทœ์น™#

  • ํƒœ๊ทธ๋ฅผ ์—ด์—ˆ์œผ๋ฉด ๋‹ซ์•„์•ผ ํ•จ. ( input , br ํฌํ•จ ๋ชจ๋“  ํƒœ๊ทธ. ํƒœ๊ทธ ์‚ฌ์ด์— ๋‚ด์šฉ์ด์—†์„ ๋•, <input/> ๋กœ ์…€ํ”„ํด๋กœ์ง• ๊ฐ€๋Šฅ)

  • ๋‘ ๊ฐœ ์ด์ƒ์˜ ํƒœ๊ทธ๋Š” ํ•˜๋‚˜์˜ ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์–ด์•ผ ํ•œ๋‹ค. <> </> Fragment๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ํƒœ๊ทธ ์—†์ด ๋‘ ๊ฐœ ์ด์ƒ์˜ ํƒœ๊ทธ ๊ฐ€๋Šฅ.

  • JSX ๋‚ด๋ถ€์— ๋ณ€์ˆ˜๋Š” {} ๋กœ ๊ฐ์‹ธ์„œ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์Œ.


style ๊ณผ className#

style ๊ณผ CSS class ์„ค์ • ๋ฐฉ๋ฒ•์ด HTML๊ณผ ๋‹ค๋ฅด๋‹ค.

  • ์ธ๋ผ์ธ ์Šคํƒ€์ผ์€ ๊ฐ์ฒด์ฒ˜๋Ÿผ ์ž‘์„ฑ.

  • background-color ๊ฐ™์ด - ๋กœ ๊ตฌ๋ถ„๋œ ์†์„ฑ ์ด๋ฆ„์„ ๊ฐ€์ง„ ์†์„ฑ๋“ค์€ camelCase ํ˜•ํƒœ๋กœ ( backgroundColor )

  • CSS class ์„ค์ •์‹œ์—” class="" ๊ฐ€ ์•„๋‹Œ className="" ์œผ๋กœ.

App.js

import React from 'react';import Hello from './Hello';import './App.css';
function App() {    const name = 'react';    const style = {        backgroundColor: 'black',        color: 'aqua',        fontSize: 24, // ๊ธฐ๋ณธ ๋‹จ์œ„ px        padding: '1rem', // ๋‹ค๋ฅธ ๋‹จ์œ„ ์‚ฌ์šฉ ์‹œ ๋ฌธ์ž์—ด๋กœ ์„ค์ •    };
    return (        <>            <Hello />            <div style={style}>{name}</div>            <div className="gray-box"></div>        </>    );}
export default App;

App.css

.gray-box {    background: gray;    width: 64px;    height: 64px;}

์ฃผ์„#

{/* JSX ๋‚ด๋ถ€ ์ฃผ์„ ์ž‘์„ฑ๋ฒ• */}

์—ด๋ฆฌ๋Š” ํƒœ๊ทธ ๋‚ด๋ถ€์—์„œ๋Š” // ์ด๋Ÿฐ ํ˜•ํƒœ์˜ ์ฃผ์„ ์ž‘์„ฑ๋„ ๊ฐ€๋Šฅ


props ๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ์— ๊ฐ’ ์ „๋‹ฌ#

App ์ปดํฌ๋„ŒํŠธ์—์„œ Hello ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ

App.js

import React from 'react';import Hello from './Hello';
function App() {    return <Hello name="react" />;}
export default App;

Hello.js

import React from 'react';
function Hello(props) {    return <div>์•ˆ๋…•ํ•˜์„ธ์š” {props.name}</div>;}
export default Hello;

props ๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์กฐํšŒ, ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๋ฏ€๋กœ props.name ์œผ๋กœ ์กฐํšŒ ๊ฐ€๋Šฅ


๋น„๊ตฌ์กฐํ™” ํ• ๋‹น#

App.js

import React from 'react';import Hello from './Hello';
function App() {    return <Hello name="react" color="red" />;}
export default App;

name , color ๋‘ ๊ฐ€์ง€ ๊ฐ’์„ ์ „๋‹ฌ.

import React from 'react';
function Hello(props) {    return <div style={{color: props.color}}>์•ˆ๋…•ํ•˜์„ธ์š” {props.name}</div>;}
export default Hello;

color: props.color ๋Š” ๊ฐ์ฒด์ด๋ฏ€๋กœ {} ๋กœ ํ•œ ๋ฒˆ ๊ฐ์‹ธ๊ณ , ์ด ๊ฐ์ฒด๊ฐ€ JS ๊ฐ’์ด๋ฏ€๋กœ {} ๋กœ ํ•œ๋ฒˆ ๋” ๊ฐ์‹ผ๋‹ค.


๋‘ ๊ฐ€์ง€ ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

import React from 'react';
function Hello({color, name}) {    return <div style={{color}}>์•ˆ๋…•ํ•˜์„ธ์š” {name}</div>;    // color: color -> color ๋กœ ์ž‘์„ฑ ๊ฐ€๋Šฅ}
export default Hello;