Skip to content

Latest commit

ย 

History

History
1796 lines (1183 loc) ยท 89.6 KB

react.md

File metadata and controls

1796 lines (1183 loc) ยท 89.6 KB

prepare_frontend_interview

React


React ์‹œ์ž‘

๋ฆฌ์•กํŠธ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๊ฐ€์š” ํ”„๋ ˆ์ž„์›Œํฌ์ธ๊ฐ€์š”

ํ•ด๋‹น ๋ฌธ๋‹จ์€ ๊ถŒ์œคํ•™๋‹˜์˜ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฐจ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๊ณ  ๋ด์•ผ ํ• ๊นŒ์š” ์•„๋‹ˆ๋ฉด, ํ”„๋ ˆ์ž„ ์›Œํฌ๋ผ๊ณ  ๋ด์•ผ ํ• ๊นŒ์š”? ์šฐ์„  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ”„๋ ˆ์ž„ ์›Œํฌ์˜ ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1.ํ”„๋ ˆ์ž„์›Œํฌ

ํ”„๋ ˆ์ž„์›Œํฌ๋Š” Application ๊ฐœ๋ฐœ์‹œ ์ฝ”๋“œ์˜ ํ’ˆ์งˆ, ํ•„์ˆ˜์ ์ธ ์ฝ”๋“œ, ์•Œ๊ณ ๋ฆฌ์ฆ˜, ์•”ํ˜ธํ™”, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™ ๊ฐ™์€ ๊ธฐ๋Šฅ๋“ค์„ ์–ด๋Š์ •๋„ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋Š” ๋ผˆ๋Œ€(๊ตฌ์กฐ)๋ฅผ ์ œ๊ณตํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ง„๊ฑธ ํ”„๋ ˆ์ž„์›Œํฌ๋ผ๊ณ ํ•ฉ๋‹ˆ๋‹ค.

์กฐ๊ธˆ ์–ด๋ ต๊ฒŒ ์„ค๋ช…๋“œ๋ ธ๋Š”๋ฐ, ๊ฐœ๋ฐœ ๊ตฌ์กฐ๋‚˜ ์„ค๊ณ„ ์‹œ ์ œ๊ณต๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. ์™„์„ฑ๋œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์•„๋‹ˆ์ง€๋งŒ ์–ด๋Š์ •๋„ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ œ๊ณต๋œ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ตฌ์กฐ์—์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

2.๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํŠน์ • ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ API(๋„๊ตฌ / ํ•จ์ˆ˜)๋ฅผ ๋ชจ์€ ์ง‘ํ•ฉ์„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด ๋ถˆ๋Ÿฌ์™€์„œ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์„ ์ƒ๊ฐํ•˜์‹œ๋ฉด ์‰ฌ์šธ๋“ฏ ํ•ฉ๋‹ˆ๋‹ค.

3.ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฐจ์ด

์œ„์˜ ๋‚ด์šฉ์œผ๋กœ๋งŒ ๋ดค์„๋•Œ๋Š” ๋‹จ์ˆœํžˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ชจ์ด๋ฉด ํ”„๋ ˆ์ž„์›Œํฌ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €๋„ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์—ˆ๊ณ ์š” ๊ทธ๋ฆฌ๊ณ  ํฌ๊ฒŒ ํ‹€๋ฆฐ ์ƒ๊ฐ๋„ ์•„๋‹Œ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค๋งŒ

์ž๋ฃŒ๋ฅผ ์ฐพ์•„๋ณด๋‹ˆ ํ† ๋น„์˜ ์Šคํ”„๋ง์— ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋‹จ์ง€ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘” ๋ฐ˜์ œํ’ˆ์ด๋‚˜, ํ™•์žฅํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ค€๋น„๋œ ์ถ”์ƒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ง‘ํ•ฉ์ด ์•„๋‹ˆ๋‹ค.
ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์–ด๋–ค ๊ฒƒ์ธ์ง€ ์ดํ•ดํ•˜๋ ค๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€ ์•Œ์•„์•ผ ํ•œ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ๋ฆ„์„ ์ง์ ‘ ์ œ์–ดํ•œ๋‹ค.
๋‹จ์ง€ ๋™์ž‘ํ•˜๋Š” ์ค‘์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์ด ์žˆ์„ ๋•Œ ๋Šฅ๋™์ ์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋ฟ์ด๋‹ค.

๋ฐ˜๋ฉด์— ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๊ฑฐ๊พธ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๊ฐ€ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
ํ”„๋ ˆ์ž„์›Œํฌ์—๋Š” ๋ถ„๋ช…ํ•œ ์ œ์–ด์˜ ์—ญ์ „ ๊ฐœ๋…์ด ์ ์šฉ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์งœ๋†“์€ ํ‹€์—์„œ ์ˆ˜๋™์ ์œผ๋กœ ๋™์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ flow๋ฅผ ๋ˆ„๊ฐ€ ์ œ์–ดํ•˜๋Š”๋ƒ๊ฐ€ ํ”„๋ ˆ์ž„์›Œํฌ์ธ์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ์ง€ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

1. ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์˜ ํ™”๋ฉด๊ตฌ์„ฑ

๋ฆฌ์•กํŠธ๋Š” ํ™”๋ฉด์˜ ํ•œ ๋ถ€๋ถ„์„ ์ปดํฌ๋„ŒํŠธ ๋ผ๋Š” ๋‹จ์œ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋Œ€๊ทœ๋ชจ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ปดํฌ๋„ŒํŠธ๋Š” ์—ญํ• ๊ณผ ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์šฉ์ดํ•˜๋ฉฐ, ๋ฐ˜๋ณต๋˜๋Š” ๋ถ€๋ถ„์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์–ด์„œ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค. ๋˜ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์˜ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด ๋ธ”๋ก ์Œ“๊ธฐ์ฒ˜๋Ÿผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์Œ“์•„์„œ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์œผ๋กœ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.


2. Virtual DOM์œผ๋กœ ์ธํ•œ ์ถฉ๋ถ„ํžˆ ๋น ๋ฅธ ์†๋„

  • Virtual DOM์€ UI์˜ ์ด์ƒ์ ์ธ ๋˜๋Š” โ€œ๊ฐ€์ƒโ€์ ์ธ ํ‘œํ˜„์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๊ณ  ReactDOM๊ณผ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์˜ํ•ด โ€œ์‹ค์ œโ€ DOM๊ณผ ๋™๊ธฐํ™”ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ์žฌ์กฐ์ •์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ๋ฐฉ์‹์ด React์˜ ์„ ์–ธ์  API๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. React์—๊ฒŒ ์›ํ•˜๋Š” UI์˜ ์ƒํƒœ๋ฅผ ์•Œ๋ ค์ฃผ๋ฉด DOM์ด ๊ทธ ์ƒํƒœ์™€ ์ผ์น˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ์•ฑ ๊ตฌ์ถ•์— ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์กฐ์ž‘, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ, ์ˆ˜๋™ DOM ์—…๋ฐ์ดํŠธ๋ฅผ ์ถ”์ƒํ™”ํ•ฉ๋‹ˆ๋‹ค.

3. SPA(์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)

  • ์žฅ์  : ์„œ๋ฒ„์˜ ์ž์›์„ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค. & ๋” ์ข‹์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ์  : ์‚ฌ์šฉ์ž์™€ ์ธํ„ฐ๋ ‰์…˜์ด ๋งŽ์€ ๊ฒฝ์šฐ์—๋Š” ์„œ๋ฒ„์˜ ์ž์›์ด ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ๋ถˆํ•„์š”ํ•œ ํŠธ๋ ˆํ”ฝ์ด ๋‚ญ๋น„ ๋  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์ด๋Ÿฌํ•œ ์žฅ์ ๋•Œ๋ฌธ์ด๋‹ค

  • component๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ด (ํ•„์š”ํ•œ ๋ถ€๋ถ„์˜ component๋งŒ ๋ Œ๋”๋ง ๋œ๋‹ค. ์ตœ์ ํ™”๋œ ๋ Œ๋”๋ง์ด ๊ฐ€๋Šฅ)
  • ์ƒํƒœ๊ณ„๊ฐ€ ๋„“๊ณ , ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • virtual DOM์„ ํ™œ์šฉํ•˜์—ฌ ๋น ๋ฅธ ๋ Œ๋”๋ง์ด ๊ฐ€๋Šฅ
  • ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์•ฑ ๊ฐœ๋ฐœ ๊ฐ€๋Šฅ

virtual DOM์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”

DOM(Document Object Model)์€ XML์ด๋‚˜ HTML ๋ฌธ์„œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์ผ์ข…์˜ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. DOM์€ ๋ฌธ์„œ์˜ ๊ตฌ์กฐํ™”๋œ ํ‘œํ˜„(structured representation)์„ ์ œ๊ณตํ•˜๋ฉฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ DOM ๊ตฌ์กฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์—ฌ ๊ทธ๋“ค์ด ๋ฌธ์„œ ๊ตฌ์กฐ, ์Šคํƒ€์ผ, ๋‚ด์šฉ ๋“ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋•๋Š”๋‹ค.

HTTP response > DOM tree > CSSOM tree > render tree > painting

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

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

๋ฆฌ์•กํŠธ์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ•˜์—ฌ ์›น ๋ธŒ๋ผ์šฐ์ €์— ์‹ค์ œ DOM์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋Š” ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ์ ˆ์ฐจ๋ฅผ ๋ฐŸ์Šต๋‹ˆ๋‹ค.

  1. ์ „์ฒด UI๋ฅผ Virtual DOM์— ๋ฆฌ๋ Œ๋”๋ง
  2. ์ด์ „ ๋‚ด์šฉ๊ณผ ํ˜„์žฌ ๋‚ด์šฉ์„ ๋น„๊ต
  3. ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ DOM์— ์ ์šฉ

Virtual DOM

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

์šฐ๋ฆฌ๋Š” ๋‹ค์Œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ๋ฆฌ์•กํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
์ง€์†์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ™”ํ•˜๋Š” ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•ํ•˜๊ธฐ

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

๋ฆฌ์•กํŠธ์™€ Virtual DOM์ด ์–ธ์ œ๋‚˜ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ฐ”๋กœ ์—…๋ฐ์ดํŠธ ์ฒ˜๋ฆฌ ๊ฐ„๊ฒฐ์„ฑ์ž…๋‹ˆ๋‹ค. UI๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ณผ์ •์—์„œ ์ƒ๊ธฐ๋Š” ๋ณต์žกํ•จ์„ ๋ชจ๋‘ ํ•ด์†Œํ•˜๊ณ , ๋”์šฑ ์‰ฝ๊ฒŒ ์—…๋ฐ์ดํŠธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ์˜ ๋ Œ๋”๋ง์— ๋Œ€ํ•ด ์•„๋‚˜์š”

๋ธŒ๋ผ์šฐ์ €์˜ ๋ Œ๋”๋ง์€ HTML๊ณผ CSS ๋ฆฌ์†Œ์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์›น ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ UI๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ์˜ ๋ Œ๋”๋ง์˜ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ Œ๋”๋ง๊ณผ ๊ตฌ๋ถ„ ์ง€์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๋ฆฌ์•กํŠธ ํŒŒ์ด๋ฒ„์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”

๋ฆฌ์•กํŠธ ํŒŒ์ด๋ฒ„๋Š” ๋ฆฌ์•กํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ํ‰๋ฒ”ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋‹ค. ํŒŒ์ด๋ฒ„๋Š” ํŒŒ์ด๋ฒ„ ์žฌ์กฐ์ •์ž(fiber reconciler)๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ, ๊ฐ€์ƒ DOM๊ณผ ์‹ค์ œ DOM์„ ๋น„๊ตํ•ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ˆ˜์ง‘ํ•˜๋ฉฐ, ๋งŒ์•ฝ ์ด ๋‘˜ ์‚ฌ์ด์— ์ฐจ์ด๊ฐ€ ์žˆ์œผ๋ฉด ๋ณ€๊ฒฝ์— ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŒŒ์ด๋ฒ„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ™”๋ฉด์— ๋ Œ๋”๋ง์„ ์š”์ฒญํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๋ฆฌ์•กํŠธ ํŒŒ์ด๋ฒ„๋Š” ๋ฆฌ์•กํŠธ ์•ฑ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜, ๋ ˆ์ด์•„์›ƒ, ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ ‰์…˜์— ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“œ๋Š” ๋ฐ˜์‘์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ด๋‹ค.

๋ชจ๋“  ๊ณผ์ •์€ ๋น„๋™๊ธฐ๋กœ ์ผ์–ด๋‚˜๋ฉฐ, ์ž‘์—…์„ ์Šค์ผ€์ค„๋งํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ๊ฐ™์ด ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์ž‘์—…์€ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ๋‚ฎ์€ ์ž‘์—…์„ ์—ฐ๊ธฐ์‹œํ‚ค๋Š” ๋“ฑ ์ข€ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋œ๋‹ค.

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

๋ฆฌ์•กํŠธ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ

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

๋”๋ธ” ๋ฒ„ํผ๋ง์€ ๋ Œ๋” ๋‹จ๊ณ„์™€ ์ปค๋ฐ‹ ๋‹จ๊ณ„ ์ค‘ ์ปค๋ฐ‹ ๋‹จ๊ณ„์—์„œ ์ˆ˜ํ–‰๋œ๋‹ค.

๋ฆฌ์•กํŠธ ํŒŒ์ด๋ฒ„์™€ DOM, Virtual DOM์˜ ๊ด€๊ณ„

๋ฆฌ์•กํŠธ์˜ ํŒŒ์ด๋ฒ„ ์•„ํ‚คํ…์ฒ˜์—์„œ ํ˜„์žฌ ๋ชจ์Šต์„ ๋‹ด์€ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ(current fiber tree)์™€ ์ž‘์—… ์ค‘์ธ ํŠธ๋ฆฌ(workInProgress fiber tree)๋Š” ์‹ค์ œ DOM๊ณผ Virtual DOM๊ณผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ(current fiber tree)
  • ์ด ํŠธ๋ฆฌ๋Š” ํ˜„์žฌ ํ™”๋ฉด์— ๋ Œ๋”๋ง๋˜์–ด ์žˆ๋Š” UI์˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ๋“ค์€ ์‹ค์ œ DOM ๋…ธ๋“œ์™€ 1:1 ๋Œ€์‘ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • ์ฆ‰, ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ๋Š” ์‹ค์ œ DOM์˜ ํ˜„์žฌ ๋ชจ์Šต์„ ๊ฐ€์ƒ์ ์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  1. ์ž‘์—… ์ค‘์ธ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ(workInProgress fiber tree)
  • ์ด ํŠธ๋ฆฌ๋Š” ๋‹ค์Œ ๋ Œ๋”๋ง ์ž‘์—… ์‹œ ์—…๋ฐ์ดํŠธ๋  UI ์ƒํƒœ๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์ž‘์—… ์ค‘์ธ ํŠธ๋ฆฌ๋Š” Virtual DOM์˜ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ƒˆ๋กœ์šด Virtual DOM ํŠธ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
  • ์ž‘์—… ์ค‘์ธ ํŠธ๋ฆฌ์—์„œ ๊ณ„์‚ฐ๋œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์‹ค์ œ DOM์— ๋ฐ˜์˜๋˜๊ธฐ ์ „์— reconciliation ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.
  1. Reconciliation(์žฌ์กฐ์ •) ๊ณผ์ •
  • React๋Š” ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ์™€ ์ž‘์—… ์ค‘์ธ ํŠธ๋ฆฌ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์„ ์ฐพ์•„๋ƒ…๋‹ˆ๋‹ค.
  • ์ด๋•Œ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ DOM์— ๋ฐ˜์˜๋˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ DOM ์กฐ์ž‘์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • Reconciliation ๊ณผ์ •์ด ์™„๋ฃŒ๋˜๋ฉด ์ž‘์—… ์ค‘์ธ ํŠธ๋ฆฌ๊ฐ€ ์ƒˆ๋กœ์šด ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
  1. DOM ์—…๋ฐ์ดํŠธ
  • Reconciliation ๋‹จ๊ณ„์—์„œ ๋ฐœ๊ฒฌ๋œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์‹ค์ œ DOM์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.
  • React๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ์ตœ์†Œํ•œ์˜ DOM ๋ณ€๊ฒฝ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๊ณผ์ •์—์„œ ์‹ค์ œ DOM๊ณผ ํ˜„์žฌ ํŒŒ์ด๋ฒ„ ํŠธ๋ฆฌ๊ฐ€ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.

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

๋ Œ๋” ๋‹จ๊ณ„์™€ ์ปค๋ฐ‹ ๋‹จ๊ณ„์— ๋Œ€ํ•ด ์•„๋‚˜์š”

๋ Œ๋” ๋‹จ๊ณ„(Render Phase)

์ด ๋‹จ๊ณ„์—์„œ๋Š” Virtual DOM ํŠธ๋ฆฌ์˜ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๊ณ„์‚ฐํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์— ์ƒˆ๋กœ์šด Virtual DOM ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. React๋Š” ์ด์ „ Virtual DOM๊ณผ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒˆ๋กœ์šด Virtual DOM ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ React๋Š” ๋ฌด์—‡์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๊ณ  ์ตœ์†Œํ•œ์˜ DOM ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ๋‹จ๊ณ„๋Š” ์™„์ „ํžˆ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์—์„œ ์ด๋ฃจ์–ด์ง€๋ฉฐ ์‹ค์ œ DOM์—๋Š” ์•„๋ฌด๋Ÿฐ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ปค๋ฐ‹ ๋‹จ๊ณ„(Commit Phase)

๋ Œ๋”๋ง ๋‹จ๊ณ„์—์„œ ๊ณ„์‚ฐ๋œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์‹ค์ œ DOM์— ๋ฐ˜์˜ํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. React๋Š” ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ DOM์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ React๋Š” ํ•„์š”ํ•œ DOM ๋…ธ๋“œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ถ”๊ฐ€, ๋ณ€๊ฒฝ ๋ฐ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ์˜ ์—…๋ฐ์ดํŠธ๋„ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ปค๋ฐ‹ ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋ณ€๊ฒฝ๋œ DOM์ด ํ™”๋ฉด์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

๋ Œ๋”๋ง๊ณผ ์ปค๋ฐ‹ ๋‹จ๊ณ„๋ฅผ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ React๋Š” ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค:

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

์ด๋ ‡๊ฒŒ React์˜ ๋‘ ๋‹จ๊ณ„ ๋ Œ๋”๋ง ๋ฐฉ์‹์€ Virtual DOM์„ ํ†ตํ•ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํšจ์œจ์ ์œผ๋กœ ๊ณ„์‚ฐํ•˜๊ณ  ๋ฐฐ์น˜ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

React์—์„œ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ์ฐจ์ด

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ

  • ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ตฌ์กฐ๋ฅผ ๋„๊ณ  ์žˆ์œผ๋ฉฐ, state๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” constructor (์ƒ์„ฑ์ž) ํ•จ์ˆ˜๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค
  • ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด state๋ฅผ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์— ๋น„ํ•ด์„œ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ณ , ์‚ฌ์ด์ฆˆ๊ฐ€ ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • state ๊ธฐ๋Šฅ ๋ฐ ๋ผ์ดํ”„ ์‚ฌ์ดํด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ž„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค
  • render ํ•จ์ˆ˜๊ฐ€ ๊ผญ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๊ทธ ์•ˆ์—์„œ ๋ณด์—ฌ ์ฃผ์–ด์•ผ ํ•  JSX๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค

  • Hooks ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด state๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š๋”๋ผ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค (useState() ๋“ฑ)
  • ์„ ์–ธํ•˜๊ธฐ๊ฐ€ ์ข€ ๋” ํŽธํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ๋œ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค
  • ์ œ๊ณต๋˜๋Š” hook ํ•จ์ˆ˜๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ปค์Šคํ…€ ํ›…์„ ์ƒ์„ฑํ•˜์—ฌ ๋™์ž‘์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค
  • ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์„ฑํ•˜์—ฌ ๋นŒ๋“œํ•œ ํ›„ ๋ฐฐํฌํ•  ๋•Œ๋„ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฒฐ๊ณผ๋ฌผ์˜ ํŒŒ์ผ ํฌ๊ธฐ๊ฐ€ ๋” ์ž‘์Šต๋‹ˆ๋‹ค

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” state์™€ ๋ผ์ดํ”„์‚ฌ์ดํด API์˜ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์ธ๋ฐ, ์ด๋ฅผ ํ•ด๊ฒฐ ํ•˜๊ธฐ ์œ„ํ•ด v16.8 ์—…๋ฐ์ดํŠธ ์ดํ›„์— ์ ์šฉ๋œ Hooks๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


๋ฆฌ์•กํŠธ์—์„œ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ์•Š๊ณ  ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”

(๋‹ต๋ณ€ ์ถœ์ฒ˜ - ํ…Œ์˜ค์˜ ํ”„๋ก ํŠธ์—”๋“œ ์ธ์„ฑ๋‹˜)

์›๋ž˜ ๋ฆฌ์•กํŠธ ์ธก์—์„œ๋Š” ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ๋„ค์ด๋ฐ์ด ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ณผ ๋น„์Šทํ–ˆ๊ณ , ์ถฉ๋ถ„ํžˆ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ ๋ฆฌ์•กํŠธ์˜ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐฐ์šฐ๋Š” ์ž…์žฅ์—์„œ๋Š” 'ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค'์™€ ๊ฐ™์€ ํ˜ผ๋ž€์„ ๋Š๋‚„ ์ˆ˜ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๊ฐ€ ๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋Š” ํ›…(hook)์ด ๋“ค์–ด๊ฐ€๊ณ , ์ด ํ›…์œผ๋กœ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ ๋ฅผ ๋นˆ๋ฒˆํžˆ ์ผ์œผํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ฅผ ์ง€ํ–ฅํ•˜๋Š”๋ฐ, ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ๋นˆ๋ฒˆํžˆ ์ผ์œผํ‚ค๋Š” ๋ฆฌ์•กํŠธ์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณด๊ธฐ๋Š” ์–ด๋ ต๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2018๋…„ ์ดํ›„ ๋ฆฌ์•กํŠธ ์ธก์—์„œ๋„ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋กœ ์ด๋ฆ„์„ ๋‹ค์‹œ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

Rename "functional component" to "function component"


props์™€ state์˜ ์ฐจ์ด

  • props : ์ปดํฌ๋„ŒํŠธ ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์š”์†Œ์ด๋‹ค. props๊ฐ’์€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • state : ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐ”๋€”์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ์˜๋ฏธํ•œ๋‹ค. props๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ณผ์ •์—์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์„ค์ •ํ•˜๋Š” ๊ฐ’์ด๋ฉฐ, ์ปดํฌ๋„ŒํŠธ ์ž์‹ ์€ ํ•ด๋‹น props๋ฅผ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. props๋ฅผ ๋ฐ”๊พธ๋ ค๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ”๊พธ์–ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

props & state


props๊ฐ€ ์ปดํฌ๋„ŒํŠธ๊ฐ„์— ์ „๋‹ฌ๋ฐ›๋Š” ๊ฒƒ์ด๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ๋„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€

  1. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋‹ค. (์ž์‹์ด props๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ค„ ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์ด๋‹ค.)

  2. ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ• = ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.

  • ์ž์‹์€ props๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ถ€๋ชจ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฑด๋„ค์ค„ ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ๋ถ€๋ชจ๊ฐ€ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด props๋กœ ์ž์‹์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋ฉด, ์ž์‹์ด ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ์ฆ‰, ๋ถ€๋ชจ๊ฐ€ props๋กœ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ์ž์‹์ด ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ๊ฑด๋„ค์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.

FLUX์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”

๋งํฌ ๋ฒจ๋กœํผํŠธ๋‹˜ ์œ ํŠœ๋ธŒ

๋งํฌ FLUX ์นดํˆฐ ์•ˆ๋‚ด์„œ

๋ฆฌ๋•์Šค๋Š” ํŽ˜์ด์Šค๋ถ์—์„œ ๋ฆฌ์•กํŠธ๊ฐ€ ํ•จ๊ป˜ ์†Œ๊ฐœํ•œ FLUX ์•„ํ‚คํ…์ณ๋กœ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ

type StoreState = {
  count: number;
};

type Action = { type: 'add'; payload: number };

function reducer(state: StoreState, action: Action) {
  const { type: ActionType, payload } = action;

  if (ActionType === 'add') {
    return {
      count: state.count + payload,
    };
  }

  throw new Error(`Unexpected action type: ${ActionType}`);
}

export default function App() {
  const [state, dispatcher] = useReducer(reducer, { count: 0 });

  function handleClick() {
    dispatcher({ type: 'add', payload: 1 });
  }

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={handleClick}>Add</button>
    </div>
  );
}

๊ทธ๋ ‡๋‹ค๋ฉด FLUX๋Š” ๋ญ˜๊นŒ์š”? FLUX๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์•„๋‹Œ ์ถ”์ƒ์ ์ธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

MVC ํŒจํ„ด์—์„œ ์Œ๋ฑกํ–ฅ์ ์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ฐ•์กฐํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ FLUX ํŒจํ„ด์—์„œ๋Š” ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค.

MVC ํŒจํ„ด์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž์˜ ์–ด๋– ํ•œ ํ–‰์œ„(์•ก์…˜)๊ฐ€ ์žˆ์„ ๋•Œ, ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์„ค๊ณ„๋œ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์„ ๋ณ€ํ™”ํ•˜๊ณ  ์ด๋ฅผ ๋ทฐ์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

MVC ํŒจํ„ด

๋ณด์—ฌ์ ธ์•ผ ํ•  ๋ทฐ๊ฐ€ ์ ๊ฑฐ๋‚˜, ๋ณ€๊ฒฝ๋  ๋ชจ๋ธ์ด ๋งŽ์ง€ ์•Š๋‹ค๋ฉด ๋งค์šฐ ํšจ์œจ์ ์ธ ๊ตฌ์กฐ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๋ชจ๋ธ๊ณผ ๋ทฐ๊ฐ€ ๋ณต์žกํ•˜๊ฒŒ ์–ฝํ˜€ ์žˆ๋‹ค๋ฉด ์–ด๋–ค ๋ชจ๋ธ์ด ๋ณ€ํ™”๋˜์–ด ๋ทฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์ œ๋Œ€๋กœ ํ™•์ธํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค.

MVC ํŒจํ„ด

์‹ค์ œ๋กœ ํŽ˜์ด์Šค๋ถ์—์„œ๋Š” MVC ํŒจํ„ด์œผ๋กœ ์„ค๊ณ„ํ•œ ๊ตฌ์กฐ ๋•Œ๋ฌธ์—, ์•„์ง ์ฝ์ง€ ์•Š์€ ๋ฉ”์„ธ์ง€๋ฅผ ํ‘œ์‹œํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ ๋“ค์–ด๊ฐ€ ๋ณด๋ฉด ์ƒˆ๋กœ์šด ๋ฉ”์„ธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ œ์–ดํ•˜๋Š” ํŒจํ„ด์ด FLUX ์ž…๋‹ˆ๋‹ค.

FLUX ํŒจํ„ด

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

๋ทฐ์—์„œ๋Š” ์Šคํ† ์–ด์— ์ง์ ‘ ์ ‘๊ทผํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๋””์ŠคํŒจ์ฒ˜๋กœ ๋‹ค์‹œ ์•ก์…˜์„ ๋ณด๋‚ด๊ณ  ์Šคํ† ์–ด๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ๋’ค, ๋‹ค์‹œ ๋ทฐ๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•˜๋Š” ๋‹จ๋ฐฉํ–ฅ์  ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

FLUX ํŒจํ„ด์€ ์ด๋Ÿฌํ•œ ๋‹จ๋ฐฉํ–ฅ์ ์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ์–ด๋–ค ์•ก์…˜์ด ๋””์ŠคํŒจ์ฒ˜์— ์˜ํ•ด ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ๋‚ณ๊ณ  ๋ณ€ํ™”๋˜๋Š”์ง€ ๋ช…ํ™•ํžˆ ํŒŒ์•…ํ•˜๊ณ  ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋•์Šค์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”

๋ฆฌ๋•์Šค๋Š” ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋•์Šค๋Š” Store(์Šคํ† ์–ด)๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ์ „์—ญ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ „์—ญ์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— props <-> state๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ, ์ž์‹์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‚ด๋ ค์ฃผ์ง€ ์•Š์•„๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋•์Šค์˜ ๊ธฐ๋ณธ ์›์น™์€

  1. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์ „์—ญ์ƒํƒœ๋Š” ๋‹จ์ผ ์ €์žฅ์†Œ ๋‚ด์˜ ํŠธ๋ฆฌ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค
  2. ์ƒํƒœ(state)๋Š” ์ฝ๊ธฐ ์ „์šฉ์ž…๋‹ˆ๋‹ค.
  3. ์ˆœ์ˆ˜ ํ•จ์ˆ˜์— ์˜ํ•ด์„œ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ctrl + F '๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๋Š” ํ•จ์ˆ˜ (์ˆœ์ˆ˜ ํ•จ์ˆ˜)'

ctrl + F '๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์žˆ๋Š” ๋ฐฐ์—ด์˜ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ'

React์—์„œ state์˜ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ผ๋Š” ๋ง์ด ์žˆ๋Š”๋ฐ ์ด์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋‹ฌ๋ผ

๊ฐ์ฒด๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐ’์ด ์•„๋‹Œ ์ฐธ์กฐ ๊ฐ’์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์‚ฌํ•˜์—ฌ ๋™์ผํ•œ ์ฐธ์กฐ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ๊ฐ์ฒด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด, ๋ชจ๋“  ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

์ด๋ฏธ ๋ณต์‚ฌ๋ฅผ ํ•œ ํ”„๋ฆฐํŠธ ๋ฌผ์€ A ์ธ์‡„๋ฌผ์— ๋‚™์„œ๋ฅผ ํ•˜๋”๋ผ๋„ B ์ธ์‡„๋ฌผ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค

๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ๊ฐ์ฒด ํ˜•์‹ ๋˜๋Š” ๋ฐฐ์—ด ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŽ์ด ๋‹ค๋ฃจ๊ฒŒ ๋˜๋Š”๋ฐ, ์›๋ณธ ๋ฐฐ์—ด์ด ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ ์˜๋„ํ•œ ๋™์ž‘๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์–ด๋–ค ํ•จ์ˆ˜์— ์˜ํ•ด ๋ถ€์ˆ˜ํšจ๊ณผ(side effect)๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ฐพ๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let A = {
  name: 'junhee',
  age: 25,
  job: 'student',
};

B = { ...A };

console.log('A', A);
console.log('B', B);
/*
A { name: 'junhee', age: 25, job: 'student' }
B { name: 'junhee', age: 25, job: 'student' }
*/

B = { ...A, job: 'frontend developer' };

console.log('A', A);
console.log('B', B);

/*
A { name: 'junhee', age: 25, job: 'student' }
B { name: 'junhee', age: 25, job: 'frontend developer' }
*/

๋ฆฌ๋“€์„œ ๋‚ด๋ถ€์—์„œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋Š” ์ด์œ ๋Š”? ์ „๊ฐœ ์—ฐ์‚ฐ์ž์˜ ๋‹จ์ ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€

์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด ๋„ค ๊ฐ€์ง€ ๊ฒฝ์šฐ์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

  • props๊ฐ€ ๋ฐ”๋€” ๋•Œ
  • state๊ฐ€ ๋ฐ”๋€” ๋•Œ
  • ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ
  • this.forceUpdate๋กœ ๊ฐ•์ œ๋กœ ๋ Œ๋”๋ง์„ ํŠธ๋ฆฌ๊ฑฐํ•  ๋•Œ

๋ฆฌ๋“€์„œ์˜ initial state์—๋Š” ์„œ๋ฒ„์—์„œ ๋„˜๊ฒจ๋ฐ›๋Š” ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ์ „์—ญ์œผ๋กœ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ €์žฅ์†Œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

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

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

const nextState = {
  ...state,
  posts: state.posts.map((post) =>
    post.id === 1
      ? {
          ...post,
          comments: post.comments.concat({
            id: 3,
            text: '์ƒˆ๋กœ์šด ๋Œ“๊ธ€',
          }),
        }
      : post
  ),
};

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ immer ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

produce, draft๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ์กด์˜ ... spread ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•ด์ฃผ๋ฉฐ ๋ถˆํ•„์š”ํ•œ ๋ถ€์ˆ˜ํšจ๊ณผ(side effect)๋ฅผ ๋ง‰์•„์ค๋‹ˆ๋‹ค.

const nextState = produce(state, (draft) => {
  const post = draft.posts.find((post) => post.id === 1);
  post.comments.push({
    id: 3,
    text: '์™€ ์ •๋ง ์‰ฝ๋‹ค!',
  });
});

๋ฆฌ์•กํŠธ ์‚ฌ์šฉ์‹œ์— ๋ถ€์ˆ˜ํšจ๊ณผ๋กœ ์ธํ•ด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ์ ์ด ์žˆ๋‹ค๋ฉด

๋ถ€์ˆ˜ํšจ๊ณผ ์—†๋Š” "์ˆœ์ˆ˜ํ•จ์ˆ˜" ๋ง›๋ณด๊ธฐ

๋ถ€์ˆ˜ํšจ๊ณผ๋ž€ ํ•จ์ˆ˜๊ฐ€ ๋งŒ๋“ค์–ด์ง„ ๋ชฉ์ ๊ณผ๋Š” ๋‹ค๋ฅธ ํšจ๊ณผ ๋˜๋Š” ๋ถ€์ž‘์šฉ์ž…๋‹ˆ๋‹ค.

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

๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ์ผ์œผํ‚ค๋Š” ํ•จ์ˆ˜ (๋ถˆ์ˆœ ํ•จ์ˆ˜)

/* ์ฝ”๋“œ ์ฐธ์กฐ (https://maxkim-j.github.io/posts/js-pure-function) */

// http ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ํ•จ์ˆ˜ : ์ˆœ์ˆ˜ํ•จ์ˆ˜ ๋  ์ˆ˜ ์—†์Œ
const getData = () => {
  axios.get('http://data.url')
  .then(...)
  .catch(...)
}

// ์ž…๋ ฅ ๋‚ดํฌํ•œ ํ•จ์ˆ˜ : ์ˆœ์ˆ˜ํ•จ์ˆ˜ ๋  ์ˆ˜ ์—†์Œ
const typeInput = () => {
  const input = prompt("Message");
  return input;
}

// ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜ : ์ˆœ์ˆ˜ํ•จ์ˆ˜ ๋  ์ˆ˜ ์—†์Œ
const changeParams = (arr, elem) => {
  arr.push(elem);
  return arr;
}

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

๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋“ค์–ด์˜จ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜ ์—ญ์‹œ ์ˆœ์ˆ˜ํ•จ์ˆ˜๊ฐ€ ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ์ฐธ์กฐ ์ž๋ฃŒํ˜• ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ง์ ‘ ๋ณ€๊ฒฝํ•œ๋‹ค๋ฉด, ๋‚˜์ค‘์— ์ด ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ์ž‘์—…์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋’ค์—์„œ ์ข€ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ถˆ์ˆœ ํ•จ์ˆ˜๋ผ๋Š” ๋ง์ด ๋ถ€์ •์ ์ธ ๋‰˜์•™์Šค๋ฅผ ๋‚ดํฌํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ™์ง€๋งŒ, ๋ง‰ ๋‚˜์œ๊ฑด ์•„๋‹™๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ http ์š”์ฒญ์ฒ˜๋Ÿผ ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๋Š” ํ•จ์ˆ˜ (์ˆœ์ˆ˜ ํ•จ์ˆ˜)

ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋“ค์–ด์˜จ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ๋งŒ ํ•ด๋„, ์ˆœ์ˆ˜ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ง์ ‘ ์กฐ์ž‘์„ ํ”ผํ•˜๋Š” ์ด์œ ๋Š” ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋˜ ์–ด๋””์— ์“ฐ์ผ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

/* ์ฝ”๋“œ ์ฐธ์กฐ (https://maxkim-j.github.io/posts/js-pure-function) */

const num_arr = [1, 2, 3, 4, 5];

// ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๋ถˆ์ˆœํ•จ์ˆ˜
const addSixImpure = (arr) => {
  // ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ง์ ‘ 6 ์ถ”๊ฐ€
  arr.push(6);
  return arr;
};

// ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ณต์‚ฌํ•œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜
const addSixPure = (arr) => {
  // ํŽผ์นจ ์—ฐ์‚ฐ์ž๋กœ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— 6 ์ถ”๊ฐ€
  newArr = [...arr, 6];
  return newArr;
};

// ๋งค๊ฐœ๋ณ€์ˆ˜ arr์— 6์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜
const hasSix = (arr) => {
  if (arr.includes(6)) {
    return true;
  } else {
    return false;
  }
};

const new_arr = addSixImpure(num_arr);
console.log(hasSix(num_arr)); // true

addSixPure()๊ณผ addSixInpure()๋Š” ์–ธ๋œป ๋ณด๋ฉด ๋ณ„ ์ฐจ์ด๊ฐ€ ์—†์–ด ๋ณด์ด์ง€๋งŒ, addSixInpure()๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๋ถˆ์ˆœํ•จ์ˆ˜์ด๊ณ , addSixPure()๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

addSixInpure()๋Š” num_arr์„ ์ง์ ‘ ๋ฐ”๊ฟจ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด num_arr์˜ ๊ฐ’์ด [1,2,3,4,5,6]์œผ๋กœ ์˜๊ตฌํžˆ ๋ฐ”๋€๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ hasSix()ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋กœ๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜์ฃ .

ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์ž์˜ ์˜๋„๊ฐ€ ๋ณ€์ˆ˜ new_arr์— addSix ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ํ• ๋‹นํ•˜๊ณ  ๋‚œ ํ›„, ๊ฐ’์ด [1,2,3,4,5]์ธ num_arr์— ๋Œ€ํ•ด์„œ 6์ด ์žˆ๋Š”์ง€ ํŒ๋‹จํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๊ฑฐ์˜€๋‹ค๋ฉด ์ฝ”๋“œ๋Š” ์˜๋„๋Œ€๋กœ ์‹คํ–‰๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์˜๋„๋Œ€๋กœ๋ผ๋ฉด false๊ฐ€ ๋‚˜์™€์•ผ ํ•˜๋Š”๋ฐ, num_arr์ด ์ด๋ฏธ ๋ณ€๊ฒฝ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” addSixํ•จ์ˆ˜๊ฐ€ num_arr์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹ ์— ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜์ฃ 

const new_arr = addSixPure(num_arr);
console.log(hasSix(num_arr)); // false

addSixPure()๋Š” num_arr์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— num_arr์— ์ฒ˜์Œ ํ• ๋‹น๋˜์—ˆ๋˜ ๊ฐ’์€ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ hasSix(num_arr)์˜ ๊ฒฐ๊ณผ๋Š” false์ž…๋‹ˆ๋‹ค.

์ด ์˜ˆ์‹œ๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ฝ”๋“œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. addSixInpure()๊ฐ€ 6์„ num_arr์— ์ถ”๊ฐ€ํ•ด๋ฒ„๋ฆฐ ๋ถ€์ˆ˜ํšจ๊ณผ ๋•Œ๋ฌธ์— hasSix()์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ถ€์ •ํ™•ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋“ค์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜์ง€ ์•Š์„์ˆ˜๋ก ํ•จ์ˆ˜๋“ค์€ ๋ถ€์ˆ˜ํšจ๊ณผ ์—†์ด ๊ฐœ๋ฐœ์ž์˜ ์˜๋„๋Œ€๋กœ ์›€์ง์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.

์š”์•ฝ

React state๋Š” ์ง์ ‘ ์กฐ์ž‘์„ ํ”ผํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.(state, props๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋ฆฌ๋ Œ๋”๋ง์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„์น˜ ์•Š๊ฒŒ ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜๋“ค๋กœ ์ธํ•ด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์ด ์žฆ์•„์งˆ ์ˆ˜ ์žˆ๋‹ค) Redux์˜ reducer๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜์—ฌ์•ผ๋งŒ ํ•˜๋Š”๋ฐ, store๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ๋™๋ฐ˜ํ•˜์ง€ ์•Š์•„์•ผ store ๋‚ด๋ถ€์˜ ๊ฐ’๋“ค์ด ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

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

๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์žˆ๋Š” ๋ฐฐ์—ด์˜ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ

์ฐธ๊ณ ์ž๋ฃŒ

const arr = [1];

// push ๋ฉ”์„œ๋“œ๋Š” ์›๋ณธ ๋ฐฐ์—ด(arr)์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•œ๋‹ค.
arr.push(2);
console.log(arr); // [1, 2]

// concat ๋ฉ”์„œ๋“œ๋Š” ์›๋ณธ ๋ฐฐ์—ด(arr)์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
const result = arr.concat(3);
console.log(arr); // [1, 2]
console.log(result); // [1, 2, 3]

/* 

๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์žˆ๋Š” ๋ฐฐ์—ด์˜ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ

Array.isArray 
Array.prototype.indexOf 
Array.prototype.push (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.pop (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.unshift (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.shift (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.concat 
Array.prototype.splice ๐ŸŒŸ (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.slice 
Array.prototype.join ๐ŸŒŸ (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.reverse ๐ŸŒŸ (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.fill ๐ŸŒŸ (์›๋ณธ ๋ฐฐ์—ด์„ ๋ณ€๊ฒฝํ•œ๋‹ค - ๋ถ€์ˆ˜ํšจ๊ณผ o)
Array.prototype.includes 
*/

์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด ๋ฉ”์„œ๋“œ

๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ์˜ ์ข…๋ฅ˜๋Š” ์ด ์•„ํ™‰ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  • will ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์€ ๋ฉ”์„œ๋“œ๋Š” ์–ด๋–ค ์ž‘์—…์„ ์ž‘๋™ํ•˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.
  • Did ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์€ ๋ฉ”์„œ๋“œ๋Š” ์–ด๋–ค ์ž‘์—…์„ ์ž‘๋™ํ•œ ํ›„์— ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋“ค์€ ์šฐ๋ฆฌ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ํด๋ž˜์Šค์—์„œ ๋ฎ์–ด ์จ ์„ ์–ธํ•จ์œผ๋กœ์จ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์ดํ”„์‚ฌ์ดํด์€ ์ด ์„ธ ๊ฐ€์ง€, ์ฆ‰ ๋งˆ์šดํŠธ, ์—…๋ฐ์ดํŠธ, ์–ธ๋งˆ์šดํŠธ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋‚˜๋ˆ•๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ ๋ผ์ดํ”„ ์‚ฌ์ดํด ๋ฉ”์„œ๋“œ

  1. ๋งˆ์šดํŠธ
  • DOM์ด ์ƒ์„ฑ๋˜๊ณ  ์›น ๋ธŒ๋ผ์šฐ์ €์ƒ์— ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ๋งˆ์šดํŠธ๋ผ๊ณ  ํ•œ๋‹ค.

  • componentDidMount : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €์ƒ์— ๋‚˜ํƒ€๋‚œ ํ›„ ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.


  1. ์—…๋ฐ์ดํŠธ

์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด ๋„ค ๊ฐ€์ง€ ๊ฒฝ์šฐ์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

  • Props๊ฐ€ ๋ฐ”๋€” ๋•Œ

  • state๊ฐ€ ๋ฐ”๋€” ๋•Œ

  • ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ

  • this.forceUpdate๋กœ ๊ฐ•์ œ๋กœ ๋ Œ๋”๋ง์„ ํŠธ๋ฆฌ๊ฑฐํ•  ๋•Œ

  • componentDidUpdate : ์ปดํฌ๋„ŒํŠธ์˜ ์—…๋ฐ์ดํŠธ(๋ฆฌ๋ Œ๋”๋ง) ์ž‘์—…์ด ๋๋‚œ ํ›„ ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.


  1. ์–ธ๋งˆ์šดํŠธ
  • ๋งˆ์šดํŠธ์˜ ๋ฐ˜๋Œ€ ๊ณผ์ •, ์ฆ‰ ์ปดํฌ๋„ŒํŠธ๋ฅผ DOM์—์„œ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

  • componentWillUnmount : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €์‚ฌ์—์„œ ์‚ฌ๋ผ์ง€๊ธฐ ์ „์— ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ


Hooks์˜ ์ข…๋ฅ˜

Hooks๋Š” ๋ฆฌ์•กํŠธ ๋ฒ„์ „ 16.8์— ์ƒˆ๋กœ ๋„์ž…๋œ ๊ธฐ๋Šฅ์œผ๋กœ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” useState ๋ Œ๋”๋ง ์งํ›„ ์ž‘์—…์„ ์„ค์ •ํ•˜๋Š” useEffect ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ๊ธฐ์กด์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•  ์ˆ˜ ์—†์—ˆ๋˜ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค

  1. useState
  • ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Hook์ด๋‹ค. ์ฒซ ๋ฒˆ์งธ ์›์†Œ๋Š” ์ƒํƒœ ๊ฐ’, ๋‘ ๋ฒˆ์งธ ์›์†Œ๋Š” ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ์ด ํ•จ์ˆ˜์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ํ˜ธ์ถœํ•˜๋ฉด ์ „๋‹ฌ๋ฐ›์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ’์ด ๋ฐ”๋€Œ๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง ๋ฉ๋‹ˆ๋‹ค
import { useState } from 'react';

const [value, setValue] = useState(0);

useState ๋‚ด๋ถ€์˜ ๋ชจ์Šต์„ ๊ตฌํ˜„ํ•œ ๋ชจ์Šต

const MyReact = (function () {
  const global = {};
  let index = 0;

  function useState(initialState) {
    if (!global.states) {
      // ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์˜ states ๋ฐฐ์—ด์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
      // ์ตœ์ดˆ ์ ‘๊ทผ์ด๋ผ๋ฉด ๋นˆ ๋ฐฐ์—ด๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
      global.states = [];
    }

    // states ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด์„œ ํ˜„์žฌ ์ƒํƒœ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์—†๋‹ค๋ฉด ์ดˆ๊นƒ๊ฐ’์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.
    const currentState = global.states[index] || initialState;
    // states์˜ ๊ฐ’์„ ์œ„์—์„œ ์กฐํšŒํ•œ ํ˜„์žฌ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
    global.states[index] = currentState;

    // ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๋กœ setter๋ฅผ ๋งŒ๋“ ๋‹ค.
    const setState = (function () {
      // ํ˜„์žฌ index๋ฅผ ํด๋กœ์ €๋กœ ๊ฐ€๋‘ฌ๋†”์„œ ์ดํ›„์—๋„ ๊ณ„์†ํ•ด์„œ ๋™์ธํ•œ index์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
      let currentIndex = index;
      return function (value) {
        global.states[currentIndex] = value;
        // ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค. ์‹ค์ œ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ์ฝ”๋“œ๋Š” ์ƒ๋žตํ–ˆ๋‹ค.
      };
    })();

    /**
     * useState๋ฅผ ์“ธ ๋•Œ๋งˆ๋‹ค index๋ฅผ ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด index๋Š” setState์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
     * ์ฆ‰, ํ•˜๋‚˜์˜ state๋งˆ๋‹ค index๊ฐ€ ํ• ๋‹น๋ผ ์žˆ์–ด ๊ทธ index๊ฐ€ ๋ฐฐ์—ด์˜ ๊ฐ’(global.states)์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•œ๋‹ค.
     **/

    index = index + 1;

    return [currentState, setState];
  }

  function Component() {
    const [value, setValue] = useState(0);

    //...
    return <div>{value}</div>;
  }
})();

  1. useEffect
  • ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” Hook ์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ componontDidMount์™€ componentDidUpdate๋ฅผ ํ•ฉ์นœ ํ˜•ํƒœ๋กœ ๋ณด์•„๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค

๋งˆ์šดํŠธ๋งŒ ์‹คํ–‰์‹œํ‚ค๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ : ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋น„์–ด์žˆ๋Š” ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค

useEffect(() => {
  console.log('๋งˆ์šดํŠธ๋  ๋•Œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.');
}, []);

ํŠน์ • ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ : ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฐฐ์—ด ์•ˆ์— ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์€ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค

useEffect(() => {
  console.log(name);
}, [name]);

๋’ท ์ •๋ฆฌ ํ•˜๊ธฐ:

  • ์ •๋ฆฌ : useEffect๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ Œ๋”๋ง๋˜๊ณ  ๋‚œ ์งํ›„๋งˆ๋‹ค ์‹คํ–‰๋˜๋ฉฐ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐฐ์—ด์— ๋ฌด์—‡์„ ๋„ฃ๋Š”์ง€์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ์กฐ๊ฑด์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค

useEffect๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ Œ๋”๋ง๋˜๊ณ  ๋‚œ ์งํ›„๋งˆ๋‹ค ์‹คํ–‰๋˜๋ฉฐ, ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐฐ์—ด์— ๋ฌด์—‡์„ ๋„ฃ๋Š”์ง€์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ์กฐ๊ฑด์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ ์ „์ด๋‚˜ ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ์ง์ „์— ์–ด๋– ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด useEffect์—์„œ ๋’ท์ •๋ฆฌ(cleanup) ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์–ธ๋งˆ์šดํŠธ ์‹œ์— ์ž‘์—…ํ•  ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

useEffect(() => {
    console.log("๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
    console.log("none clean up: ", { name, nickname });
    return () => {
      console.log("clean up!");
      console.log("clean up name: ", { name });
    };
  }

๋’ท์ •๋ฆฌํ•จ์ˆ˜


  1. useReducer
  • useReducer๋Š” useState๋ณด๋‹ค ๋” ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์ƒํƒœ๋ฅผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” Hook์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๋Š” ํ˜„์žฌ ์ƒํƒœ, ๊ทธ๋ฆฌ๊ณ  ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ์•ก์…˜ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์•„ ์ƒˆ๋กœ์šด ์ƒํƒœ์— ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ ํ•จ์ˆ˜์—์„œ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋งŒ๋“ค ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
type State = {
  count: number,
};

type Action = { type: 'up' | 'down' | 'reset', payload?: State };

function init(count: State): State {
  return count;
}

const initialState: State = { count: 0 };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'up':
      return { count: state.count + 1 };
    case 'down':
      return { count: state.count - 1 };
    case 'reset':
      return init(action.payload || { count: 0 });
    default:
      throw new Error(`Unexpected action type ${action.type}`);
  }
}

export default function App() {
  const [state, dispatcher] = useReducer(reducer, initialState, init);

  function handleUpButtonClick() {
    dispatcher({ type: 'up' });
  }

  function handleDownButtonClick() {
    dispatcher({ type: 'down' });
  }

  function handleResetButtonClick() {
    dispatcher({ type: 'reset', payload: { count: 1 } });
  }

  return (
    <div>
      <h1>{state.count}</h1>
      <button onClick={handleDownButtonClick}>+</button>
      <button onClick={handleDownButtonClick}>-</button>
      <button onClick={handleResetButtonClick}>reset</button>
    </div>
  );
}

useReducer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ์Šต์ด ์–ธ๋œป ๋ณด๋ฉด ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ useReducer์˜ ๋ชฉ์ ์€ ๊ฐ„๋‹คํ•ฉ๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ํ˜•ํƒœ์˜ state๋ฅผ ์‚ฌ์ „์— ์ •์˜๋œ dispatcher๋กœ๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ์คŒ์œผ๋กœ์จ state ๊ฐ’์— ๋Œ€ํ•œ ์ ‘๊ทผ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ณ , ์ด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ƒ์„ธ ์ •์˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฐ–์— ๋‘” ๋‹ค์Œ, state์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด ๋‘” dispatcher๋กœ๋งŒ ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

state์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ œํ•œ์ ์œผ๋กœ ๋‘๊ณ  ์ด์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์„ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•˜๋Š” ๊ฒƒ์ด useReducer์˜ ๋ชฉ์ ์ด๋‹ค.


  1. useMemo

useMemo๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—ฐ์‚ฐ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ๋ฆฌ์ŠคํŠธ์— ์ˆซ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ถ”๊ฐ€๋œ ์ˆซ์ž๋“ค์˜ ํ‰๊ท ์„ ๋ณด์—ฌ ์ฃผ๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ด ๋ด…์‹œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ˆซ์ž๋ฅผ ๋“ฑ๋กํ•  ๋•Œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ธํ’‹ ๋‚ด์šฉ์ด ์ˆ˜์ •๋  ๋•Œ๋„ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  getAverage ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธํ’‹ ๋‚ด์šฉ์ด ๋ฐ”๋€” ๋•Œ๋Š” ํ‰๊ท ๊ฐ’์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•  ํ•„์š”๊ฐ€ ์—†๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์€ ๋‚ญ๋น„๊ฒ ์ง€์š”?

useMemo Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ Œ๋”๋งํ•˜๋Š” ๊ณผ์ •์—์„œ ํŠน์ • ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋งŒ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ•˜๊ณ , ์›ํ•˜๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „์— ์—ฐ์‚ฐํ–ˆ๋˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

memo

์ฝ”๋“œ ๋ณด๊ธฐ
import React, { useCallback, useMemo, useRef, useState } from 'react';

const getAverage = (numbers) => {
  console.log('ํ‰๊ท ๊ฐ’ ๊ณ„์‚ฐ ์ค‘..');
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};

const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
  const inputEl = useRef();

  const onChange = useCallback((e) => {
    setNumber(e.target.value);
  }, []); // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋ Œ๋”๋ง๋  ๋•Œ๋งŒ ํ•จ์ˆ˜ ์ƒ์„ฑ

  const onInsert = useCallback(
    (e) => {
      const nextList = list.concat(parseInt(number));
      setList(nextList);
      setNumber('');
      inputEl.current.focus();
    },
    [number, list] // number ํ˜น์€ list๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋งŒ ํ•จ์ˆ˜ ์ƒ์„ฑ
  );

  const avg = useMemo(() => getAverage(list), [list]);

  return (
    <div>
      <input value={number} onChange={onChange} ref={inputEl} />
      <button onClick={onInsert}>๋“ฑ๋ก</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>ํ‰๊ท ๊ฐ’:</b> {avg}
      </div>
    </div>
  );
};

export default Average;

  1. useCallback
  • useMemo์™€ ์ƒ๋‹นํžˆ ๋น„์Šทํ•œ ํ•จ์ˆ˜์ด๋‹ค. ์ฃผ๋กœ ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค. ์ด Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งŒ๋“ค์–ด๋†จ๋˜ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. useCallback์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ƒ์„ฑํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜๋ฅผ ๋„ฃ๊ณ , ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค. ์ด ๋ฐฐ์—ด์—๋Š” ์–ด๋–ค ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š”์ง€ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.
const onChange = useCallback((e) => {
  setNumber(e.target.value);
}, []); // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋ Œ๋”๋ง๋  ๋•Œ๋งŒ ํ•จ์ˆ˜ ์ƒ์„ฑ


const onInsert = useCallback(
  (e) => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber("");
  },
  [number, list] // number ํ˜น์€ list๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋งŒ ํ•จ์ˆ˜ ์ƒ์„ฑ
);


useMemo(() => {
  const fn = () => {
    console.log(โ€˜hello world!โ€˜);
  };
  return fn;
}, [])

onChange์ฒ˜๋Ÿผ ๋น„์–ด ์žˆ๋Š” ๋ฐฐ์—ด์„ ๋„ฃ๊ฒŒ ๋˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, onInsert์ฒ˜๋Ÿผ ๋ฐฐ์—ด ์•ˆ์— number์™€ list๋ฅผ ๋„ฃ๊ฒŒ ๋˜๋ฉด ์ธํ’‹ ๋‚ด์šฉ์ด ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋  ๋•Œ๋งˆ๋‹ค ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ƒํƒœ ๊ฐ’์— ์˜์กดํ•ด์•ผ ํ•  ๋•Œ๋Š” ๊ทธ ๊ฐ’์„ ๋ฐ˜๋“œ์‹œ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ ์•ˆ์— ํฌํ•จ์‹œ์ผœ ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด onChange์˜ ๊ฒฝ์šฐ ๊ธฐ์กด์˜ ๊ฐ’์„ ์กฐํšŒํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์„ค์ •๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด์ด ๋น„์–ด ์žˆ์–ด๋„ ์ƒ๊ด€์—†์ง€๋งŒ, onInsert๋Š” ๊ธฐ์กด์˜ number์™€ list๋ฅผ ์กฐํšŒํ•ด์„œ nextList๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด ์•ˆ์— number์™€ list๋ฅผ ๊ผญ ๋„ฃ์–ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ๋‹ค์Œ ๋‘ ์ฝ”๋“œ๋Š” ์™„์ „ํžˆ ๋˜‘๊ฐ™์€ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

useCallback(() => {
  console.log('hello world!');
}, []);

useMemo(() => {
  const fn = () => {
    console.log('hello world!');
  };
  return fn;
}, []);
  1. useRef
  • ๋ฐ”๋‹๋ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ DOM ์š”์†Œ๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด querySelector๋‚˜ getElementById ๋“ฑ์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด, ๋ฆฌ์•กํŠธ์—์„œ๋Š” useRef ํ›… ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • useRef๋Š” .current ํ”„๋กœํผํ‹ฐ์— ๋ณ€๊ฒฝ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ๋‹ด๊ณ ์žˆ๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค
  • .currentํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ref ๊ฐ์ฒด ์•ˆ์˜ ๊ฐ’์€ ๋ฆฌ์•กํŠธ ์ƒ๋ช…์ฃผ๊ธฐ์— ๋…๋ฆฝ์ ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค
import React, { useRef, Component } from 'react';

class RefSample extends Component {
  input = useRef();

  handleFocus = () => {
    this.input.current.focus();
  };

  render() {
    return (
      <div>
        <input ref={input} />
      </div>
    );
  }
}

export default RefSample;

useMemo์™€ useCallback์˜ ์ฐจ์ด๋ฅผ ์•„๋‚˜์š”

  • useMemo ํ•จ์ˆ˜๋Š” ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค
  • useCallback ํ•จ์ˆ˜๋Š” ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๋œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค
Memoization(๋ฉ”๋ชจ์ด์ œ์ด์…˜)

ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์‹œ ์ด์ „์— ๊ณ„์‚ฐํ•œ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค
์›ํ•˜๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „์— ์—ฐ์‚ฐํ–ˆ๋˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ๋ฆฌ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค

  • props๊ฐ€ ๋ฐ”๋€” ๋•Œ
  • state๊ฐ€ ๋ฐ”๋€” ๋•Œ
  • ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ

์ปดํฌ๋„ŒํŠธ๋Š” state์™€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ props ๋“ฑ ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์— ์˜ํ•ด ์‰ฝ๊ฒŒ ๋ฆฌ๋ Œ๋”๋ง์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋‚ด๊ฐ€ ๋งŒ๋“  ์„œ๋น„์Šค์˜ ์„ฑ๋Šฅ ์ €ํ•˜์— ๊ฐ€์žฅ ํฐ ์›์ธ์ด ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํŠน์ • ์ƒํ™ฉ (๊ฐ’, ๋˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ)์— ๋งž๊ฒŒ ๋ฆฌ๋ Œ๋”๋ง์ด ๋  ์ˆ˜ ์žˆ๋„๋ก useMemo์™€ useCallback ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜์กด์„ฑ ๋ฐฐ์—ด๋กœ ์–ด๋–ค ๊ฐ’์— ์˜ํ•ด ๋ฐ”๋€Œ๋Š” ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ์ฝœ๋ฐฑ์ธ [] ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ๊ฐ’์„ ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// useMemo
const avg = useMemo(() => getAverage(list), [list]); // list ๋ผ๋Š” ๊ฐ’์ด ๋ณ€๊ฒฐ๋  ๋•Œ'๋งŒ' getAverage ํ•จ์ˆ˜๋ฅผ ์žฌ ํ˜ธ์ถœํ•˜๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค

// useCallback
const onInsert = useCallback(
  (e) => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  },
  [number, list] // number ํ˜น์€ list๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋งŒ onInsert ํ•จ์ˆ˜ ์ƒ์„ฑ
);
// useMemo

<div>
  <b>ํ‰๊ท ๊ฐ’:</b> {avg}
</div>
// useCallback

<button onClick={onInsert}>๋“ฑ๋ก</button>

useCallback์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋‚˜์š”?

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

์ด์™€ ๋ฐ˜๋Œ€๋กœ useCallback์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒฝ์šฐ ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กญ๊ฒŒ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ์ดˆ๊ธฐํ™”(์„ ์–ธ, initialize) ๊ธฐ๋Šฅ๊ณผ ํ•จ๊ป˜ 'useCallback' ํ›… ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์—ฌ๋ถ€๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ • ์š”๊ตฌ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ์ด ๋น„๊ต์  ๊ฐ„๋‹จํ•˜๊ณ  ์žฌํ˜„ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค์ง€ ์•Š๋Š”๋‹ค๋ฉด 'useCallback'์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋” ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๊ฒฝ์šฐ์—๋Š” ์ด ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ 'useCallback'์„ ์‚ฌ์šฉํ•˜๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ธ์ œ useState ๋Œ€์‹  useRef๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‚˜์š”?

useRef๋Š” ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์žฌ๋ Œ๋”๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ๊ฐ’์„ ์ €์žฅํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

๋ฐ˜๋ฉด, useState๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋‹ค์‹œ ๋ Œ๋”๋ง์„ ํŠธ๋ฆฌ๊ฑฐํ•ด์•ผ ํ•˜๋Š” ๊ฐ’์„ ์ €์žฅํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ™”๋ฉด์— ์ผ๋ถ€ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ’์ด๋‚˜ ์–‘์‹ ์ž…๋ ฅ์˜ ํ˜„์žฌ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์˜ˆ์ž…๋‹ˆ๋‹ค.

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


๋ฆฌ์•กํŠธ์—์„œ setState๋Š” ๋น„๋™๊ธฐ ๋™์ž‘์ธ๊ฐ€์š” ๋™๊ธฐ ๋™์ž‘์ธ๊ฐ€์š”

์ฐธ๊ณ ์ž๋ฃŒ

function Example() {
  const [count, setCount] = React.useState(0);

  useEffect(()=>{
    console.log('in useEffect:', count)
  },[count])

  const onClickButton = () => {
    console.log("before", count);

    setCount(count + 1);
    // setCount(prev => prev+1);

    console.log("after", count);
  };

  return <button onClick={onClickButton}>{count}</button>;
}

>>>
/*
  before 0
  after 0
  in useEffect 1
*/

state ๊ฐ’์„ ๊ฐฑ์‹ ํ•˜๋Š” ํ•จ์ˆ˜์ธ setState ๋Š” ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ํ›… ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค

React๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ state, props ๊ฐ’์— ๋”ฐ๋ผ re-rendering์ด ์ผ์–ด๋‚˜์ฃ .

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ์— ํ•œ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์—ฌ๋Ÿฌ state ๊ฐ’์„ ์—ฐ์†์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์ผ์ด ์ƒ๊ธด๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ฒˆ ๋น„๊ตํ•˜๊ณ  ๋‹ค์‹œ ๊ทธ๋ฆฌ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

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

์ด์— ๋Œ€๋น„ํ•˜์—ฌ ๋ฆฌ์•กํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” state๋ฅผ ๋‹ค์‹œ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜์ธ setState๋ฅผ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ์ฒ˜๋ฆฌํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ๋‚ด์˜ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝœ๋ฐฑํ๊ฐ€ ๋‹ค ๋น„์›Œ์ง€๋ฉด ๋ฆฌ๋ Œ๋”๋งํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ๋ง์ธ ์ฆ‰, ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ ์‹คํ–‰๋œ ๋’ค์— ๋งˆ์ง€๋ง‰์— setState๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ์ด์•ผ๊ธฐ๊ฒ ์ฃ ?

const onClickButton = () => {
  console.log('before', count); // ----> ๋™๊ธฐํ•จ์ˆ˜

  setCount(count + 1); // ---->  ๋น„๋™๊ธฐํ•จ์ˆ˜

  console.log('after', count); // ---->  ๋™๊ธฐํ•จ์ˆ˜
};

setState๊ฐ€ ๋น„๋™๊ธฐ ๋™์ž‘์„ ์ทจํ–ˆ์„ ๋•Œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”

์•ž์„œ ๋งํ–ˆ์ง€๋งŒ, setState๊ฐ€ ๋น„๋™๊ธฐ ๋™์ž‘์„ ์ทจํ•จ์œผ๋กœ์จ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‚ด์˜ ์‹คํ–‰์ปจํ…์ŠคํŠธ ์Šคํƒ์ด ๋Œ์•„๊ฐˆ ๋•Œ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜๋“ค์„ ๋ชจ๋‘ ๋™์ž‘ํ•œ ๋’ค์— ํ์— ์กด์žฌํ•˜๋Š” ๋น„๋™๊ธฐ์ ์ธ ํ•จ์ˆ˜๋“ค์„ ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์˜ํ•ด ๊บผ๋‚ด์™€์„œ ์‹คํ–‰์‹œํ‚ต๋‹ˆ๋‹ค.

setState๊ฐ€ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค๋ฉด, ํ•œ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ํ•จ์ˆ˜์— ์˜ํ•ด state ๊ฐ’์ด ์—ฐ์†์ ์œผ๋กœ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ ๋ฆฌ์•กํŠธ์˜ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง ์กฐ๊ฑด์— ์˜ํ•ด ์ง€์†์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.


useLayoutEffect๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹  ์  ์žˆ๋‚˜์š”

์ฐธ๊ณ ์ž๋ฃŒ

๋ฆฌ์•กํŠธ ํ›… ํ•จ์ˆ˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค

hookflow

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

์œ„ ๊ทธ๋ฆผ์˜ ํ›… ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ๋ณด์‹œ๋‹ค์‹œํ”ผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์Šคํฌ๋ฆฐ์— ํŽ˜์ธํŒ… ์ž‘์—…์ด ์™„๋ฃŒ๋œ ์ดํ›„์— ์šฐ๋ฆฌ๋Š” useEffect ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์กŒ์—ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ Œ๋”๋งํ•  ๋•Œ useState(0)๊ณผ ๊ฐ™์€ ์ดˆ๊ธฐ useState์˜ ๊ฐ’์ด ๋นˆ ๊ฐ’์ด๋ผ๋ฉด, 0์„ ์ถœ๋ ฅํ–ˆ๋‹ค๊ฐ€ useEffect๋ฅผ ํ†ตํ•ด ๊ฐ’์ด ์ฑ„์›Œ์ง€๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์กŒ์—ˆ์Šต๋‹ˆ๋‹ค.

// ์ฝ”๋“œ ์ฐธ๊ณ : https://merrily-code.tistory.com/46

import { useEffect, useState } from 'react';

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState('');

  useEffect(() => {
    setAge(25);
    setName('์ฐฌ๋ฏผ');
  }, []);

  return (
    <>
      <div className='App'>{`๊ทธ์˜ ์ด๋ฆ„์€ ${name} ์ด๋ฉฐ, ๋‚˜์ด๋Š” ${age}์‚ด ์ž…๋‹ˆ๋‹ค.`}</div>
    </>
  );
}

export default App;

useEffect

useLayoutEffect ํ›…์€ ๋ฐ”๋กœ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ํ›…์ž…๋‹ˆ๋‹ค.

useLayoutEffect๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์— DOM์„ ๊ทธ๋ฆฌ๊ธฐ ์ „์— ์ดํŽ™ํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค .

๋”ฐ๋ผ์„œ ์œ„ ์ฝ”๋“œ์˜ ์‹คํ–‰ ์ˆœ์„œ๋„ ๋‹ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  1. ๋ ˆ์ด์•„์›ƒ ์ดํŽ™ํŠธ ๋‚ด๋ถ€์˜ setNumber, setName ํ˜ธ์ถœ

  2. <div>๊ทธ์˜ ์ด๋ฆ„์€ ์ฐฌ๋ฏผ์ด๋ฉฐ, ๋‚˜์ด๋Š” 25์‚ด ์ž…๋‹ˆ๋‹ค.</div> ๋ฅผ ํŽ˜์ธํŠธ

// ์ฝ”๋“œ ์ฐธ๊ณ : https://merrily-code.tistory.com/46

import { useLayoutEffect, useState } from 'react';

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState('');

  useLayoutEffect(() => {
    setAge(25);
    setName('์ฐฌ๋ฏผ');
  }, []);

  return (
    <>
      <div className='App'>{`๊ทธ์˜ ์ด๋ฆ„์€ ${name} ์ด๋ฉฐ, ๋‚˜์ด๋Š” ${age}์‚ด ์ž…๋‹ˆ๋‹ค.`}</div>
    </>
  );
}

export default App;

useLayoutEffect


๋ฆฌ์•กํŠธ์˜ ์„ฑ๋Šฅ๊ฐœ์„  ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”

์ œ๊ฐ€ ์‚ฌ์šฉํ•ด ๋ณธ ์„ฑ๋Šฅ ๊ฐœ์„  ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • hook ํ•จ์ˆ˜ ์‚ฌ์šฉ (useMemo, useCallback)
  • ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… (react.lazy(), Next.js ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ ๋“ฑ)

์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ธ๋“ค๋งํ•ด์•ผ ํ•˜๋‚˜์š”

์ด๋ฒคํŠธ๋กœ ์„ค์ •ํ•  ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์ง์ ‘ ๋„ฃ์–ด ์ค„ ๋•Œ๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋„ฃ์–ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

case 1: ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ๋ฒ•
<button onClick={this.setState({ number: number + 1})}>  (x)

case 2: ์ž‘๋™ํ•˜๋Š” ๋ฌธ๋ฒ•
<button onClick={()=> this.setState({ number: number + 1}; )}>  (o)

or
case 3: ์•„์˜ˆ ํ•จ์ˆ˜๋กœ ๋นผ์ฃผ๊ณ  ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ ์‚ฌ์šฉํ•œ๋‹ค.

const plusNum = (number) => {
  setState(number : number + 1);
}
...

<button onClick={plusNum}>+ 1 </button>

SPA๊ฐ€ ๋ญ”๊ฐ€์š”

SPA๋Š” Single Page Application(์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์˜ ์•ฝ์–ด์ž…๋‹ˆ๋‹ค. ๋ง ๊ทธ๋Œ€๋กœ ํ•œ ๊ฐœ์˜ ํŽ˜์ด์ง€๋กœ ์ด๋ฃจ์–ด์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์ „ํ†ต์ ์ธ ์›น ํŽ˜์ด์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

MPA

๊ธฐ์กด์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด html์„ ๋ฐ›์•„ ์˜ค๊ณ , ํŽ˜์ด์ง€๋ฅผ ๋กœ๋”ฉํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ํ•ด์„ํ•œ ๋’ค ํ™”๋ฉด์— ๋ณด์—ฌ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์ด๋Š” ํ™”๋ฉด์€ ์„œ๋ฒ„ ์ธก์—์„œ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์ „์— html ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ์œ ๋™์ ์ธ html์„ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ–ˆ์ฃ .

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

SPA

์‚ฌ์šฉ์ž์™€์˜ ์ธํ„ฐ๋ ‰์…˜์ด ๋ฐœ์ƒํ•˜๋ฉด ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—…๋ฐ์ดํŠธ (JSON ํ˜•์‹์œผ๋กœ ์š”์ฒญํ•จ)

SPAVSMPA

[์ถœ์ฒ˜ : https://babytiger.netlify.app/posts/SPA/]

์‹ฑ๊ธ€ ํŽ˜์ด์ง€๋ผ๊ณ  ํ•ด์„œ ํ™”๋ฉด์ด ํ•œ ์ข…๋ฅ˜์ธ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. SPA์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ํŽ˜์ด์ง€๋Š” ํ•œ ์ข…๋ฅ˜์ด์ง€๋งŒ, ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ ๋กœ๋”ฉ๋œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ํ˜„์žฌ ์‚ฌ์šฉ์ž ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ํ™”๋ฉด์„ ๋ณด์—ฌ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์ฃผ์†Œ์— ๋‹ค๋ฅธ ํ™”๋ฉด์„ ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์„ ๋ผ์šฐํŒ…์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž์ฒด์— ์ด ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ๋ธŒ๋ผ์šฐ์ €์˜ API๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๊ฑฐ๋‚˜, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์ž‘์—…์„ ๋”์šฑ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ(react-router), ๋ฆฌ์น˜ ๋ผ์šฐํ„ฐ(reach-router), Next.js ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฆฌ์•กํŠธ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ๋ผ์šฐํŒ…์„ ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด ์ค๋‹ˆ๋‹ค. ๋” ๋‚˜์•„๊ฐ€ ๋‚˜์ค‘์— ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ํ•  ๋•Œ๋„ ๋ผ์šฐํŒ…์„ ๋„์™€์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ œ๊ณตํ•ด ์ค๋‹ˆ๋‹ค.


SPA์˜ ๋‹จ์ 

SPA์˜ ๋‹จ์ ์€ ์•ฑ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์ด ๋„ˆ๋ฌด ์ปค์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋Š” ํŽ˜์ด์ง€์˜ ์Šคํฌ๋ฆฝํŠธ๋„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์ด์ฃ . ํ•˜์ง€๋งŒ ํ›„์— ๋ฐฐ์šธ ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…(code splitting)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์šฐํŠธ๋ณ„๋กœ ํŒŒ์ผ๋“ค์„ ๋‚˜๋ˆ„์–ด์„œ ํŠธ๋ž˜ํ”ฝ๊ณผ ๋กœ๋”ฉ ์†๋„๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ผ์šฐํŒ…์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š” ์ผ๋ฐ˜ ํฌ๋กค๋Ÿฌ์—์„œ๋Š” ํŽ˜์ด์ง€์˜ ์ •๋ณด๋ฅผ ์ œ๋Œ€๋กœ ์ˆ˜์ง‘ํ•ด ๊ฐ€์ง€ ๋ชปํ•œ๋‹ค๋Š” ์ž ์žฌ์ ์ธ ๋‹จ์ ์ด ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌ๊ธ€, ๋„ค์ด๋ฒ„, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒ€์ƒ‰ ์—”์ง„์˜ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— ํŽ˜์ด์ง€๊ฐ€ ์ž˜ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๊นŒ์ง€ ํŽ˜์ด์ง€๊ฐ€ ๋น„์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์ด ๋กœ๋”ฉ๋˜์–ด ์‹คํ–‰๋˜๋Š” ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ ํฐ ํŽ˜์ด์ง€๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฌธ์ œ์ ๋“ค์€ ๋‹คํ–‰ํžˆ ๋‚˜์ค‘์— ๋ฐฐ์šฐ๊ฒŒ ๋  ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(server-side-rendering)์„ ํ†ตํ•ด ๋ชจ๋‘ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


SSR์ด ๋ญ”๊ฐ€์š”

๋ฆฌ์•กํŠธ๋Š” ๋Œ€ํ‘œ์ ์ธ CSR(client side rendering)์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฆฌ์•กํŠธ์˜ CSR์ ์ธ ๋ถ€๋ถ„์—์„œ SSR ์ ์œผ๋กœ ๋ฐ”๊ฟ” ์ฃผ๊ธฐ ์œ„ํ•ด์„œ next.js์™€ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

SSR์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ ๋Š” ํšจ์œจ์ ์ธ SEO๋ฅผ ์œ„ํ•ด์„œ ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ฌธ๋‹จ์—์„œ ๋‹ค๋ฃจ๊ฒ ์ง€๋งŒ, SEO๋Š” google, naver์™€ ๊ฐ™์€ ๊ฒ€์ƒ‰ ์—”์ง„๋“ค์ด ์šฐ๋ฆฌ์˜ ์›น์‚ฌ์ดํŠธ์—์„œ html ํƒœ๊ทธ์•ˆ์˜ ๋‚ด์šฉ์„(title, meta-data ๋“ฑ๋“ฑ,,,) ๋ถ„์„ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์•Œ๋งž์€(์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š”) ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” CSR์œผ๋กœ ์ž‘๋™๋˜๋Š”๋ฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์šฐ๋ฆฌ์˜ ํ•ด๋‹น ๋„๋ฉ”์ธ์— ์ ‘์†ํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„(์‚ฌ์šฉ์ž์˜ ์ปดํ“จํ„ฐ)๊ฐ€ html๊ณผ js ๋“ฑ์˜ ํŒŒ์ผ์„ ๋‹ค์šด๋ฐ›์•„ ๋ณด์—ฌ์ฃผ๋Š” ํ˜•์‹์ž…๋‹ˆ๋‹ค. CSR ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์ „์— html์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฒ€์ƒ‰ ์—”์ง„์— ๋…ธ์ถœ๋˜๋Š” ๋นˆ๋„๊ฐ€ ํ˜„์ €ํžˆ ์ ๊ฑฐ๋‚˜, ๋ธŒ๋ผ์šฐ์ €์— ๋”ฐ๋ผ ๊ฒ€์ƒ‰ ์—”์ง„์— ํ•ด๋‹น ์ •๋ณด๊ฐ€ ๋…ธ์ถœ๋˜์ง€ ์•Š์•„ ๊ฒ€์ƒ‰์„ ํ•ด๋„ ๋‚˜์˜ค์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(๋„๋ฉ”์ธ์„ ํ†ตํ•ด ์ ‘์†ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•ด์ง€๋Š” ์ •๋„, ํ•ด๋‹น ์‚ฌ์ดํŠธ์— ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ ์—”์ง„์ด ํฌ๋กค๋งํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Œ)๊ทธ๋ž˜์„œ SSR์„ ํ†ตํ•ด ์„œ๋ฒ„๊ฐ€ ์‚ฌ์ „์— html๊ณผ ์ผ๋ถ€ js ํŒŒ์ผ์„ ๋„˜๊ฒจ์ฃผ๊ฒŒ ๋˜๋ฉด, ๊ฒ€์ƒ‰ ์—”์ง„์—์„œ ์ด๋ฅผ ์บ์น˜ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ์šฐ๋ฆฌ ์‚ฌ์ดํŠธ๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


SEO๊ฐ€ ๋ญ”๊ฐ€์š”

SEO๋ž€, Search Engine Optimization์˜ ์•ฝ์ž๋กœ, SEO๋Š” ๊ตฌ๊ธ€, ๋„ค์ด๋ฒ„์™€ ๊ฐ™์€ ๊ฒ€์ƒ‰ ์—”์ง„๋“ค์ด ์„œ๋ฒ„์— ๋“ฑ๋ก๋œ ์›น์‚ฌ์ดํŠธ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜์”ฉ ๋Œ์•„ ๋‹ค๋‹ˆ๋ฉด์„œ ์›น์‚ฌ์ดํŠธ์˜ HTML ๋ฌธ์„œ๋ฅผ ๋ถ„์„ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋•Œ HTML์— ์‚ฌ์šฉ๋œ ํƒœ๊ทธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒ€์ƒ‰ํ•  ๋•Œ, ์›น์‚ฌ์ดํŠธ๋ฅผ ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, CSR์—์„œ ์‚ฌ์šฉ๋˜๊ณ ์žˆ๋Š” HTML์˜ body๋Š” ํ……ํ…… ๋น„์–ด ์žˆ๋‹ค๊ฐ€(div id="root"์˜ ๋ฆฌ์•กํŠธ ํŠน์„ฑ), ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ๋„๋ฉ”์ธ์„ ๊ฐ€์ง„ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„์—์„œ js ๋ฐ‘ html ํƒœ๊ทธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ˜•์‹์ด๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์ „์— html ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฒ€์ƒ‰ ์—”์ง„์ด ํ•ด๋‹น ๋„๋ฉ”์ธ์— ์ ‘๊ทผํ•  ๋•Œ ์–ด๋ ค์›€์ด ์žˆ์Šต๋‹ˆ๋‹ค. (์šฐ๋ฆฌ ์‚ฌ์ดํŠธ๋ฅผ ๊ฒ€์ƒ‰ ์—”์ง„์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ์œ ์ž…๋˜๋Š” ๊ฒƒ์ด ํž˜๋“ค๋‹ค why? ๊ฒ€์ƒ‰ ์—”์ง„์ด ์šฐ๋ฆฌ html ํŒŒ์ผ์„ ๋ถ„์„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— why? CSR ํ˜•์‹์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผํ•ด์•ผ html, js ๋“ฑ์˜ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์—) ๋”ฐ๋ผ์„œ, ๊ฒ€์ƒ‰ ์—”์ง„์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜์—ฌ ์–ป๊ณ ์žํ•˜๋Š” ์ •๋ณด๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ, ๊ฒ€์ƒ‰ ์—”์ง„์ด ์šฐ๋ฆฌ์˜ ์›น ์‚ฌ์ดํŠธ์—์„œ ํ•ด๋‹น ๋‚ด์šฉ์„ ์บ์น˜ํ•˜๋Š”๋ฐ ์–ด๋ ค์›€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” SEO ์ฆ‰, ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”๋ฅผ ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด, SSR์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ „์— html ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ ์—”์ง„์ด ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜์—ฌ SEO๋ฅผ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. SSR์€ ์„œ๋ฒ„์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์‚ฌ์ „์— html ํŒŒ์ผ์„ ๋งŒ๋“ค๊ฒŒ ๋˜๊ณ  ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ HTML ํŒŒ์ผ์„ ์ผ๋ถ€ ์ดˆ๊ธฐ ์„ธํŒ…์— ํ•„์š”ํ•œ js์™€ ํ•จ๊ป˜ ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„์— ๋ณด๋‚ด์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” ์„œ๋ฒ„์—์„œ ๋งŒ๋“ค์–ด์ค€ ๋ฌธ์„œ๋ฅผ ๋ฐ›์•„ ์™€์„œ ๋ฐ”๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ . ์ด๋ ‡๊ฒŒ SSR์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์‚ฌ์ „์— HTML ๋ฌธ์„œ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ธก์œผ๋กœ ์ „๋‹ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํŽ˜์ด์ง€ ๋กœ๋”ฉ์ด ๋นจ๋ผ์ง€๊ณ , ๊ฒ€์ƒ‰ ์—”์ง„์ด ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ๋”ฐ๋ผ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ฐพ์„ ๋•Œ(๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•  ๋•Œ), ์šฐ๋ฆฌ์˜ ์›น์‚ฌ์ดํŠธ์— ํ•ด๋‹น ๊ฒ€์ƒ‰์–ด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด ์šฐ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํšจ์œจ์ ์ธ SEO๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ SSR์ด CSR์˜ ๋ชจ๋“  ๋ฌธ์ œ์ ์— ํ•ด๊ฒฐ์ฑ…์ด ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์ „์— ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ๋ฒˆ์งธ๋กœ blinking issue๊ฐ€ ์—ฌ์ „ํžˆ ์กด์žฌํ•˜๊ณ (ํŽ˜์ด์ง€๊ฐ€ ๋„˜์–ด๊ฐˆ ๋•Œ๋งˆ๋‹ค ๊นœ๋นก์ž„ why? html ๋ฐ js ํŒŒ์ผ์„ ์ƒˆ๋กœ ๋ฐ›์•„์˜ค๊ธฐ ๋•Œ๋ฌธ์—), ๋‘ ๋ฒˆ์งธ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ ์„œ๋ฒ„๋Š” ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ์˜ํ•ด ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์„œ HTML์„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋ฏ€๋กœ ๊ณผ๋ถ€ํ™”๊ฐ€ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋น ๋ฅด๊ฒŒ ์›น์‚ฌ์ดํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, SSR์‹œ ๋ชจ๋“  jsํŒŒ์ผ์„ ๋‹ค์šด ๋ฐ›์€ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—, jsํŒŒ์ผ์ด ์™„์ „ํžˆ ๋‹ค์šด๋กœ๋“œ ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ํŽ˜์ด์ง€์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์„ ํด๋ฆญํ•˜๋ฉด, ์ž‘๋™์ด ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TTV TTI

TTV๋Š” ๋ณด์—ฌ์ง€๋Š” ์‹œ์  (Time To View), TTI๋Š” ์ธํ„ฐ๋ ‰์…˜ ์‚ฌ์šฉ์ž์™€์˜ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•ด์ง€๋Š” ์‹œ์  (Time To Interact)์ž…๋‹ˆ๋‹ค

CSR์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง๊ณผ ๋™์‹œ์— ๋ชจ๋“  html๊ณผ js๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์—, TTV๊ณผ ๋จ๊ณผ ๋™์‹œ์— TTI ๋ชจ๋“  ๋™์ ์ธ ํ–‰๋™์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, SSR์€ html๊ณผ ์ผ๋ถ€ jsํŒŒ์ผ์€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‚ฌ์ „์— ๋ฐ›์•„ ๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์— TTV ์ƒํƒœ์—์„œ๋„ TTI๊ฐ€ ์ „๋ถ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค

์ตœ์ข…์ ์œผ๋กœ CSR์„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ์ตœ์ข…์ ์œผ๋กœ ๋ฒˆ๋“ค๋งํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฒŒ์— ๋ณด๋‚ด์ฃผ๋Š” js ํŒŒ์ผ์„ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ํšจ์œจ์ ์œผ๋กœ ๋งŽ์ด ๋ถ„ํ• ํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ธฐ ์œ„ํ•ด์„œ ํ•„์š”ํ•œ ์ •๋ง ํ•„์ˆ˜์ ์ธ html ์š”์†Œ๋งŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์„์ง€ ๊ณ ๋ฏผํ•ด๋ด์•ผ ํ•˜๊ณ , SSR์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ณ , ์ธํ„ฐ๋ ‰์…˜(TTI)ํ•˜๋Š” ์ด ์‹œ๊ฐ„์˜ ๋‹จ์ฐจ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ ์–ด๋–ค ๋…ธ๋ ฅ์„ ํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ณ ๋ฏผํ•ด๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์กฐ๊ธˆ ๋” ๋งค๋„๋Ÿฌ์šด UI์™€ UX๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์„์ง€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ๋“ค์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์š”์ฆ˜์—๋Š” SSR, CSR ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ SSG(Static Site Generation)๋˜ํ•œ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•์œผ๋กœ ๋“ฑ์žฅํ•˜์˜€์Šต๋‹ˆ๋‹ค. SSG๋Š” ๋ฆฌ์•กํŠธ๋ฅผ ์˜ˆ๋กœ ๋“ค๋ฉด 'Gatsby' ๋˜๋Š” 'Next'์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋ง์„ ํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์›นํŽ˜์ด์ง€๋ฅผ ์ •์ ์œผ๋กœ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด๋‘๊ณ , ์„œ๋ฒ„์— ๋ฐฐํฌํ•ด๋†“๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. SSG์—์„œ๋„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ html ํŒŒ์ผ๊ณผ ํ•จ๊ป˜ ๊ฐ€์ง€๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋™์ ์ธ ์š”์†Œ๋„ ์ถฉ๋ถ„ํžˆ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Next์—์„œ๋Š” SSR๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, static generation, no pre-rendering, pre-rendering์ƒํƒœ๋ฅผ ๋ชจ๋‘ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ๋กœ ์ž‘์—…์„ ๊ณ„์†ํ•œ๋‹ค๋ฉด next.js๋ฅผ ๋ฐฐ์›Œ๋ณด๋Š” ๊ฒƒ๋„ ๋งค์šฐ ํšจ๊ณผ์ ์ผ ๊ฒ๋‹ˆ๋‹ค.

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

์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๋ฆฌ์•กํŠธ API๋ฅผ ์•Œ๊ณ  ์žˆ๋‚˜์š” ?

renderToString

  • ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜์—ฌ ์ •์  HTML ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • SSR ์‹œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” API์ž…๋‹ˆ๋‹ค.

renderToStaticMarkup

  • renderToString๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ์ผ๋ถ€ ๋ฐ์ดํ„ฐ ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ •์  ํŽ˜์ด์ง€ ์ƒ์„ฑ ์‹œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

renderToNodeStream > renderToPipeableStream

  • ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜์—ฌ Node.js ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋Œ€์šฉ๋Ÿ‰ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜๊ฑฐ๋‚˜ ํ”„๋ก์‹œ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • React 18 ๋ฒ„์ „์—์„œ renderToPipeableStream ์œผ๋กœ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

renderToStaticNodeStream

  • renderToNodeStream๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ •์  ํŽ˜์ด์ง€ ์ƒ์„ฑ ์‹œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ Œ๋”๋ง์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

hydrate

  • ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ HTML ์ฝ”๋“œ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ธ์‹ํ•˜๊ณ  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋งˆํฌ์—…์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฐ๊ฒฐํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฏธ ๋ Œ๋”๋ง๋œ HTML์ด ์žˆ๋‹ค๋Š” ๊ฐ€์ •ํ•˜์— ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค
  • renderToString, renderToNodeStream ๋“ฑ์œผ๋กœ ์ƒ์„ฑ๋œ HTML ์ปจํ…์ธ ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ•ธ๋“ค๋Ÿฌ๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ๋ถ™์ด๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค

ํ•˜์ด๋“œ๋ ˆ์ด์…˜์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ๋‚˜์š”

์ฐธ๊ณ  ์ž๋ฃŒ 1 ๐Ÿ”ฅ ์ฐธ๊ณ  ์ž๋ฃŒ 2 ๐Ÿ”ฅ

hydration = ์ˆ˜ํ™” = ์šฐ๋ฆฌ ๋ชธ์— ์ˆ˜๋ถ„์„ ๋ณด์ถฉํ•˜๋Š” ํ–‰์œ„

ํ•˜์ด๋“œ๋ ˆ์ด์…˜์ด๋ž€, ๋ฆฌ์•กํŠธ์—์„œ ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ํ˜น์€ SSG(์Šคํƒœํ‹ฑ ์‚ฌ์ดํŠธ ์ œ๋„ค๋ ˆ์ด์…˜)์„ ์‹คํ–‰ํ•œ HTML ๊ฒฐ๊ณผ๋ฌผ์„ ๋ฐ›์•„์˜จ ๋’ค, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ด๊ฒƒ์„ ๋‹ค์‹œ ๋ฆฌ์•กํŠธ ํŠธ๋ฆฌ์— ๋งž๊ฒŒ ํŒŒ์‹ฑํ•˜๋Š” ํ–‰์œ„์ด๋‹ค.

hydration

์ถœ์ฒ˜ (https://simsimjae.tistory.com/389)

์„œ๋ฒ„๊ฐ€ ์™„์„ฑ๋œ HTML์„ ๋‚ด๋ ค์ค€๋‹ค. ์ด๋•Œ Dehydrate๋Š” ์ˆ˜๋ถ„์„ ์—†์•ค๋‹ค๋Š” ๋œป์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ ๋™์ ์ธ๊ฒƒ์„ ์ •์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ํ–‰์œ„๋ฅผ Dehydrate๋ผ๊ณ  ํ‘œํ˜„ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ JS๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ๋ฆฌ์•กํŠธ๊ฐ€ ์ •์ ์ธ HTML๊ณผ store๋ฅผ ๋™์ ์ธ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์™€ store๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ์ผ์–ด๋‚˜๋Š”๋ฐ, ์ด๊ฑธ (Re)hydrate๋ผ๊ณ  ํ•œ๋‹ค. ๋งˆ์น˜ ์ˆ˜๋ถ„๊ธฐ ์—†๋Š” ์ •์ ์ธ ์ƒํƒœ์—์„œ ์ˆ˜๋ถ„ ๋„˜์น˜๋Š” ๋™์ ์ธ ์ƒํƒœ๋กœ ๋ณ€ํ™”ํ•œ๊ฒƒ์ด๋‹ค. ๋ฌธ์ œ๋Š” ์ด๋ ‡๊ฒŒ rehydrate๊ฐ€ ์ผ์–ด๋‚˜๋ฉด์„œ ์“ธ๋ฐ์—†์ด ํ™”๋ฉด์ด ํ•œ๋ฒˆ๋” ๊ทธ๋ ค์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•œ๋‹ค๋Š”๊ฒƒ์ด๋‹ค. ์™œ๋ƒ๋ฉด ๋ฆฌ์•กํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์™„์„ฑ๋œ HTML์ด ๋‚ด๋ ค์™€์„œ ์ด๋ฏธ ํ™”๋ฉด์— ์ œ๋Œ€๋กœ ๋ Œ๋”๋ง์ด ๋ฌ๋Š”์ง€ ์•ˆ๋ฌ๋Š”์ง€ ๋ชจ๋ฅด๊ณ  ์ž์‹ ์ด ํ• ์ผ์„ ๊ทธ๋ƒฅ ํ–ˆ์„ ๋ฟ์ด๋‹ค. ๊ทธ๋ž˜์„œ SSR์„ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ReactDom์˜ render๋ฉ”์†Œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ hydrate ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋งํ–ˆ์—ˆ๋‹ค.

์ด hydrate ๋‹จ๊ณ„์—์„œ,

  • ๋ Œ๋”๋งํ•œ ๊ฒฐ๊ณผ๋ฌผ์ด ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์ธ์ง€ ํ™•์ธํ•œ๋‹ค
  • ๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๊ฑธ๋ฆฐ ์ด๋ฒคํŠธ ๋“ค์„ ์‹ค์ œ DOM์— ๊ฑธ์–ด์ฃผ๋Š” ๋™์ž‘์„ ํ•˜๊ฒŒ ๋œ๋‹ค

ํ•˜์ด๋“œ๋ ˆ์ด์…˜์ด ์ž˜๋ชป๋˜์—ˆ์„ ๋•Œ, ์šฐ๋ฆฌ๊ฐ€ ๋งˆ์ฃผํ•˜๋Š” ๋ฌธ์ œ๋“ค์€ ๊ฑฐ์˜ 1๋ฒˆ ๊ณผ์ •์ด ์ž˜๋ชป๋˜์–ด์„œ ์ผ์–ด๋‚œ๋‹ค.

Next.JS์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ReactDOM.hydrate ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•œ๋‹ค.

  • ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ DOM tree์™€ ์ž์ฒด์ ์œผ๋กœ ๋ Œ๋”๋งํ•œ tree๋ฅผ ๋น„๊ตํ•œ๋‹ค
  • ๋‘ tree ์‚ฌ์ด์˜ ์ฐจ์ด(diff, diffrence)๋ฅผ ์–ป์–ด๋‚ธ ๋’ค, ์ž์ฒด์ ์œผ๋กœ(ํด๋ผ์ด์–ธํŠธ์‚ฌ์ด๋“œ) ๋ Œ๋”๋ง ํ•œ tree์— ๋งž์ถฐ patch๋ฅผ ์ ์šฉํ•œ๋‹ค

hydration์ด ๋˜์–ด์•ผ ์ง„์งœ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ

์„œ๋ฒ„์—์„œ ๋‚ด๋ ค์ค€ HTML๋กœ ๋ Œ๋”๋ง ๋œ ํ™”๋ฉด์€ ๊ทธ๋ƒฅ ๋‹จ์ˆœํžˆ ๊ทธ๋ฆผ์ผ ๋ฟ์ด๋‹ค. ๋ฆฌ์•กํŠธ๊ฐ€ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ํ™”๋ฉด์ด๋‹ค. SSR์„ ํ•˜๋”๋ผ๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ์•กํŠธ๊ฐ€ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” hydration์€ ๊ผญ ํ•„์š”ํ•œ ์ž‘์—…์ด๋‹ค.

๊ฒฐ๋ก 

๋ฆฌ์•กํŠธ์—์„œ hydration์ด๋ผ๊ณ  ํ•˜๋Š” ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” "์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ˆ˜๋ถ„์ด ์—†๋Š” ์ •์ ์ธ HTML๊ณผ State๋กœ๋ถ€ํ„ฐ ์ˆ˜๋ถ„์„ ๋ณด์ถฉํ•˜๋Š” ๊ณผ์ •(๋™์ ์ธ ์ƒํƒœ๋กœ ๋ณ€ํ™”)์ธ hydrate๊ฐ€ ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ" ์ด๋ผ๊ณ  ์ถ”์ธกํ•ด๋ณธ๋‹ค.


Next์˜ ๋ Œ๋”๋ง ์ˆ˜ํ–‰ ๋ฐฉ์‹

์ฐธ๊ณ  ์ž๋ฃŒ: Velog, Next.js 100% ํ™œ์šฉํ•˜๊ธฐ

  1. SSR์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์„œ๋ฒ„์— ์‚ฌ์ „์— ์ €์žฅ๋œ ๋ Œ๋”ํŠธ๋ฆฌ(render tree)์˜ HTML์„ ๋กœ๋“œ
  2. โ‘  ๋ฐฉ์‹์˜ ์‚ฌ์ „ ๋ Œ๋”๋ง(pre-render) ์ดํ›„์—๋Š” CSR ์‚ฌ์šฉ
  3. ํŽ˜์ด์ง€๊ฐ€ ๊ทธ๋ ค์ง„ ์ดํ›„์— ํŽ˜์ด์ง€ ๋‚ด๋ถ€์—์„œ ๋™์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์น˜(axios, fetch, XMLHttpRequest)ํ•˜๋Š” ๊ณผ์ •์€ CSR ๋ฐฉ์‹์„ ๋”ฐ๋ฅธ๋‹ค.
  4. ๋งŒ์•ฝ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋  ๋•Œ ํ•จ๊ฒŒ ๋ฐ์ดํ„ฐ๊ฐ€ ํŒจ์นญ๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด(pre-render)
  5. next.js์˜ ๋ฐ์ดํ„ฐ ํŒจ์นญ ๋ฐฉ์‹ (โ‘  getInitialProps/ โ‘ก getStaticProps / โ‘ข getStaticPath / โ‘ฃ getServerSideProps) ์„ ์ด์šฉํ•ด ์ฒซ ๋ Œ๋”๋ง ์‹œ์— HTML ํŒŒ์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ๊ฐ€ ํŒจ์นญ๋  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Next๋ฅผ ์“ด ์ด์œ ๊ฐ€ ์žˆ๋‚˜์š”

์ถœ์ฒ˜: ํด๋ก  ์ฝ”๋”ฉ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” Next.js

1. ์‚ฌ์ „ ๋ Œ๋”๋ง ๋ฐ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง

  • ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ํ™˜๊ฒฝ๋ณด๋‹ค ๋น ๋ฅธ ๋ Œ๋”๋ง์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. Hot Code Reloading์„ ์ง€์›

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

3. ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ• 

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

4. ์„ค์ •์ด ํ•„์š”์—†์Œ

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

  • ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ๋‹ค๋ฉด ์†์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

5. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋‚ด์žฅ๋จ

6. ํŒŒ์ผ๊ธฐ๋ฐ˜ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ

  • ๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ผ์šฐํŠธ๋ฅผ ์œ„ํ•ด์„œ 'react-router'๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ผ์šฐํŒ… ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ทธ๋กœ ์ธํ•ด ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ์— ๋Œ€ํ•˜์—ฌ ์ง์ ‘ ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  • ํ•˜์ง€๋งŒ ๋„ฅ์ŠคํŠธ๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ํด๋”์˜ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ๊ฐ€ ์„ค์ •๋˜์–ด ๊ตฌ์ถ•์ด ๋น ๋ฅด๊ณ  ๊ด€๋ฆฌ๊ฐ€ ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.


Next๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ์„ค์ • ํŒŒ์ผ์— ๋Œ€ํ•ด์„œ ์•Œ๊ณ  ์žˆ๋‚˜์š”

๐Ÿ“ pages ํด๋” ์•ˆ์—๋Š” ๋„ฅ์ŠคํŠธ์—์„œ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๋Š” ํŠน๋ณ„ํ•œ ํŒŒ์ผ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๐Ÿ“™_app.jsx (tsx)
  • ๐Ÿ“™_document.jsx (tsx)
  • ๐Ÿ“™_error.jsx (tsx)
  • ๐Ÿ“™404.jsx (tsx)

๐Ÿ“™_app.jsx

App ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€์˜ ๊ณตํ†ต ํŽ˜์ด์ง€ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

App ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ชจ๋“  ํŽ˜์ด์ง€๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํŽ˜์ด์ง€๋“ค์˜ ๊ณตํ†ต๋œ ๋ ˆ์ด์•„์›ƒ
  • ํŽ˜์ด์ง€๋ฅผ ํƒ์ƒ‰ํ•  ๋•Œ ์ƒํƒœ ์œ ์ง€
  • ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์ด์ง€์— ์ฃผ์ž…
  • ๊ธ€๋กœ๋ฒŒ CSS ์ถ”๊ฐ€
๐Ÿ“ pages/_app.jsx

import Header from '../components/Header';

const MyApp = ({ Component, pageProps }) => {
  return (
    <>
      <Header />
      <Component {...pageProps} />
      <style jsx global>
        {`
          body {
            margin: 0;
          }
        `}
      </style>
    </>
  );
};

export default MyApp;

๐Ÿ“™_document.jsx

์‚ฌ์šฉ์ž ์ •์˜ Document๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ <HTML> ๋ฐ <body> ํƒœ๊ทธ๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋„ํ๋จผํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ <title>, <description>, <meta> ๋“ฑ ํ”„๋กœ์ ํŠธ์˜ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” HTML ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ณ ,

ํฐํŠธ๋‚˜ ์™ธ๋ถ€ api, cdn ๋“ฑ์„ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ CSS-in-JS์˜ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ์œ„ํ•œ ์„ค์ •์„ ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Head ํƒœ๊ทธ์— meta ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ตฌ๊ธ€ ํฐํŠธ ๋“ฑ์—์„œ ์ œ๊ณตํ•˜๋Š” ํฐํŠธ๋ฅผ link ๋กœ ๋ถˆ๋Ÿฌ์™€ ์ „์—ญ์œผ๋กœ ์ ์šฉ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ pages/_document.jsx

import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html lang="ko">
        <Head>
          <meta name="title" content="๊นƒํ—ˆ๋ธŒ ๋ ˆํฌ์ง€ํ† ๋ฆฌ" />
          <meta name="description" content="๊นƒํ—ˆ๋ธŒ ๋ ˆํผ์ง€ํ† ๋ฆฌ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค" />
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&display=swap"
            rel="stylesheet"
          />
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,700&display=swap&subset=korean"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

๐Ÿ“™_error.jsx

๋„ฅ์ŠคํŠธ์—์„œ๋Š” ๋นŒ๋“œ ๋œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋กœ ๋ผ์šฐํŒ… ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋นŒ๋“œ ๋œ ํ”„๋กœ๋•ํŠธ ํ™˜๊ฒฝ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ž๋™์ ์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ ์—๋Ÿฌ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ 500, 404 ๋“ฑ๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๐Ÿ“ pages/_error.jsx

const Error = () => {
  return (
    <div>
      <p>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค</p>
    </div>
  );
};

export default Error;

์‚ฌ์ „ ๋ Œ๋”๋ง์„ ์œ„ํ•ด ์‚ฌ์šฉํ•ด ๋ณธ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‚˜์š”

์ฐธ๊ณ ์ž๋ฃŒ

  • getInitialProps
  • getStaticProps
  • getStaticPath
  • getServerSideProps

getInitialProps

Next 9.3 ๋ฒ„์ „ ์ด์ „์—” getInitialProps๋งŒ์œผ๋กœ ์‚ฌ์ „ ๋ Œ๋”๋ง ๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ์ „๋ถ€ ํ•ด๊ฒฐํ–ˆ์ง€๋งŒ, 9.3๋ฒ„์ „๋ถ€ํ„ฐ๋Š” getInitialProps๊ฐ€ 3๊ฐ€์ง€๋กœ ๋ถ„๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

  • getStaticProps
  • getStaticPath
  • getServerSideProps

getStaticProps

  • ๋นŒ๋“œ์‹œ ๊ณ ์ •๋˜๋Š” ๊ฐ’์œผ๋กœ ๋นŒ๋“œ ์ดํ›„์—๋Š” ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
  • data๋ฅผ ๋นŒ๋“œ ์‹œ์— ๋ฏธ๋ฆฌ ๋•ก๊ฒจ์™€ ์ •์ ์œผ๋กœ(static ํ•˜๊ฒŒ) ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค
  • ๋งค ์œ ์ €์˜ ์š”์ฒญ๋งˆ๋‹ค fetchํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง„ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค
  • ์œ ์ €์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๊ณ  ํผ๋ธ”๋ฆญํ•˜๊ฒŒ ์บ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ
  • SEO ๋“ฑ์˜ ์ด์Šˆ๋กœ ์ธํ•ด ๋น ๋ฅด๊ฒŒ ๋ฏธ๋ฆฌ ๋ Œ๋”๋งํ•ด์•ผ๋งŒ ํ•˜๋Š” ํŽ˜์ด์ง€

getStaticPath

  • ๋™์  ๋ผ์šฐํŒ… + getStaticProps๋ฅผ ์›ํ•  ๋•Œ ์‚ฌ์šฉ
  • ์ •์˜ํ•˜์ง€ ์•Š์€ ํ•˜์œ„ ๊ฒฝ๋กœ๋Š” ์ ‘๊ทผํ•ด๋„ ํ™”๋ฉด์ด ๋œจ์ง€ ์•Š๋Š”๋‹ค (error ํŽ˜์ด์ง€๋กœ ๋ผ์šฐํŒ…)
  • ๋™์  ๋ผ์šฐํŒ… ์‹œ, ๋ผ์šฐํŒ…๋˜๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

getServerSideProps

  • ๋นŒ๋“œ์™€ ์ƒ๊ด€์—†์ด, ๋งค ํŽ˜์ด์ง€ ์š”์ฒญ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค

Suspense

์ฐธ๊ณ , ๋ฆฌ์•กํŠธ ์ฝ”๋ฆฌ์•„ - suspense

  • suspense๊ฐ€ ๋ญ”๊ฐ€์š”?

suspense๋Š” ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๋ฅผ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

suspense๋Š” '์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฝ์–ด๋“ค์ด๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์•„์ง ์ค€๋น„๋˜์ง€ ์•Š์•˜๋‹ค'๊ณ  React์— ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋Š”, ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ž…๋‹ˆ๋‹ค.

์ดํ›„์— React๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ค€๋น„๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ UI๋ฅผ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์˜ˆ์‹œ ์ฝ”๋“œ ๋ณด๊ธฐ
const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense fallback={<h1>Loading profile...</h1>}>
      <ProfileDetails />
      <Suspense fallback={<h1>Loading posts...</h1>}>
        <ProfileTimeline />
      </Suspense>
    </Suspense>
  );
}

function ProfileDetails() {
  // ์•„์ง ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜๋”๋ผ๋„, ์‚ฌ์šฉ์ž ์ •๋ณด ์ฝ๊ธฐ๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline() {
  // ์•„์ง ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜๋”๋ผ๋„, ๊ฒŒ์‹œ๊ธ€ ์ฝ๊ธฐ๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค
  const posts = resource.posts.read();
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}
  • suspense๋กœ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์–ด๋–ค ๊ฒƒ๋“ค์ด ์žˆ๋‚˜์š”?
  1. ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค(axios, SWR, react-query)์ด React์™€ ๊นŠ๊ฒŒ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค

  2. ์˜๋„์ ์œผ๋กœ ์„ค๊ณ„๋œ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. suspense๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ถˆ๋Ÿฌ์ ธ์•ผ ํ•˜๋Š”์ง€๋ฅผ ์ •ํ•˜์ง€ ์•Š๊ณ , ์•ฑ์˜ ์‹œ๊ฐ์ ์ธ ๋กœ๋”ฉ ๋‹จ๊ณ„๋ฅผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค

  3. ๊ฒฝ์Ÿ ์ƒํƒœ(Race Condition)๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค. await๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋Š” ์ข…์ข… ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. suspense๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ฝ์–ด์˜ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง€๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

์›น ์„ฑ๋Šฅ ์ตœ์ ํ™”

LCP๊ฐ€ ๋ญ”๊ฐ€์š”?

LCP(Large Contentful Paint)๋Š” ์›น ํŽ˜์ด์ง€์—์„œ ๊ฐ€์žฅ ํฐ ์ฝ˜ํ…์ธ  ์š”์†Œ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ์„ฑ๋Šฅ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์›น ํŽ˜์ด์ง€์˜ ๋กœ๋”ฉ ์†๋„์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ ์ธ์‹์„ ๋ฐ˜์˜ํ•˜๊ณ  ์›น ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ ์ฐธ์—ฌ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•œ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค.

LCP๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด lazy load, ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๋ฐ ํ˜•์‹ ์ตœ์ ํ™”, CDN(์ฝ˜ํ…์ธ  ์ „์†ก ๋„คํŠธ์›Œํฌ) ๋“ฑ์˜ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ๋ฐ ๋น„๋””์˜ค์™€ ๊ฐ™์€ ๋Œ€์šฉ๋Ÿ‰ ์ฝ˜ํ…์ธ  ์š”์†Œ์˜ ๋กœ๋“œ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ HTML, CSS ๋ฐ JavaScript ํŒŒ์ผ์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์„œ๋ฒ„์— ๋Œ€ํ•œ ์š”์ฒญ ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜์—ฌ ์›น ํŽ˜์ด์ง€์˜ ์ „์ฒด ๋กœ๋“œ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Chrome DevTools์˜ Lighthouse ๊ฒ€์‚ฌ ๋˜๋Š” WebPageTest์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ํŽ˜์ด์ง€์˜ LCP๋ฅผ ์ธก์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

FCP๊ฐ€ ๋ญ”๊ฐ€์š”?

FCP(First Contentful Paint)๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›น ํŽ˜์ด์ง€์˜ ์ฒซ ๋ฒˆ์งธ ์ฝ˜ํ…์ธ  ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ์„ฑ๋Šฅ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค. ์ด ๋‚ด์šฉ ์š”์†Œ๋Š” ํ…์ŠคํŠธ, ์ด๋ฏธ์ง€ ๋˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์œ ํ˜•์˜ ๋‚ด์šฉ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

FCP๋Š” ์›น ํŽ˜์ด์ง€์˜ ๋กœ๋”ฉ ์†๋„์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ ์ธ์‹์„ ๋ฐ˜์˜ํ•˜๊ณ  ์›น ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ ์ฐธ์—ฌ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•œ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค.

FCP๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด HTML, CSS ๋ฐ JavaScript ํŒŒ์ผ์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์„œ๋ฒ„์— ๋Œ€ํ•œ ์š”์ฒญ ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜์—ฌ ์›น ํŽ˜์ด์ง€ ๋กœ๋“œ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋กœ๋“œ ํ”„๋กœ์„ธ์Šค์—์„œ ์šฐ์„  ์ˆœ์œ„๋ฅผ ์ง€์ •ํ•˜์—ฌ ์œ„์˜ ๋‚ด์šฉ๊ณผ ๊ฐ™์€ ์ค‘์š”ํ•œ ๋ฆฌ์†Œ์Šค์˜ ๋กœ๋“œ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

controlled pattern์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”?

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

Controlled ํŒจํ„ด์˜ ์ฃผ์š” ํŠน์ง•:

  1. ์ƒํƒœ ๊ด€๋ฆฌ:

    • ํผ ์š”์†Œ์˜ ๊ฐ’์„ React์˜ state๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋”ฐ๋ผ state๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ฐ’ ์„ค์ •:

    • ํผ ์š”์†Œ์˜ value ์†์„ฑ์„ state ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง:

    • onChange ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๊ฐ์ง€ํ•˜๊ณ  state๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ:

import React, { useState } from 'react';

function ControlledForm() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log('Submitted value:', inputValue);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type='text' value={inputValue} onChange={handleChange} />
      <button type='submit'>Submit</button>
    </form>
  );
}

Controlled ํŒจํ„ด์˜ ์žฅ์ :

  1. ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ: React๊ฐ€ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ์™„์ „ํžˆ ์ œ์–ดํ•˜๋ฏ€๋กœ UI์™€ ์ƒํƒœ ๊ฐ„์˜ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

  2. ์ฆ‰์‹œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋”ฐ๋ผ ์ฆ‰์‹œ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. ์กฐ๊ฑด๋ถ€ ๋น„ํ™œ์„ฑํ™”: ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ํผ ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  4. ๊ฐ’ ํฌ๋งทํŒ…: ์ž…๋ ฅ๊ฐ’์„ ์ฆ‰์‹œ ํฌ๋งทํŒ…ํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜์‚ฌํ•ญ:

  1. ์„ฑ๋Šฅ: ๋งŽ์€ ์ˆ˜์˜ ํผ ์š”์†Œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ๊ฐ ์ž…๋ ฅ๋งˆ๋‹ค ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ๋ณต์žก์„ฑ: ๊ฐ„๋‹จํ•œ ํผ์˜ ๊ฒฝ์šฐ Uncontrolled ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ฐ„๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Controlled ํŒจํ„ด์€ React์—์„œ ํผ์„ ๋‹ค๋ฃฐ ๋•Œ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ์‹์ด๋ฉฐ, ํŠนํžˆ ๋ณต์žกํ•œ ํผ์ด๋‚˜ ๋™์ ์ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

uncontrolled pattern์— ๋Œ€ํ•ด์„œ ์•„๋‚˜์š”?

Uncontrolled ํŒจํ„ด์€ React์—์„œ ํผ ์š”์†Œ์˜ ์ƒํƒœ๋ฅผ ์ง์ ‘ React์˜ state๋กœ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ , DOM์ด ๋‚ด๋ถ€์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ์ฃผ๋กœ ref๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งŒ DOM์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

Uncontrolled ํŒจํ„ด์˜ ์ฃผ์š” ํŠน์ง•:

  1. ์ƒํƒœ ๊ด€๋ฆฌ:

    • React์˜ state๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  DOM์ด ์ž์ฒด์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    • ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ref๋ฅผ ํ†ตํ•ด DOM์—์„œ ๊ฐ’์„ ์ฝ์–ด์˜ต๋‹ˆ๋‹ค.
  2. ๊ฐ’ ์„ค์ •:

    • ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•˜๋ ค๋ฉด defaultValue ์†์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง:

    • onChange ์ด๋ฒคํŠธ๋ฅผ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ:

import React, { useRef } from 'react';

function UncontrolledForm() {
  const inputRef = useRef(null);

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log('Submitted value:', inputRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type='text' defaultValue='' ref={inputRef} />
      <button type='submit'>Submit</button>
    </form>
  );
}

Uncontrolled ํŒจํ„ด์˜ ์žฅ์ :

  1. ๊ฐ„๋‹จ์„ฑ: ๊ฐ„๋‹จํ•œ ํผ์˜ ๊ฒฝ์šฐ ์ฝ”๋“œ๊ฐ€ ๋” ๊ฐ„๊ฒฐํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ์„ฑ๋Šฅ: React์˜ state๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ž…๋ ฅ ์‹œ๋งˆ๋‹ค ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  3. ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ†ตํ•ฉ: React ์™ธ๋ถ€์˜ DOM ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ†ตํ•ฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

  4. ํŒŒ์ผ ์ž…๋ ฅ: file input๊ณผ ๊ฐ™์ด ์ฝ๊ธฐ ์ „์šฉ ๊ฐ’์„ ๋‹ค๋ฃฐ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์˜์‚ฌํ•ญ:

  1. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ: ์ฆ‰๊ฐ์ ์ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋‚˜ ์ž…๋ ฅ๊ฐ’ ๋ณ€ํ™˜์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

  2. ๋™์  UI: ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ UI๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

  3. ๊ฐ’ ์ดˆ๊ธฐํ™”: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ž…๋ ฅ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

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

Controlled์™€ Uncontrolled ํŒจํ„ด์€ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์žˆ์œผ๋ฏ€๋กœ, ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ํŒจํ„ด์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.