React: ๋น„๋™๊ธฐ ์„œ๋ฒ„ ๋ Œ๋”๋ง ์ง€์›(๋ Œ๋”๋ง ์ „ ๋ฐ์ดํ„ฐ ๋Œ€๊ธฐ)

์— ๋งŒ๋“  2014๋…„ 06์›” 24์ผ  ยท  139์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: facebook/react

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

Component API Server Rendering Backlog Feature Request

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋ช‡ ๋‹ฌ ์ „ ๋‚˜๋Š” JSConf ์•„์ด์Šฌ๋ž€๋“œ์—์„œ React์˜ ๋‹ค๊ฐ€์˜ค๋Š” ๋น„๋™๊ธฐ ๋ Œ๋”๋ง ๊ธฐ๋Šฅ์„ ์„ค๋ช…ํ•˜๋Š” ์—ฐ์„ค์„ ํ–ˆ์Šต๋‹ˆ๋‹ค(๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„ ์ฐธ์กฐ): https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react -16.html. ์ด๊ฒƒ์€ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ @acdlite ๋Š” React ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ๋Œ€๊ธฐํ•˜๊ณ  ์ค€๋น„๊ฐ€ ๋˜๋ฉด ๋งˆํฌ์—…์„ ์ ์ง„์ ์œผ๋กœ ํ”Œ๋Ÿฌ์‹œํ•˜๋Š” ๋ฐ ๋™์ผํ•œ ๊ฐœ๋…์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค. https://www.youtube.com/watch?v= z-6JC0_cOns

์ด ๊ฐ•์—ฐ์„ ์ฆ๊ฒ๊ฒŒ ์‹œ์ฒญํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค! 1๋…„ ์ •๋„ ์ง€๋‚˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๋งˆ๋ฌด๋ฆฌํ•˜๊ณ  ์ด์— ๋Œ€ํ•œ ๊ณต์‹ ์ „๋žต์„ ์„ธ์šธ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  139 ๋Œ“๊ธ€

์ด๊ฒƒ์ด ์ด๋ฏธ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ฃผ๋œ ์ด์œ (๋‚ด ์ƒ๊ฐ์—)๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ Œ๋”๋ง์„ ์—ฐ๊ธฐํ•˜๋Š” ๋Œ€์‹  ํ•ญ์ƒ ์ผ์ข…์˜ ๋กœ๋“œ ํ‘œ์‹œ๊ธฐ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (๊ทธ๊ฒƒ์€ ๋˜ํ•œ ์ฝ”๋“œ๋ฅผ ํ›จ์”ฌ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์ง€๋งŒ ์•„๋งˆ๋„ ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.)

๊ทธ๊ฒƒ ์—†์ด๋Š” ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ค์šด ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

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

react-async ๋Š” ํŒŒ์ด๋ฒ„ ๋ฐ ์บ์‹œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ํŠธ๋ฆญ์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ ๋‚ด ๊ด€์ ์—์„œ ๊ทธ๊ฒƒ๋“ค์€ ํ•ต์‹ฌ์—์„œ๋งŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ _hackish_ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

@fdecampredon ์€ ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ์•Œ์ง€ componentWillMount ๊ฐ€ ๋น„๋™๊ธฐ์‹์ด๊ณ  ์•„๋ฌด ๊ฒƒ๋„ ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ์•„๋ฌด๊ฒƒ๋„ ์—†์„ ๋•Œ๊นŒ์ง€ React๋Š” ๋ฌด์—‡์„ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์•„์ง ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ Œ๋”๋ง์—์„œ ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? (์˜ˆ, ์„œ๋ฒ„ ์ธก์„ ์–ป์Šต๋‹ˆ๋‹ค) ๋˜ํ•œ componentWillMount ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— props๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ฉ๋‹ˆ๊นŒ?

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

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

๋‚ด๊ฐ€ ์ž˜๋ชป ์ดํ•ดํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์–ธ์ œ๋“ ์ง€ ์ €๋ฅผ ๋ฌด์‹œํ•ด ์ฃผ์„ธ์š”. ๊ทธ๋Ÿฌ๋‚˜ React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ณด๊ธฐ์™€ ๋ชจ๋ธ๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@fdecampredon ์€ componentWillMount๊ฐ€ ๋น„๋™๊ธฐ์ด๊ณ  ์ฆ‰์‹œ ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ์•„๋ฌด๊ฒƒ๋„ ์—†์„ ๋•Œ๊นŒ์ง€ React๋Š” ๋ฌด์—‡์„ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์•„์ง ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ Œ๋”๋ง์—์„œ ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? (์˜ˆ, ์„œ๋ฒ„ ์ธก์„ ์–ป์Šต๋‹ˆ๋‹ค) ๋˜ํ•œ componentWillMount๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— props๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ฉ๋‹ˆ๊นŒ?

๋ชจ๋“  ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค ^^.
์ด ๊ธฐ๋Šฅ์€ ์ตœ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ฒ˜์Œ ๋งˆ์šดํŠธํ•  ๋•Œ๋งŒ ์œ ์šฉํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ์บ์ŠคํŠธ์—์„œ ๋กœ๋” ํ‘œ์‹œ๊ธฐ๋ฅผ ํ‘œ์‹œํ•˜๋ ค๋Š” ๊ฒƒ์ด ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค.

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

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

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

์•„๋งˆ๋„ ๋‚ด๊ฐ€ ์ž˜๋ชป๋œ ๋ฐฉ์‹์œผ๋กœ ์ผ์„ ์ดํ•ดํ•˜์ง€๋งŒ ์›น ์ฃผ๋ณ€์˜ ์ผ๋ถ€ ํ† ๋ก /์ƒ˜ํ”Œ๋กœ ์ธํ•ด ์–ด๋”˜๊ฐ€์— ๋ˆ„๋ฝ๋œ ๊ฒƒ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์ผ๋ถ€ ์ƒ˜ํ”Œ ์—์„œ๋Š” @petehunt ๊ฐ€ ๋น„์Šทํ•œ ๊ฒƒ์„ ๋‹ฌ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • react-nested-router ๋Š” willTransitionTo ์—์„œ ์œ ์‚ฌํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ™๋ณดํ•˜๊ณ  ์ผ๋ถ€ ํ† ๋ก  ์—์„œ๋Š” ์•„๋ฌด๋„ ์ ์ ˆํ•œ ์†”๋ฃจ์…˜์„ ์ฐพ์ง€ ๋ชปํ–ˆ๋‹ค๊ณ  ๋Š๋‚๋‹ˆ๋‹ค.
  • RRouter ๋Š” ๋˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ Œ๋”๋ง/๋งˆ์šดํŠธ๋  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ
  • ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์•ž์„œ ๋งํ–ˆ๋“ฏ์ด ๋ฐ˜์‘ ๋น„๋™๊ธฐ์‹ ์ž…๋‹ˆ๋‹ค.

@fdecampredon ๋ช…ํ™•ํ•˜๊ฒŒ, react-nested-router์—์„œ willTransitionTo ์˜ ๋ชฉ์ ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•œ _์•„๋‹Œ_์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ํ•ด๋‹น ๋ฉ”์„œ๋“œ์—์„œ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์‹ค์ œ๋กœ ์›ํ•˜์ง€ ์•Š๋Š” ์ƒˆ UI ๋ Œ๋”๋ง์ด ์ฐจ๋‹จ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ผญ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด.

@fdecampredon ๋ชจ๋‘๊ฐ€ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์•„๋ฌด๋„ ํ™•์‹คํ•œ ๋‹ต์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์•„๋„ ๋†€๋ผ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Facebook์˜ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ด ๋ฌธ์ œ๋ฅผ ๋ช‡ ๋ฒˆ ๊ฒช์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

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

๋‚ด๊ฐ€ ์ž˜๋ชป ์ดํ•ดํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์–ธ์ œ๋“ ์ง€ ์ €๋ฅผ ๋ฌด์‹œํ•ด ์ฃผ์„ธ์š”. ๊ทธ๋Ÿฌ๋‚˜ React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ณด๊ธฐ์™€ ๋ชจ๋ธ๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ผ๋ฉด React๋Š” ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ํ…œํ”Œ๋ฆฟ ์†”๋ฃจ์…˜/๋ทฐ ๋ ˆ์ด์–ด์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋Ÿฌํ•œ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. @fdecampredon ์ด ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋œ ๋ณต์žกํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์–ธ๊ธ‰ํ•  ๋•Œ ์ •๋ง ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. React๋Š” ์ด๊ฒƒ์„ ์œ„ํ•ด ์™„๋ฒฝํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ณด๊ธฐ ๋ฐ ๋ชจ๋ธ๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Flux ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณด๋ฉด React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ _controller-views_๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž ์ƒํ˜ธ ์ž‘์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์—…์„ ํ˜ธ์ถœํ•˜๋Š” _controller-views_์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ž‘์—…์€ ์ƒ์ (= ๋ชจ๋ธ)์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์€ ๋ช…๋ฐฑํ•œ MVC ์•„ํ‚คํ…์ฒ˜์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

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

ํ˜„์žฌ๋กœ์„œ๋Š” React-async/Fibers + Flux๊ฐ€ ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. Flux์˜ ์ข‹์€ ์ ์€ ๊ตฌ์„ฑ ์š”์†Œ ์ƒํƒœ๋ฅผ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ์ธ๊ณต ์บ์‹œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์›๋ž˜ react-async ์˜ˆ์ œ์—์„œ ์ˆ˜ํ–‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ). ๊ฐ„๋‹จํžˆ ์ €์žฅ์†Œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ ๋‹ค์Œ ์ €์žฅ์†Œ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. html ๋งˆํฌ์—…์ด ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ( ์ด ์˜ˆ์ œ ์ฐธ์กฐ).

๊ทธ๋Ÿฌ๋‚˜ ์ด ์†”๋ฃจ์…˜์€ ์‹ค์ œ๋กœ _hackish_์ž…๋‹ˆ๋‹ค.

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

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

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

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

๋„ค, ์ข‹์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์„œ๋ฒ„ ์ธก์—์„œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋‘ ๋ฒˆ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React ๋‚ด์—์„œ ์ง€์›๋˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒƒ์˜ ์˜ˆ๋กœ react-nexus ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ DOM์— ๋งˆ์šดํŠธํ•˜๊ฑฐ๋‚˜ ๋ฌธ์ž์—ด์„ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ๊ตฌ์„ฑ ์š”์†Œ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ mountComponent ์ž‘๋™ ๋ฐฉ์‹์„ ๋‹ค์‹œ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ ์š”์†Œ ํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ  ํŠธ๋ฆฌ๊ฐ€ ๊ตฌ์ถ•๋˜๋Š” ๋™์•ˆ ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌํ˜„์˜ ๋ฌธ์ œ๋Š” ์ฒซ ๋ฒˆ์งธ ํŠธ๋ฆฌ๋ฅผ ๋ฒ„๋ฆฌ๊ณ  ์–ด์จŒ๋“  React.renderToString ๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋งŒ ์‚ฌ์ „ ๋ Œ๋”๋ง ํŠธ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ Œ๋”๋ง/๋งˆ์šดํŠธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ฝ”์–ด ๋‚ด์—์„œ ์ด ์ž‘์—…์„ ๊ธฐ๊บผ์ด ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์ง€์นจ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์š”๊ตฌ ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜๋Š” ๋น„๋™๊ธฐ๋กœ ์ธํ•ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ReactContext ๋ฅผ ์ „์—ญ์ ์œผ๋กœ ์ฐธ์กฐํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์™€ ๊ด€๋ จํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์ „์—ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@mridgway ๋‚ด๊ฐ€ ์‹ค์ˆ˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ธ€๋กœ๋ฒŒ ReactContext ๋Š” ํ˜ธํ™˜๋˜๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ 0.14์—์„œ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ œ๊ฐ€ _์•„๋งˆ๋„_ ํ‹€๋ฆด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@gaearon ์˜ˆ, withContext ์ง€์› ์ค‘๋‹จ์—์„œ ์–ป์€ ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

:+1: ์ด ATM์— react-router ๋ฅผ ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค. @mridgway ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋งค์šฐ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ๊ฒฌํ•ด๋Š” ๋ฒˆ๋“ค๋Ÿฌ(์˜ˆ: webpack)์—์„œ ์ƒ์„ฑ๋œ ์ฝ”๋“œ ์ฒญํฌ์˜ ๋น„๋™๊ธฐ์‹ ๋กœ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ด ํ‹ฐ์ผ“( https://github.com/rackt/react-router/issues/1402) ์—์„œ ๋…ผ์˜๋œ ๋ฐ”์™€ ๊ฐ™์ด ๋น„๋™๊ธฐ ๋ Œ๋”๋ง ์ง€์›์˜ ๋ฌธ์ œ๋Š” ๊ด€๋ จ ์ฒญํฌ๊ฐ€ ์ฒซ ๋ฒˆ์งธ์—์„œ ์•„์ง ๋กœ๋“œ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐ ๋ Œ๋”๋ง์ด null๋กœ ํ‘œ์‹œ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ Œ๋” ํŒจ์Šค๋กœ ์ธํ•ด DOM ๋ฃจํŠธ์— <noscript> ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์ฒดํฌ์„ฌ์ด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋ชจ๋“  ๊ฒƒ์ด ๋น ๋ฅด๊ฒŒ ์ œ์ž๋ฆฌ์— ๋†“์ด์ง€๋งŒ, ํŠนํžˆ ๋‹ค์šด๋กœ๋“œํ•  ์ฒญํฌ๊ฐ€ ์ ์ ˆํ•œ ํฌ๊ธฐ(์˜ˆ: > 30KB)์ธ ๊ฒฝ์šฐ ๋กœ์ปฌ์—์„œ ์ž‘์—…ํ•  ๋•Œ UI์—์„œ ๊นœ๋ฐ•์ž„์ด ๋ฐœ์ƒํ•˜๊ณ  ํ˜„์žฅ์—์„œ ๋” ๋‚˜๋น ์ง‘๋‹ˆ๋‹ค.

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

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

<WaitFor for={MyAsyncLoadedCompSignal} until={...} then={() => <MyAsyncLoadedComp ... />} /> ์™€ ๊ฐ™์ด ์ž์‹ ์—๊ฒŒ ๋” ์ ํ•ฉํ•œ ๋Œ€์ฒด ์ „๋žต์„ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•˜์„ธ์š”. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ๋“ค์€ ๋ณธ์งˆ์ ์œผ๋กœ ๋…๋‹จ์ ์ด๋ฉฐ React๊ฐ€ ์ œ๊ณตํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋งก๊ธฐ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

React ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฒ”์œ„ ๋ฐ–์— ์žˆ๋Š” ๋น„๋™๊ธฐ ํ•ญ๋ชฉ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

import React from 'react';
import Layout from './components/Layout';
import NotFoundPage from './components/NotFoundPage';
import ErrorPage from './components/ErrorPage';

const routes = {

  '/': () => new Promise(resolve => {
    require(['./components/HomePage'], HomePage => { // Webpack's script loader
      resolve(<Layout><HomePage /></Layout>);
    });
  }),

  '/about': () => new Promise(resolve => {
    require(['./components/AboutPage'], AboutPage => { // Webpack's script loader
      resolve(<Layout><AboutPage /></Layout>);
    });
  })

};

const container = document.getElementById('app');

async function render() {
  try {
    const path = window.location.hash.substr(1) || '/';
    const route = routes[path];
    const component = route ? await route() : <NotFoundPage />;
    React.render(component, container);
  } catch (err) {
    React.render(<ErrorPage error={err} />, container);
  }
}

window.addEventListener('hashchange', () => render());
render();

Webpack Code Splitting , React.js Routing from Scratch ๋ฐ react-routing (๊ณง ์ œ๊ณต ์˜ˆ์ •)์„ ์ฐธ์กฐํ•˜์„ธ์š”.

@syranide ๊ณ„์† ๋…ธ๋ ฅํ•˜๊ฒ ์ง€๋งŒ ์œ„์— ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” react-router๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ผ์šฐํ„ฐ๊ฐ€ React ํ™˜๊ฒฝ ์™ธ๋ถ€์— ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ตฌ์„ฑ ์š”์†Œ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ˜ผํ•ฉ์— ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<WaitFor ... /> ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์—์„œ ์—ฌ์ „ํžˆ ์ฝ˜ํ…์ธ ์˜ ๊นœ๋ฐ•์ž„/์†Œ์‹ค์„ ์œ ๋ฐœํ•˜๋Š” ๋‹ค๋ฅธ DOM์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์ ‘๊ทผ ๋ฐฉ์‹, ํ™•์‹คํžˆ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์—์„œ ์—ฌ์ „ํžˆ ์ฝ˜ํ…์ธ ์˜ ๊นœ๋ฐ•์ž„/์‚ฌ๋ผ์ง์„ ์œ ๋ฐœํ•˜๋Š” ๋‹ค๋ฅธ DOM์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊นœ๋ฐ•์ž„์„ ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ(์ผ๋ถ€๋Š” ํ•„์š”) ๋ Œ๋”๋ง ์ „์— ์˜์กดํ•˜๋Š” ๋ชจ๋“  ์ฒญํฌ๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. webpack์€ ์ฆ‰์‹œ require.resolve ํ•ฉ๋‹ˆ๋‹ค.

์ถ”์‹ . ๋„ค, react-router์™€ ๋‹น์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฒƒ๋“ค์€ ํ™•์‹คํžˆ ์†”๋ฃจ์…˜์„ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์ง€๋งŒ ์—ฌ์ „ํžˆ React๊ฐ€ ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๋ฌธ์ œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

๊นœ๋ฐ•์ž„์„ ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ(์ผ๋ถ€๋Š” ํ•„์š”) ๋ Œ๋”๋งํ•˜๊ธฐ ์ „์— ์˜์กดํ•˜๋Š” ๋ชจ๋“  ์ฒญํฌ๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. webpack์€ ๊ธฐ๋ณธ์ ์œผ๋กœ require.resolve๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

require.resolve ์— ๋Œ€ํ•œ ๋‚˜์˜ ์ดํ•ด๋Š” ๊ทธ๊ฒƒ์ด ๋ชจ๋“ˆ ID์˜ ๋™๊ธฐ ์กฐํšŒ์ด๊ณ  ์„œ๋ฒ„๋กœ์˜ ์—ฌํ–‰์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒญํฌ ๋กœ๋”ฉ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด require.ensure ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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

const history = new BrowserHistory();

if (typeof history.setup === "function") {
    history.setup();
}

Router.run(routes, history.location, (err, initialState, transition) => {
    React.render(<Provider redux={redux}>{() => <Router key="ta-app" history={history} children={routes} />}</Provider>, document.getElementById('ta-app'));
});

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์กฐ์‚ฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. require.resolve์— ๋Œ€ํ•œ ๋‚˜์˜ ์ดํ•ด๋Š” ๊ทธ๊ฒƒ์ด ๋ชจ๋“ˆ ID์˜ ๋™๊ธฐ ์กฐํšŒ์ด๊ณ  ์„œ๋ฒ„๋กœ์˜ ์—ฌํ–‰์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฒญํฌ ๋กœ๋”ฉ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด require.ensure๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ, require.ensure . ์ฝœ๋ฐฑ์€ ๋ชจ๋“  ์ข…์†์„ฑ์ด ์ถฉ์กฑ๋  ๋•Œ๋งŒ ์‹คํ–‰๋˜๋ฏ€๋กœ ๊ทธ ์•ˆ์— render/setState๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ต๋ณ€ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ react-router์—์„œ ๋‹ค๋ฃจ์–ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง€๋ฏ€๋กœ ๊ฑฐ๊ธฐ์—์„œ ํ† ๋ก ์„ ๊ณ„์†ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋Œ€ํ™”๋ฅผ ํ•˜๊ธฐ์— ์ž˜๋ชป๋œ ์žฅ์†Œ์˜€๋‹ค๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค!

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

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

๋‚˜๋Š” react-router์— ์ต์ˆ™ํ•˜์ง€ ์•Š์ง€๋งŒ ์—ฌ์ „ํžˆ ๋‹จ์ˆœํžˆ setRoute(...) => require.ensure([], function() { require(...); setRoute(...); }) ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ ์‹ค์ œ๋กœ๋Š” ์‹ค์šฉ์ ์ด์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹ค๋ฅธ ์ˆ˜์ค€์˜ ๊ฐ„์ ‘ ์ฐธ์กฐ๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ๋งต๊ณผ ๊ฐ๊ฐ์— ๋Œ€ํ•œ ๋น„๋™๊ธฐ require.ensure ๋กœ๋”. function asyncSetRoute(...) { loadRoute(route, function() { setRoute(...); }} ๋„์šฐ๋ฏธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ด์ œ ๋Œ€์‹  asyncSetRoute ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๋ผ์šฐํ„ฐ ์—…๋ฐ์ดํŠธ๋ฅผ ์—ฐ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

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

๊ทธ๋ž˜์„œ ๋ช‡ ์‹œ๊ฐ„ ๋™์•ˆ ์กฐ์‚ฌํ•œ ๋์— ์œ„์—์„œ ์•„๋ž˜๋กœ(?) ๋ชจ๋“  ๊ฒƒ์„ ๊ณต๊ธ‰ํ•˜์ง€ ์•Š๋Š” ํ•œ ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด _ ๋ถˆ๊ฐ€๋Šฅ _ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์ด์ œ ๋ง‰ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ ๋‹จ๊ธฐ ์†”๋ฃจ์…˜:
A. ์ €์žฅ์†Œ๋ฅผ ๋ฏธ๋ฆฌ ์ฑ„์šฐ๊ณ  ์„œ๋ฒ„ ์ธก ๋กœ๋”ฉ์„ ๋™๊ธฐ์‹์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

B. ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ ๊ฐœ์ฒด๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ฐ€์ ธ์˜จ ํ›„ ์œ„์—์„œ๋ถ€ํ„ฐ ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์„ ๊ณต๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

์žฌ: '์•„'. ๋ Œ๋” ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์ง€ ์•Š์œผ๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด ๋‹ค์–‘ํ•œ โ€‹โ€‹์ปฌ๋ ‰์…˜/๋ชจ๋ธ/API ์ข…์†์„ฑ์„ ์•Œ๊ธฐ ์œ„ํ•ด ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ API ์—†์ด ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ ์„œ๋ฒ„์—์„œ๋Š” ๋™๊ธฐํ™”ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์žฌ: 'B'. ๊ธฐ๋ณธ์ ์œผ๋กœ ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ๊ฐ๊ฐ์˜ ๊ฒฝ๋กœ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์•ฝ๊ฐ„์˜ ์ข…์†์„ฑ JSON์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

React ์ง€์› ์†”๋ฃจ์…˜์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ๋‹จ๊ธฐ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์‚ฌ์šฉ์ž ํ† ์ง€ ํฌํฌ ๋˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์Šต๋‹ˆ๊นŒ? https://www.npmjs.com/package/react-async ?

@NickStefan

๋ฌธ์ œ๊ฐ€ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. :-(

  1. ์ €์žฅ์†Œ๊ฐ€ ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹Œ ๊ฒฝ์šฐ Flux ๋˜๋Š” Flux์™€ ์œ ์‚ฌํ•œ ์ปจํ…Œ์ด๋„ˆ(Alt, Redux, Flummox ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ์—์„œ fetchData ์™€ ๊ฐ™์€ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  3. ์„œ๋ฒ„์—์„œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๊ฒฝ๋กœ๋ฅผ ์ผ์น˜์‹œํ‚ค๊ณ  fetchData ๋ฅผ ๊ฐ€์ ธ์™€ ๋ Œ๋”๋ง ์ „์— ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Flux ๋˜๋Š” Redux ์Šคํ† ์–ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ์ฑ„์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ €์žฅ์†Œ ์ธ์Šคํ„ด์Šค๋Š” ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹™๋‹ˆ๋‹ค. ํŠน์ • ์š”์ฒญ์— ๋ฐ”์ธ๋”ฉ๋˜๋ฏ€๋กœ ์š”์ฒญ์ด ๊ฒฉ๋ฆฌ๋œ ์ƒํƒœ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  4. ํ”„๋ผ๋ฏธ์Šค๊ฐ€ ์ค€๋น„๋˜๋ฉด ๋ฐฉ๊ธˆ ๋ฏธ๋ฆฌ ์ฑ„์šด ์Šคํ† ์–ด ์ธ์Šคํ„ด์Šค์™€ ๋™๊ธฐ์ ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์„ค๋ช…ํ•˜๋Š” Redux์— ๋Œ€ํ•œ ์ข‹์€ ์ž์Šต์„œ์ž…๋‹ˆ๋‹ค. https://medium.com/@bananaoomarang/handcrafting -an-isomorphic-redux-application-with-love-40ada4468af4

@gaearon ํ˜ผ๋ž€์„

์ด๊ฒƒ์€ ์ข‹์€ ํ”Œ๋Ÿญ์Šค ๊ด€ํ–‰์ด์ง€๋งŒ ์ž ์žฌ์ ์œผ๋กœ ์ œํ•œ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ๋งค์šฐ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๋ทฐ ํŠธ๋ฆฌ์˜ ๋งจ ์•„๋ž˜์— ์ž‘์€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฃจํŠธ์—์„œ ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ํŽธ์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๊ฒƒ์€ ๊นŠ์ด ์ค‘์ฒฉ๋œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋ฃจํŠธ ๊ตฌ์„ฑ ์š”์†Œ์— ๊ทธ๋“ค์˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฃจํŠธ๋ฅผ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ํ•˜๋‚˜์˜ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์— ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

@NickStefan with react-routing , ์˜ˆ๋ฅผ ๋“ค์–ด ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

import Router from 'react-routing/lib/Router';
import http from './core/http';

const router = new Router(on => {
  on('/products', async () => <ProductList />);
  on('/products/:id', async (state) => {
    const data = await http.get(`/api/products/${state.params.id`);
    return data && <Product {...data} />;
  });
});

await router.dispatch('/products/123', component => React.render(component, document.body));

์ด๋Ÿฌํ•œ ์†”๋ฃจ์…˜์€ ์ž‘๋™ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํ”„๋ฆฌํŽ˜์น˜๊ฐ€ ๋ผ์šฐํ„ฐ์— ๋ฐ”์ธ๋”ฉ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ(URL์ด ํŽ˜์ด์ง€์— ์žˆ์–ด์•ผ ํ•˜๋Š” ๋‚ด์šฉ๊ณผ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์žˆ์Œ) ์ผ๋ฐ˜์ ์œผ๋กœ ์ œํ•œ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์„ ์ž์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋…๋ฆฝํ˜• ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ(์˜ˆ: Twitter ์ŠคํŠธ๋ฆผ, ๋Œ“๊ธ€, ์บ˜๋ฆฐ๋”)๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๊ตฌ์„ฑ ์š”์†Œ ๊ณ„์ธต์— ์‚ฝ์ž…ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ react-async ์ด์ง€๋งŒ ์ด๊ฒƒ์€ ๊ฑฐ์˜ ํ•ดํ‚น์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” React ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹จ์ˆœํžˆ ์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉ๋˜๋„๋ก ์˜๋„๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ _controller_-views๋ณด๋‹ค ๋” ๋งŽ์€ ๋ณด๊ธฐ๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ React๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋“ฑ์žฅํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ œ ๊ฟˆ์€ ์–ธ์  ๊ฐ€ Wordpress, Drupal ๋˜๋Š” Modx์™€ ๊ฐ™์€ React๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„์ „ํ•œ CMS๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ HTML/PHP ์Šค๋‹ˆํŽซ ๋Œ€์‹  React ์ปดํฌ๋„ŒํŠธ์—์„œ ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@NickStefan

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

๋ฃจํŠธ ๊ตฌ์„ฑ ์š”์†Œ์— ๊ทธ๋“ค์˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฃจํŠธ๋ฅผ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ํ•˜๋‚˜์˜ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์— ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

๋ฃจํŠธ ์ฒ˜๋ฆฌ๊ธฐ ์ˆ˜์ค€์—์„œ ์ •ํ™•ํžˆ ๋ฃจํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์•ฑ์—๋Š” ๋งŽ์€ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ React Router ์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ค‘์ฒฉ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ง€์› ๋ฐฐ์—ด ์ด ํฌํ•จ๋˜๋ฏ€๋กœ Promise.all ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒŒ ๋ง์ด ๋ผ?

"๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ข…์†์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ"๋งŒํผ ์„ธ๋ถ„ํ™”๋œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ(์ƒ๋‹จ ๋ฐ ์ค‘์ฒฉ ์ฒ˜๋ฆฌ๊ธฐ)๋กœ ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด ์ œ๊ฐ€ ์›ํ•˜๋Š” ์ „๋ถ€๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์— props ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ์ˆœ์ˆ˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๊ฐ€์ ธ์˜ค๋Š” _์•Œ์ง€_์กฐ์ฐจ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ๊ทธ๊ฒƒ์„ ์š”์ฒญํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

"๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ข…์†์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค" ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ผ์ข…์˜ ์š”์ฒญ ์ผ๊ด„ ์ฒ˜๋ฆฌ ์†”๋ฃจ์…˜์ด ์—†๋Š” ํ•œ ์‹ค์šฉ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. <User> ๊ฐ€ API ํ˜ธ์ถœ์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์„ ์–ธํ•˜๊ณ  ์ด์ œ 100๊ฐœ์˜ <User> ๋ชฉ๋ก์„ ๋ Œ๋”๋งํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์„ธ์š”. 100๊ฐœ์˜ ์š”์ฒญ์„ ๊ธฐ๋‹ค๋ฆฌ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์š”๊ตฌ ์‚ฌํ•ญ ์„ธ๋ถ„์„ฑ์€ ์š”์ฒญ ์ผ๊ด„ ์ฒ˜๋ฆฌ ์†”๋ฃจ์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋‹น์‹ ์—๊ฒŒ ์ ํ•ฉํ•˜๋‹ค๋ฉด, Relay ๊ฐ€ ๋ฐ”๋กœ ๊ทธ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ํŠน๋ณ„ํ•œ ๋ฐฑ์—”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

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

@gaearon

"๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ข…์†์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค" ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ผ์ข…์˜ ์š”์ฒญ ์ผ๊ด„ ์ฒ˜๋ฆฌ ์†”๋ฃจ์…˜์ด ์—†๋Š” ํ•œ ์‹ค์šฉ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•ด ์ข€ ๋” ์ƒ๊ฐํ•œ ํ›„์—, ๋‚˜๋Š” ๋‹น์‹ ์˜ ๋ง์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ฐพ๋˜ ๊ฒƒ์€ ์‹ค์ œ๋กœ ์‹ค์šฉ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚œ ์›๋ž˜ ๋„ˆ์˜ 100๋„์˜ˆ๋ฅผ ๋“ค์–ด์ด ํŒ€ ํ›ˆ๋ จ์— ๊ดœ์ฐฎ์„ ๊ฒƒ (์ฆ‰ ๋‹จ์ง€ ์ €์ง€๋ฅด๋Š” <UsersContainer> ๋ชจ๋“  100 ์ผ ๊ฐœ ์š”๊ตฌ๋ฅผ ์•Š์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ˆœํžˆ ์ปจ๋ฒค์…˜์„ ๊ฐ–๋Š” ๊ฒƒ์€ "์‚ฌ๋žŒ๋“ค์ด ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š”" ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋ฃจํŠธ ๋˜๋Š” ๋ผ์šฐํ„ฐ์— ๋Œ€ํ•œ ๋ชจ๋“  ์ข…์†์„ฑ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค. Relay๋Š” ์„ธ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ(RelayContainer, RelayRootContainer, RelayRouter ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฃจํŠธ์—์„œ ์ข…์†์„ฑ์„ ์„ ์–ธํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์ข…์†์„ฑ ์„ ์–ธ์„ ํŠธ๋ฆฌ ์œ„๋กœ "ํ˜ธ์ด์ŠคํŠธ"ํ•˜๋Š” ๊ฒƒ์ด ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ์ ์„ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”!
์ด์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

+1

๋‚˜๋Š” ๋‹น์‹ ์ด ์ •๋ง๋กœ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•œ๋‹ค๋ฉด, ๋‹น์‹ ์€ ์ด๊ฒƒ์„ ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์›๋ž˜ React๊ฐ€ ๋น„๋™๊ธฐ ๋ Œ๋”๋ง์„ ํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์Šค๋ ˆ๋“œ์˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๊ณ  ํ™•์‹ ํ–ˆ์Šต๋‹ˆ๋‹ค.

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

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

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

๋ทฐ๊ฐ€ ๋กœ๋“œํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์ •ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ๋Š” ๊ฑฐ๊พธ๋กœ์ž…๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ธŒ๋ฆฌ์ง€๋ฅผ ํ†ตํ•ด ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด ๋น„๋™๊ธฐ๊ฐ€ ํ•„์š”ํ•œ ์›น ์ž‘์—…์ž(#3092) ๋‚ด์—์„œ React ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ์ถ”๊ตฌํ•œ๋‹ค๋ฉด ์ด ๋…ผ์˜๊ฐ€ ํ›จ์”ฌ ๋” ๊ด€๋ จ์„ฑ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

์ „์ฒด ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ์ด๋ฏธ ๋…ผ์˜๋˜์—ˆ๋‹ค๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

์ •๋ง ๋„์›€์ด ๋  ํ•œ ๊ฐ€์ง€๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ "์‹œ์ž‘/์ธ์Šคํ„ด์Šคํ™”"ํ•˜๊ณ  ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ html ๋ฌธ์ž์—ด๋กœ ๋ Œ๋”๋งํ•  ์ค€๋น„๊ฐ€ ๋œ ์‹œ์ ์„ ๊ฒฐ์ •ํ•˜๊ฒŒ ํ•˜๋Š” react-dom/server ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. . ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐœ๋ฐœ์ž๋Š” setTimeout ๋˜๋Š” ๋” ์•ˆ์ •์ ์ธ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํ˜„์žฌ ์ด๊ฒƒ์„ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด redux์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” "ํ•ดํ‚น"์ž…๋‹ˆ๋‹ค.

  // start/instantiate component
  // fires componentWillMount methods which fetch async data
  ReactDOM.renderToString(rootEle)

  // all my async methods increment a `wait` counter 
  // and decrement it when they resolve
  const unsubscribe = store.subscribe(() => {
    const state = store.getState()
    // as a result, when there are no more pending promises, the wait counter is 0
    if (state.wait === 0) {
      unsubscribe()
      // all the data is now in our redux store
      // so we can render the element synchronously
      const html = ReactDOM.renderToString(rootEle)
      res.send(html)
    }
  })

์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ๋ฌธ์ œ๋Š” ๋‘ ๋ฒˆ์งธ ReactDOM.renderToString ๊ฐ€ ๋ชจ๋“  componentWillMount ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์–˜๋“ค ์•„! ์ด๊ฒƒ์€ ํ˜„์žฌ ์ž‘์—… ์ค‘์ธ ๊ฒƒ์ž…๋‹ˆ๊นŒ? ์ด ๋ฌธ์ œ์˜ ์ค‘์š”์„ฑ์ด ์ปค์ง€๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ตœ๊ทผ์— react redux์˜ connect ๋ฅผ dataConnect ๋กœ ํ™•์žฅํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ปจํ…Œ์ด๋„ˆ ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์€ ๋Ÿฐํƒ€์ž„์— ๋ฒˆ๋“ค๋กœ ์ œ๊ณต๋˜๊ณ  ๋‹จ์ผ ์š”์ฒญ์—์„œ GraphQL๋กœ ์ฟผ๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๊ตฌ์„ฑ ๊ฐ€๋Šฅ์„ฑ๊ณผ ๊ฒฉ๋ฆฌ๋ฅผ ์ด‰์ง„ํ•˜๊ณ  ๋” ์„ฑ๋Šฅ์ด ์ข‹์€ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ๋ฐ์ดํ„ฐ ์‚ฌ์–‘์˜ ๋ฏธ๋ž˜๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. (Relay์—์„œ ๋ณธ ๋ชจ๋“  ๊ฐœ๋…)

์œ„์˜ ๋ฌธ์ œ๋Š” ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์œผ๋กœ ๋๋‚  ๊ฒƒ์ธ์ง€ ์ •์ ์œผ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ DB์—์„œ ์ฟผ๋ฆฌํ•  ๋ฒˆ๋“ค์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ํ•œ ๋ฒˆ ๋ Œ๋”๋งํ•ด์•ผ ํ•˜๊ณ  redux ์ €์žฅ์†Œ๋ฅผ ์ˆจ๊ธด ๋‹ค์Œ ์ตœ์ข… ๋ฌธ์ž์—ด์„ ์–ป๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. . ๋ฌธ์ œ๋Š” @olalonde ์˜ ๋ฌธ์ œ์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

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

const virtualTree = ReactDOM.renderVirtual(rootEle);

// get the bundled query from redux store for example
const bundle = store.getState().bundle;

// Fetch the data according to the bundle
const data = fetchDataSomehow(bundle);

// hydrate store
store.dispatch({type: 'hydrate', data});
// components that should update should be marked on the virtual tree as 'dirty'

virtualTree.update(); // this would only update the components that needed update

const domString = virtualTree.renderToString(); // final result

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

์—ฌ๋Ÿฌ๋ถ„์€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”? ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ œ๊ฐ€ ์™„์ „ํžˆ ์ž˜๋ชป ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

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

๊ทธ ์ดํ›„๋กœ ์ €๋Š” REST/HATEOS ์ด๋ฉด์˜ ์ด์ƒ์— ๋Œ€ํ•ด ํ›จ์”ฌ ๋” ๊นŠ์€ ์กด๊ฒฝ์‹ฌ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ง€์นจ ์›์น™์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์Šคํ…œ(๋ธŒ๋ผ์šฐ์ €, ํฌ๋กค๋Ÿฌ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„, ํ”„๋ก์‹œ, CDN ๋“ฑ)์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๋Œ€๊ทœ๋ชจ ๋‹จ์ˆœ์„ฑ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ž๋‹ค. ์ด ๋ฌธ์ œ์™€ ๊ด€๋ จํ•˜์—ฌ _URL์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ์˜ ์ง„์ •ํ•œ ํ‘œํ˜„์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค_. ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ทฐ ๋ ˆ์ด์–ด์ธ React๋Š” ์ด๊ฒƒ์„ ๊ฒฐ์ •ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณด๊ธฐ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ธฐ๋Šฅ์ด๊ณ  ๋ฐ์ดํ„ฐ๋Š” URL์˜ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค .

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

  • ๊ท€ํ•˜์˜ ์ฃผ์—๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ณ„๋„์˜ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒํƒœ(๋˜๋Š” ๊ทธ ์ผ๋ถ€)๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ URL์— ๋งž์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฆ„/์•„์ด๋””๋กœ ์ฐธ๊ณ ํ•˜์„ธ์š”.
  • ์ƒํƒœ๊ฐ€ ๋„ˆ๋ฌด ๋นจ๋ฆฌ ๋ณ€๊ฒฝ๋˜์–ด ์˜์›ํžˆ ์ €์žฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ? ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค. ํ•ฉ๋ฒ•์ ์ธ ๋น… ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•˜๊ณ  ์ €์žฅ์„ ์œ„ํ•œ ์Šคํ”„๋ง์„ ํ™•๋ณดํ•˜๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•  ๊ธฐ๋ฐœํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๋ถ€๋„๋Ÿฌ์›Œํ•˜๊ณ  UPDATE ์ฟผ๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜์ค‘์— ๋ชจ๋“  ๊ฒƒ์„ ์˜๊ตฌ์ ์œผ๋กœ ์บ์‹œํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(*).
  • ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๋‹ค๋ฅด์ง€๋งŒ ๋™์ผํ•œ URL(์˜ˆ: ๊ฐœ์ธํ™”๋œ ํ™ˆ ํŽ˜์ด์ง€)์—์„œ ์ œ๊ณต๋˜๋Š” ๋ณด๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์‚ฌ์šฉ์ž ์‹๋ณ„ ์‹œ ์‚ฌ์šฉ์ž ID๊ฐ€ ํฌํ•จ๋œ URL๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด์ „ URL ๊ตฌ์กฐ๋ฅผ ๊นจ๋Š” ์˜ต์…˜์ด ์—†๋Š” ์ด์ „ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์œ„์— ๊ตฌ์ถ•ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๊ณ ํ†ต์Šค๋Ÿฝ๋‹ค, ๋‚˜๋Š” ๊ฐ™์€ ๋ฐฐ์— ์žˆ๋‹ค. ์ด์ „ URL ๊ตฌ์กฐ๋ฅผ ์ž˜ ๊ตฌ์„ฑ๋œ URL ๊ตฌ์กฐ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜์—ฌ ์„ธ์…˜ ๋ฐ์ดํ„ฐ(๋˜๋Š” ๋ฌด์—‡์ด๋“ )๋ฅผ URL ๊ฒฝ๋กœ ์„ธ๊ทธ๋จผํŠธ ๋ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ฑฐ์˜ ๋˜๋Š” ์ „ํ˜€ ์ œ์–ดํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ React๊ฐ€ ์„ค๊ณ„๋œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉฐ ์ƒํ˜ธ ํ˜ธํ™˜๋˜๋Š” Wordpress / Magnolia / Umbraco ์•„ํ‚คํ…์ฒ˜์™€ ๊ฐ™์€ ๊ฒƒ์— ์ ํ•ฉํ•˜๋„๋ก React๊ฐ€ ์—‰๋ง์ด ๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ฐ€์งˆ ์ˆ˜ ์—†์—ˆ์„ ๊ทธ ๋ชจ๋“  ์ผ์— ๋Œ€ํ•ด ๋ฌด์—‡์„ ์–ป์Šต๋‹ˆ๊นŒ?

  • ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ URL์„ ๊ณต์œ ํ•˜์—ฌ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋™์ผํ•œ ์œ„์น˜๋กœ ๋ฐ๋ ค์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํƒ์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ. ํ‘œ์ค€ ํด๋ผ์ด์–ธํŠธ๋Š” ํ•ด๋‹น ์š”์†Œ์— ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋”ฐ๋ฅด๊ธฐ ์‰ฌ์šด ๋ฐฉ์‹์œผ๋กœ ๋ณต์žกํ•œ ํŽ˜์ด์ง€ ๋งค๊น€์„ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ: ์‘๋‹ต์˜ next ๋งํฌ. FB ๊ทธ๋ž˜ํ”„ API๊ฐ€ ์ด์— ๋Œ€ํ•œ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค.
  • Google ์• ๋„๋ฆฌํ‹ฑ์Šค์˜ ์‚ฌ์šฉ์ž ์›Œํฌํ”Œ๋กœ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๊ทธ๋ž˜ํ”„์ž…๋‹ˆ๋‹ค.
  • ์š”์ฒญ ๋กœ๊ทธ ์™ธ์—๋Š” ์•„๋ฌด ๊ฒƒ๋„ ์—†์ด ํ•ด๋‹น ๊ทธ๋ž˜ํ”„๋ฅผ ์ง์ ‘ ๊ตฌ์„ฑํ•˜๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค.
  • ํ˜ผ๋ˆ์˜ ๊ธธ์—์„œ ํƒˆ์ถœ: ๋ชจ๋“  ์š”์ฒญ์„ app.get("*", theOneTrueClientonaserverEntryPoint) ๋กœ ์ผ์น˜์‹œํ‚ค๋Š” ๋Œ€์‹  ์˜๋„ํ•œ ๋Œ€๋กœ ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 200 OK\n\n{status: "error"} ๋Œ€์‹  ์š”์ฒญ์—์„œ ์˜ฌ๋ฐ”๋ฅธ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํƒ€ ๋ฃจํŠธ๋Š” ๋งค๋ ฅ์ ์ด์ง€๋งŒ ๊ด‘๊ธฐ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

์ด์ œ ์Šคํƒ€ ๋„๊ตฌ์ธ React๊ฐ€ ์ž‘์—…์„ ์ œ์–ดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ Œ๋”๋งํ•  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

  1. ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๊ธฐ๋Šฅ์œผ๋กœ ๋ผ์šฐํŒ…ํ•˜๊ณ  ๊ด€๋ จ ์š”์ฒญ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ „์ฒด URL์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ  ์™„์ „ํ•œ ์ปจํ…์ŠคํŠธ ๊ฐœ์ฒด๋ฅผ ๊ฐ€์งˆ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.
  2. API ์š”์ฒญ์— ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์‘๋‹ต ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. API ์š”์ฒญ์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋Ÿฐ ๋‹ค์Œ ์™„๋ฃŒ๋˜๊ณ  ๊ฑด์กฐ๋ฉ๋‹ˆ๋‹ค.
  3. ์ตœ์†Œํ•œ์œผ๋กœ ๋ณต์žกํ•˜์ง€๋งŒ ๊ฐ€๋Šฅํ•œ ํฐ ๊ฐœ์ฒด๋ฅผ ์ตœ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” React ์ปดํฌ๋„ŒํŠธ ๊ตฌ์„ฑ์ด ์ „๋ถ€์ž…๋‹ˆ๋‹ค.
  4. ๋ฌธ์ž์—ด๋กœ ๋ Œ๋”๋งํ•˜๊ณ  ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. CDN์ด URL๋กœ ์‹๋ณ„ํ•˜๊ณ  ๋ชจ๋“  ์ฃผ์— URL์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— CDN์ด ์ด๊ฒƒ์„ ์˜์›ํžˆ ์บ์‹œํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ๋ฆฌ์‹ญ์‹œ์˜ค(* ์œ„์˜ ์ด ์˜ต์…˜์„ ํฌ์ƒํ•˜์ง€ ์•Š๋Š” ํ•œ). ๋ฌผ๋ก  CDN์—๋Š” ๋ฌดํ•œํ•œ ์ €์žฅ ๊ณต๊ฐ„์ด ์—†์ง€๋งŒ ์šฐ์„  ์ˆœ์œ„๋Š” ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์ด React๋ฅผ ํ›Œ๋ฅญํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋ฐ”๋กœ ๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค. ์ตœ๊ณ ์˜ ์ „๋ง. ๋ณด๊ธฐ๋งŒ. ฮป

@d4goxn์— ๋™์˜ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” React๋ฅผ ๋ณด๊ธฐ ๊ณ„์ธต ์ด์ƒ์œผ๋กœ ๋งŒ๋“ค๋ ค๊ณ  ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋ผ์šฐํŒ…์ด ์ค‘์š”ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ง€์ •ํ•˜๊ธฐ์—๋Š” ํ™•์‹คํžˆ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ/์ปจํ…Œ์ด๋„ˆ ์ˆ˜์ค€์—์„œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ง€์ •ํ•˜๋ฉด React๋ฅผ ๋ณด๊ธฐ ๊ณ„์ธต ์ด์ƒ์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ฑ์— ๋Œ€ํ•ด ํ›จ์”ฌ ๋” ๋‚˜์€ ๊ฒฉ๋ฆฌ ๋ฐ ์›Œํฌํ”Œ๋กœ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํฐ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์•ฑ์— 30๊ฐœ์˜ ๊ฒฝ๋กœ๊ฐ€ ์žˆ๊ณ  ๊ฐ๊ฐ์— ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์ด ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ง€์ •๋œ ๊ฒฝ๋กœ ๋Œ€์•ˆ์— ๋”ฐ๋ผ ํ•ด๋‹น ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด 30๊ฐœ์˜ ๊ฒฝ๋กœ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ปจํ…Œ์ด๋„ˆ์— ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ ์›ํ•˜๋Š” ์œ„์น˜์— ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ ์•ค ํ”Œ๋ ˆ์ด์ž…๋‹ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Relay๊ฐ€ ์ด์— ๋Œ€ํ•œ ์ข‹์€ ์˜ˆ์ด๋ฉฐ ์ด์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๊ฐ€ ๋‚˜๋ณด๋‹ค ํ›จ์”ฌ ๋” ์ž˜ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค.

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

๋‚ด ์ œ์•ˆ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ React๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด์ง€๋งŒ dom/components ํŠธ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” '๊ฐ€์ƒ ์ „์šฉ' ๋ฐฉ๋ฒ•, ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ฒ„ ์ธก์—์„œ '์‹คํ–‰'ํ•  ์ˆ˜ ์žˆ๋Š” React๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. DOM์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด). ์—ฌ์ „ํžˆ ์บ์‹ฑ๊ณผ CDN์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ์‚ฌ์ดํŠธ์™€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์—ญํ•™์ด ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ ์ •์  ์บ์‹ฑ์ด ๊ฐ์†Œํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์ง€๋งŒ ๊ทธ๊ฒƒ์€ ๋˜ ๋‹ค๋ฅธ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค ๐Ÿ˜„

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

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

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

๋‚˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์—์„œ ์ฆ๊ฐ€ํ•˜๋Š” ๋ณต์žก์„ฑ๊ณผ ํ™œ๋™์œผ๋กœ ์ธํ•ด ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ€ ์„œ๋ฒ„์˜ ํ›จ์”ฌ ๋” ํฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋งค์šฐ ์ž‘์€ ๊ฐœ์ฒด๋กœ ํ‘œํ˜„๋˜๋Š” ๊ฒƒ์„ ๋ฐฐ์ œํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€๊ทœ๋ชจ ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด 1์ธ์นญ ์ŠˆํŒ… ๊ฒŒ์ž„์„ ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋งŽ์€ ์ผ์ด ๋น ๋ฅด๊ฒŒ ์ง„ํ–‰๋˜๊ณ  ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ฒŒ์ž„ ํ˜ธ์ŠคํŠธ/์„œ๋ฒ„๋กœ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๋ฅผ ์ „์†กํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์–ผ๋งˆ๋‚˜ ์ž‘์€ ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๊นŒ? ๋ชจ๋“  ์ž…๋ ฅ ์ƒํƒœ์˜ ๋งต. ํƒ€์ž„์Šคํƒฌํ”„ + ๋ถˆํ™•์‹ค์„ฑ ๋ฒ”์œ„, ํ‚ค๋ณด๋“œ์šฉ ~110๋น„ํŠธ ํ•„๋“œ, ๋งˆ์šฐ์Šค/์กฐ์ด์Šคํ‹ฑ ๋ฐ VR ํ—ค๋“œ์…‹ ๋ฐฉํ–ฅ์šฉ ์ˆ˜์‹ญ ๋ฐ”์ดํŠธ. ํด๋ผ์ด์–ธํŠธ๋Š” ์˜ˆ์ธกํ•˜๊ณ , ๋‚™๊ด€์ ์œผ๋กœ ๋ Œ๋”๋ง ๋ฐ ๋ฌผ๋ฆฌ์  ์ฒ˜๋ฆฌํ•˜๊ณ , ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ž‘์€ ์ƒํƒœ ๋ฐ ์ƒํƒœ ๊ธฐ๋ก์—์„œ ์—„์ฒญ๋‚œ ์–‘์˜ ์ •๋ณด๋ฅผ ๋„์ถœํ•˜๊ณ  ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด ์ƒ๋‹นํžˆ ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค( ๋ชจ๋“  ์ฃผ๋ณ€ ์—์ด์ „ํŠธ์— ๋Œ€ํ•ด ๋™์ผํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜, ์ž์‚ฐ ํ‘ธ์‹œ), ๊ทธ๋Ÿฌ๋‚˜ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ ์ŠคํŠธ๋ฆผ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹2KB ์š”์ฒญ์— ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Relay์™€ GraphQL์— ๋Œ€ํ•œ ๊ต์œก์„ ์š”์ฒญํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. API๊ฐ€ ์•ˆ์ •์ ์ธ ๋ฒ„์ „์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ํ”ผ์ƒ์ ์œผ๋กœ๋งŒ ์‚ดํŽด๋ณด์•˜์„ ๋ฟ์ž…๋‹ˆ๋‹ค(์ง€๊ธˆ ์ž ๊ฒจ ์žˆ์Šต๋‹ˆ๊นŒ?) ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ์ง€์ •ํ•˜๊ณ  ๊ฐ€์ ธ์™€์•ผ ํ•  ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ํ™•์‹คํ•˜๋‹ค๋ฉด, ์ข‹์€ ๊ณ„ํš์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค์‹œ ํ•œ ๋ฒˆ ์‚ดํŽด๋ด์•ผ ํ•  ๋•Œ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•ด ๋ช‡ ๊ฐ€์ง€ ์–ด๋ ค์šด ์งˆ๋ฌธ์ด ์žˆ์ง€๋งŒ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

:๋งฅ์ฃผ:

์ถ”์‹ : HTTP๊ฐ€ MMOFPS๋ฅผ ์œ„ํ•œ ์ข‹์€ ํ†ต์‹  ํ”„๋กœํ† ์ฝœ์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ œ์•ˆํ•˜๋ ค๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

@d4goxn ์ด์— ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ๋ง์„ค์ž„๊ณผ ํšŒ์˜๋ฅผ

๋‚˜๋Š” ์ด ์ˆ˜์ค€์˜ ์ถ”์ƒํ™”๊ฐ€ ๊ฐˆ ๊ธธ์ด๋ผ๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” Relax CMS์—์„œ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•ด ์™”์œผ๋ฉฐ ์›Œํฌํ”Œ๋กœ์šฐ์™€ ๊ฒฉ๋ฆฌ๋Š” ํ•จ๊ป˜ ์ผํ•  ์ˆ˜ ์žˆ๋Š” ํ–‰๋ณต์ž…๋‹ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์š”์ฒญ๋œ ๋ฐ์ดํ„ฐ๋Š” ui๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ ์ด์ƒ๋„ ์ดํ•˜๋„ ์•„๋‹ˆ๋ฉฐ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ๋ณ‘ํ•ฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ™•์ธ์— ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ Relate http://relax.github.io/relate/how-it-works.html ์—์„œ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‚ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‚ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๋…๋ฆฝ์ ์ธ ๋ธ”๋ก์œผ๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

๋‚˜์—๊ฒŒ ์ฃผ์š” ์งˆ๋ฌธ์€ ๊ทธ๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค.

๋‹น์‹ ์ด ์ œ์•ˆํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ข‹์€ ์˜ค๋ž˜๋œ ์„œ๋ฒ„ ์ธก MVC ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: Spring MVC๊ฐ€ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค). ํ˜„์žฌ URL์€ _๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋ทฐ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ๋‚ด ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ์›น ํŽ˜์ด์ง€๋ฅผ ๋ณด๋ฉด ์ผ์ข…์˜ ๊ตฌ์„ฑ ์š”์†Œ ๊ณ„์ธต ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค(๋ฐ˜๋“œ์‹œ React ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์•„๋‹˜). ๋‹น์‹ ์ด ํ•ด์•ผ ํ•  ์ผ์€ URL์—์„œ ๊ณ„์ธต์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‘ ๋ฒˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! ์ฒซ์งธ, ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š”์ง€ ์•Œ๊ธฐ ์œ„ํ•ด ์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋””์ฝ”๋”ฉํ•ด์•ผ ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ๋กœ ๋ณด๊ธฐ์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋””์ฝ”๋”ฉํ•˜์—ฌ... ์Œ... ์‹ค์ œ ๋ณด๊ธฐ๋ฅผ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๋งค์šฐ _DRY_ ์ ‘๊ทผ ๋ฐฉ์‹์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ €๋Š” Spring MVC์— ์ต์ˆ™ํ•˜์ง€ ์•Š์ง€๋งŒ React๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ MVC ํ”„๋ ˆ์ž„์›Œํฌ(Nette๋ผ๊ณ  ํ•˜๋Š” PHP ํ”„๋ ˆ์ž„์›Œํฌ)๋ฅผ ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์•„์ด๋””์–ด๋Š” ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ(์˜ˆ: ์–‘์‹)์— ๋Œ€ํ•ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๊ณ  ํŠนํžˆ _ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋กœ๋“œ_๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ํŒฉํ† ๋ฆฌ๋ฅผ ์ฝ”๋“œ์— ์ •์˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ณด๊ธฐ์˜ ์–ด๋Š ์œ„์น˜์—๋‚˜ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ HTML ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  _view ๊ณ„์ธต ๊ตฌ์กฐ_๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฝ์ž…ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ธฐ๋ณธ ํŒฉํ† ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ดˆ๊ธฐํ™”๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ž‘์€ ๋…๋ฆฝ ์ปจํŠธ๋กค๋Ÿฌ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๊ณ  ์ž์ฒด ์ˆ˜๋ช… ์ฃผ๊ธฐ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ข…์†์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ทฐ์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•˜์—ฌ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

  • ํ•ต์‹ฌ ๋„๊ตฌ๋Š” react-router ์ž…๋‹ˆ๋‹ค. ๊ฐ URL์—์„œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์š”์ฒญ์„ ํ›„ํ‚นํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ ์ธก๊ณผ ์„œ๋ฒ„ ์ธก ๋ชจ๋‘์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ณต์‹์ ์œผ๋กœ ๋งํ•˜๋ฉด ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ _controller_ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ react-router ์˜ ๋””์ž์ธ์ž…๋‹ˆ๋‹ค. ๋™์ผํ•œ ์œ„์น˜์—์„œ _data-hierarchy_ ๋ฐ _view/component hierarchy_๋ฅผ ๋ชจ๋‘ ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹ค์ œ ๊ฒฝ๋กœ ์ •์˜๋„ ๊ณ„์ธต์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋งค์šฐ _๋ฐ˜์‘ํ•˜๋Š” ๊ฒƒ ๊ฐ™์€_ ๋Š๋‚Œ์ž…๋‹ˆ๋‹ค.
  • ์ „์ฒด ์ƒํƒœ(๋ฐ์ดํ„ฐ)๋Š” redux ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ์žฅ์  ์™ธ์—๋„ ์ „์ฒด ์ƒํƒœ๋ฅผ ๋‹จ์ผ ๊ฐœ์ฒด๋กœ ์œ ์ง€ํ•˜๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ๊ฐœ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ connect() ์ ‘๊ทผ ๋ฐฉ์‹ ๋•๋ถ„์— props๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ƒ์œ„ ์ˆ˜์ค€์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์•„๋ž˜๋กœ ์ „๋‹ฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ๋˜ ๋‹ค๋ฅธ ํผ์ฆ ์กฐ๊ฐ์€ ์ƒํƒœ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ž‘๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ์žฌ์„ ํƒ ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋””์ปคํ”Œ๋ง ํŒฉํ„ฐ๋ฅผ ํฌ๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.

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

๋‚˜ ์—ญ์‹œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€์— ์žˆ์„ ๋•Œ ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•œ ๊ฒƒ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ๋™ํ˜• ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ์€ ์ฒ ํ•™์  ๋…ผ์Ÿ์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๊ณ , ๋‚˜๋Š” componentDidMount์—์„œ ์ž์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ตฌ์„ฑ ์š”์†Œ์™€ ํ•จ๊ป˜ ๋ฐ”๋‹๋ผ ๋ฐ˜์‘(๋˜ํ•œ ์ž์ฒด ๊ฐœ๋ฐœ ๋ผ์šฐํŒ…)์„ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•ด ์™”์Šต๋‹ˆ๋‹ค. ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ์ค‘๋ณต ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ์•„์ด๋””์–ด๊ฐ€ ์ •๋ง ์‹ซ์Šต๋‹ˆ๋‹ค. ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ ํŠธ๋ฆฌ์— ์ด๋ฏธ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉฐ ์—ฌ๊ธฐ์—์„œ๋Š” ์ „์ฒด ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ Œ๋” ํŒจ์Šค๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋ฆฌ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐ”๋กœ ์ง€๊ธˆ, ๋‚˜๋Š” isomophic react, imo์— ๋Œ€ํ•œ ์ด๊ฒƒ์˜ ์ค‘์š”์„ฑ์ด ์ปค์ง€๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋‘ ๋ฒˆ์งธ๋กœ ๋งํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ๋™์•ˆ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”.

๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํŠธ๋ž˜๋ฒ„์„œ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. -dependencies.js. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -> ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ -> ๋ฐ˜์‘ ๋ Œ๋”๋ง์„ ๋ฌธ์ž์—ด๋กœ.

@decodeman , FWIW์—์„œ๋Š” ๋Œ€๊ทœ๋ชจ ํ”„๋กœ๋•์…˜ ์•ฑ์—์„œ ์ด์ค‘ ๋ Œ๋” ์ ‘๊ทผ ๋ฐฉ์‹(๊ท€ํ•˜๊ฐ€ ์–ธ๊ธ‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€)์„ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•ด ์™”์Šต๋‹ˆ๋‹ค. ์ด redux-saga ์˜ˆ์ œ ์—์„œ ์˜๊ฐ์„ ์–ป์—ˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋ชจ๋“  ์œ ํ˜•์˜ ๋น„๋™๊ธฐ ๋กœ๋”ฉ์—์„œ ์ž˜ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋กœ๋“œ๋ฅผ componentWillMount ๋กœ ์ด๋™ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ ์šฉ์ด์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜์ ์ธ ๋กœ๋“œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณ ์ฐจ ๊ตฌ์„ฑ ์š”์†Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: prop x ํ•˜๊ณ  nil์ด๋ฉด ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ณ  ์ผ์ข…์˜ ์ง€์—ฐ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•์„ ๊ฐ–๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์–‘์ชฝ ๋ชจ๋‘๋ฅผ ํ–‰๋ณตํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด asyncRenderToString์ด๋ผ๋Š” ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  asyncOnLoad ๋˜๋Š” ์ด์™€ ์œ ์‚ฌํ•œ ์ƒˆ๋กœ์šด "lifecycle" ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. asyncRender ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก๊ณผ ํด๋ผ์ด์–ธํŠธ ์ธก ์‚ฌ์ด์˜ ์ฝ”๋“œ ์ค‘๋ณต ์ธก๋ฉด์—์„œ ์ด๊ฒƒ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ผ๋ฐ˜์ ์ธ ๋กœ๋”ฉ ์ฝ”๋“œ๋ฅผ ๋ณ„๋„์˜ ๋ฉ”์†Œ๋“œ๋กœ ์˜ฎ๊ธฐ๊ณ  asyncOnLoad ๋ฐ componentMount ์—์„œ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. asyncOnLoad๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ๊ฐ์ง€ํ•˜๋ฉด ๋ฐ˜ํ™˜๋œ Promise๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(undefined๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ฑฐ๋‚˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•ด๋‹น ์ˆ˜๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ๋ Œ๋”๋งํ•ด์•ผ ํ•จ). ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด Promise๊ฐ€ ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์€ ์ŠคํŠธ๋ฆผ ์ฒดํฌ ์•„์›ƒ ๋ฐ˜์‘ ์ŠคํŠธ๋ฆผ์ด๋ผ๊ณ  ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

2016๋…„ 11์›” 3์ผ ๋ชฉ์š”์ผ, Florian Krauthan [email protected]
์ผ๋‹ค:

๋‚ด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๊ตฌ์„ฑ ์š”์†Œ์™€ ์ผ์ข…์˜ ์ง€์—ฐ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋‘˜ ๋‹ค ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด
side happy๋Š” asyncRenderToString์ด๋ผ๋Š” ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
asyncOnLoad ๋˜๋Š” ์ด์™€ ์œ ์‚ฌํ•œ "lifecycle" ์ด๋ฒคํŠธ. ์ด๊ฒƒ์€
asyncRender ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ ๋ฉด์—์„œ
์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์ธก ๊ฐ„์˜ ์ค‘๋ณต์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ผ๋ฐ˜์ ์ธ ๋กœ๋”ฉ ์ฝ”๋“œ๋ฅผ ๋ณ„๋„์˜ ๋ฉ”์†Œ๋“œ๋กœ ์˜ฎ๊ธฐ๊ณ 
asyncOnLoad ๋ฐ componentMount์˜ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. asyncOnLoad์ธ์ง€ ๊ฐ์ง€
done์€ ๋ฐ˜ํ™˜๋œ Promise๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(undefined๊ฐ€
๋ฐ˜ํ™˜๋œ/์ •์˜๋˜์ง€ ์•Š์€ ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น ํ•ญ๋ชฉ์„ ์ง์ ‘ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ˆ˜๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ ๋ฐ ๋ Œ๋”๋ง) ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•ฝ์† ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

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

โ€”
์ด ์Šค๋ ˆ๋“œ์— ๊ฐ€์ž…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/facebook/react/issues/1739#issuecomment -258198533,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/ATnWLUIEJw4m1Y3A4oGDOBzP6_ajDcqIks5q6g4_gaJpZM4CHAWq
.

@yamat124 ๋ฐ˜์‘ ์ŠคํŠธ๋ฆผ์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ด ํ”„๋กœ์ ํŠธ๋งŒ ์ฐพ์Šต๋‹ˆ๋‹ค: https://github.com/aickin/react-dom-stream

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

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

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

Next.js ์—๋Š” ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ async getInitialProps ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ์—ฌ์ „ํžˆ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฃจํŠธ๊นŒ์ง€ ๋‹ค์‹œ ์ž์‹์˜ getInitialProps ๋ฅผ ํ˜ธ์ถœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Apollo GraphQL ํด๋ผ์ด์–ธํŠธ๋Š” ๋˜ํ•œ ๋ชจ๋“  ํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜์—ฌ ์„œ๋ฒ„ ์ธก์—์„œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ˆ˜์ง‘ํ•œ ๋‹ค์Œ ๋ชจ๋“  ๊ฒƒ์„ ๋‹ค์‹œ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ + Apollo์˜ ์˜ˆ: https://github.com/sedubois/realate.

์ด๋Ÿฌํ•œ ๊ฒƒ๋“ค์„ ํ•จ๊ป˜ ๊ฒฐํ•ฉํ•˜๊ธฐ ์œ„ํ•ด ๋น„๋™๊ธฐ React ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ ์ฃผ์— SSR์— ๋Œ€ํ•ด ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์ด ์˜๋ฏธ๊ฐ€ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค ๐Ÿ˜„

/cc @nkzawa @stubailo

BTW componentWill/DidMount ๋Š” ์ด๋ฏธ ๋น„๋™๊ธฐ์‹์ž…๋‹ˆ๋‹ค. ๋„์›€์ด ๋˜๋‚˜์š”?

https://twitter.com/Vjeux/status/772202716479139840

@sedubois ๋Š” ๋ Œ๋”๋งํ•˜๊ธฐ ์ „์— React๊ฐ€ ์•ฝ์†์ด ํ•ด๊ฒฐ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค

@olalonde ๊ทธ๋ ‡๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค : https://github.com/sedubois/react-async-poc/blob/1d41b6f77e789c4e0e9623ba1c54f5ed8d6b9912/src/App.js

const getMessage = async () => new Promise((resolve) => {
  setTimeout(() => {
    resolve('Got async message!');
  }, 3000);
});
class App extends Component {
  state = {
    message: 'Loading...',
  };
  async componentWillMount() {
    this.setState({ message: await getMessage() });
  }
  render() {
    return (... {this.state.message} ...);
  }
}
loadinggot

@sedubois ๊ท€ํ•˜์˜ ์˜ˆ์—์„œ componentWillMount

  async componentWillMount() {
    this.setState({ message: await getMessage() });
  }

๋ฐ˜ํ™˜ undefined ์™€ ์•ฝ์†ํ•˜์ง€๋งŒ, ์Šคํฌ๋ฆฐ ์ƒท๋Š” ๋ Œ๋”๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์•ฝ์†์„ ์œ„ํ•ด (๊ทธ๋ ‡์ง€ ์•Š์„ ์ˆ˜)๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๋ฐ˜์ž‘์šฉ ๊ฒƒ์„ ๋ณด์—ฌ Loading... ํ…์ŠคํŠธ๋ฅผ.

์ˆ˜์ •: ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

@sedubois @polytypic ๋˜ํ•œ Promise๊ฐ€ ์ „ํ˜€ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ฐœ์ƒํ•œ ๋ชจ๋“  ์˜ค๋ฅ˜๊ฐ€ ์กฐ์šฉํžˆ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

@polytypic @dantman "์•ฝ์†์ด ์ „ํ˜€ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์Œ"์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. await ์—ฐ์‚ฐ์ž๊ฐ€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๋ฅผ ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์ œ๋ฅผ ์—…๋ฐ์ดํŠธ ํ–ˆ์Šต๋‹ˆ๋‹ค(Apollo๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ๋กœ๋”ฉ/์˜ค๋ฅ˜ ์„œ๋ช… ์‚ฌ์šฉ).

    try {
      this.setState({ message: await getMessage() });
    } catch(error) {
      this.setState({ error });
    }

๊ทธ๋ฆฌ๊ณ  ๋ Œ๋”๋ง:

{error ? error : loading ? 'Loading...' : message}
screen shot 2016-11-07 at 13 25 46

@sedubois async ํ•จ์ˆ˜๊ฐ€ ์•”์‹œ์ ์œผ๋กœ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ ํ•จ์ˆ˜์˜ ๋ชจ๋“  throw ๋Š” ์Šคํƒ์„ ๋˜์ง€๋Š” ๋Œ€์‹  ์•”์‹œ์ ์œผ๋กœ ํ•ด๋‹น ์•ฝ์†์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ componentWillMount ๊ฐ€ ์ด์ œ ํ˜ธ์ถœ์ž์—๊ฒŒ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

React๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์•„๋ฌด ์ž‘์—…๋„ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•จ์ˆ˜๋Š” ์ด์ œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜๋Š” Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ๋Œ€์‹  ๊ทธ๋ƒฅ ๋ฒ„๋ ค์ง€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ์•ฝ์†์˜ ๊ฑฐ๋ถ€๋Š” React์˜ ์–ด๋–ค ์ฝ”๋“œ์—์„œ๋„ ํฌ์ฐฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์˜ค๋ฅ˜๋Š” ์ฝ˜์†”์— ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  try..catch๋ฅผ ํ•ด๋„ ์™„๋ฒฝํ•˜๊ฒŒ ๋ณดํ˜ธ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. setState ์—์„œ catch์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ catch์—์„œ ์˜คํƒ€๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ์˜ค๋ฅ˜๊ฐ€ ์ž๋™์œผ๋กœ ์‚ฌ๋ผ์ง€๊ณ  ๋ฌด์–ธ๊ฐ€๊ฐ€ ๊นจ์กŒ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@sedubois ์‚ฌ์‹ค, ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๋Š” ํ•ญ์ƒ JavaScript(๋ฏธ๋ž˜์˜ JavaScript)์—์„œ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. C#์—์„œ async-await ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์› ์Šต๋‹ˆ๋‹ค. _์†Œ์Œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค!_

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์Šคํฌ๋ฆฐ์ƒท์€ React๊ฐ€ ์•ฝ์†์ด ํ•ด๊ฒฐ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๋ถ„๋ช…ํžˆ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. componentWillMount ํ˜ธ์ถœํ•œ ์งํ›„ render ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  Loading... ํ…์ŠคํŠธ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ setState ํ˜ธ์ถœ ํ›„ render ๋‹ค์‹œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์•ฝ์†์ด ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๋ฉด Loading... ํ…์ŠคํŠธ๋ฅผ ์ „ํ˜€ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋Œ€์‹ , ์•ฝ์†์ด ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ render ๋งŒ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง ์ค‘์— ๋น„๋™๊ธฐ IO๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ด ๋ฌธ์ œ์˜ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

@dantman @polytypic ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘ ์˜ˆ, ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์˜ค๋ฅ˜๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด React ๋‚ด๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ์— ์—ฌ๊ธฐ ์ €๊ธฐ์— await ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ˜„

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

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ๋ฉ”์‹œ์ง€๊ฐ€ ์ค‘๊ฐ„ "๋กœ๋“œ ์ค‘" ์ƒํƒœ์ธ ๊ฒฝ์šฐ์—๋„ ๋น„๋™๊ธฐ ๊ตฌ์„ฑ ์š”์†Œ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„์š” ์—†์ด ์ •์  ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์— ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@sedubois ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ ์Šคํƒ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ. React์˜ ํ˜„์žฌ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•์€ ๋™๊ธฐํ™”์ด๋ฏ€๋กœ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‹ค๋ฅธ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

@dantman ๋‚˜๋Š” ์ด ๋ฌผ์ด ๋‚˜์—๊ฒŒ ๋„ˆ๋ฌด ๊นŠ๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์— ์–ด๋–ค ์˜๊ฒฌ๋„ ์ œ์‹œํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๋‚ด ์ดˆ๊ธฐ ๋ชฉํ‘œ๋Š” Vjeux์˜ async componentWillMount ํ•ดํ‚น์„ ์ง€์ ํ•˜๋Š” ๊ฒƒ๋ฟ์ด์—ˆ์Šต๋‹ˆ๋‹ค...), ํ•˜์ง€๋งŒ ํ , React๋Š” ๋‹ค์Œ ์œ ํ˜•์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด์ด๊ณ  ์•ฝ์†์ธ ๊ฒฝ์šฐ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ(ํ˜„์žฌ, ์ฆ‰ ์ด์ „ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๋Š” ๋ฐฉ์‹์œผ๋กœ)?

@fkrauthan์ด ์ œ์•ˆํ•œ ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ผ๋ฏธ์Šค ๋˜๋Š” undefined ๋ฐ ์ถ”๊ฐ€ ๋น„๋™๊ธฐ renderToStringAsync ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ load . ๊ทธ๋Ÿฌ๋‚˜ load ๋Š” ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์—์„œ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. render ๋˜๋Š” renderToString ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฐ˜ํ™˜๋œ ์•ฝ์†์€ ์˜ค๋Š˜๋‚ ์˜ ๋™์ž‘๊ณผ ์ผ์น˜ํ•˜๋„๋ก ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. renderToStringAsync ํ•˜๊ณ  load ๊ฐ€ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ Œ๋”๋ง ์ „์— ์•ฝ์†์„ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Next.js ์ฒ˜๋Ÿผ ์ƒ์„ฑ์ž๋ณด๋‹ค ๋จผ์ € ํ˜ธ์ถœ๋˜๋Š” React async getInitialProps ์ˆ˜๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์œผ๋ฉด ์ƒ์„ฑ์ž๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {});
...
const app = createElement(App, {
  Component,
  props,
  ...
});

Next.js์˜ getInitialProps ๊ฐ€ React ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜๋ช… ์ฃผ๊ธฐ์— ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์•„ ์ตœ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๋ฉด Next.js๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ๊ณ  ๊ทธ๋ƒฅ ํ•จ๊ป˜ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@sedubois getInitialProps๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์žฅ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„  ES6์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ ๊ทธ ๋ฐฉ๋ฒ•์ด ์—†๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ๋กœ initalProps + props์— ์ „๋‹ฌ๋œ initalProps ๋ณ‘ํ•ฉ ์œ„์— ์ž‘์—…ํ•˜๋ ค๋Š” initalProps(๊ธฐ๋ณธ๊ฐ’์ผ ๋ฟ)์—์„œ ์ž‘์—…ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ componentWillMount ์ „์— ์ „๋‹ฌ๋˜๋Š” ์ƒˆ๋กœ์šด ์ˆ˜๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

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

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

ES6์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ ๊ทธ ๋ฐฉ๋ฒ•์ด ์—†๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@fkrauthan ์•„๋งˆ๋„ getInitialState ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์—ฌ๊ธฐ์„œ ์ €๋Š” ์ƒˆ๋กœ์šด getInitialProps (Next.js์—์„œ ์‚ฌ์šฉ๋œ ์ด๋ฆ„)์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์š”์ ์€ ์˜ˆ, constructor ์ด์ „๋ณด๋‹ค componentWillMount ์ด์ „์— ์ƒˆ ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์— ์–ธ๊ธ‰ํ•œ ๋Œ€๋กœ React ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์น˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— Next์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ React ๋‚ด์—์„œ ์ด๋Ÿฌํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

@sedubois ๊ทธ๊ฒƒ๋„ . ์˜ˆ๋ฅผ ๋“ค์–ด es7 ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ  ํด๋ž˜์Šค ๋ณธ๋ฌธ์— static props = {}; ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ œ ์ƒ๊ฐ์—๋Š” ์ฝ”๋“œ๋ฅผ ๋” ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ es7์ด ๊ณต์‹์ ์œผ๋กœ ์ถœ์‹œ๋˜์ž๋งˆ์ž ์ ์  ๋” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ด ์ฝ”๋“œ๋กœ ์ „ํ™˜ํ•  ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ : ํด๋ž˜์Šค ์†์„ฑ์€ "ES7" ๊ธฐ๋Šฅ์ด ์•„๋‹™๋‹ˆ๋‹ค. ES7์ด ์ด๋ฏธ ์™„์„ฑ๋˜์—ˆ์œผ๋ฉฐ ์ง€์ˆ˜ ์—ฐ์‚ฐ์ž๋งŒ ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ์–ธ์–ด ๊ธฐ๋Šฅ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๋งํ•˜๋Š” ๊ฒƒ์€ 2๋‹จ๊ณ„ ํด๋ž˜์Šค ์†์„ฑ ์ œ์•ˆ ์ž…๋‹ˆ๋‹ค. ์•„์ง ์–ธ์–ด์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฉฐ ๋ณ€๊ฒฝ๋˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ด์ „์— ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ ์ข‹์€ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์ด์ „์— ์ œ์•ˆํ•œ ๋‚ด์šฉ์„ ์•ฝ๊ฐ„ ์—…๋ฐ์ดํŠธํ•จ).

const virtualTree = ReactDOM.renderVirtual(rootEle);

// get the bundled query from redux store for example
const bundle = store.getState().bundle;

// Fetch the data according to the bundle
const data = await fetchDataSomehow(bundle);

// hydrate store (this will set updates on the virtual tree)
store.dispatch({type: 'hydrate', data});

// final result
const domString = virtualTree.renderToString();

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

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

@fkrauthan ๋„ค, ํ•˜์ง€๋งŒ ๊ฐ€์ƒ ๋ Œ๋”๋Š” ๋ฌธ์ž์—ด์— 2๊ฐœ์˜ ๋ Œ๋”๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋” ์„ฑ๋Šฅ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ œ ์ƒ๊ฐ์—๋Š” ์—ฌ๊ธฐ์—์„œ ์ฃผ์š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค(SSR์˜ ์„ฑ๋Šฅ). React์˜ ์•ฝํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋ฐ˜์‘์˜ renderToString ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์‹คํ—˜์ด ์žˆ์—ˆ์ง€๋งŒ ๋ฐ˜์‘ ํŒ€์—์„œ ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ์‹ค์งˆ์ ์ธ ์ง„์ „์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค(์—ฌ๊ธฐ์„œ ๋น„ํŒํ•˜์ง€ ์•Š๊ณ  ๋†€๋ผ์šด ์ผ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค).

๋‚˜๋Š” @bruno12mota ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด์„œ๋„ ์ž ์‹œ ๋™์•ˆ ์ˆ™๊ณ ํ•œ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋ Œ๋”๋ง์ด "ํ”Œ๋Ÿฌ์‹œ"๋˜์–ด์•ผ ํ•˜๋Š” ์‹œ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ž์œ ๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ๋ชจ๋“  ๊ฒƒ์„ ํ›จ์”ฌ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

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

@bruno12mota ์™€ ํ•จ๊ป˜ ํ•ฉ๋‹ˆ๋‹ค. VDom์€ ํ‹€๋ฆผ์—†์ด ๋” "์ €์ˆ˜์ค€" ์†”๋ฃจ์…˜์ด์ง€๋งŒ React ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฌ์šฐ๋ฉฐ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ์—†์œผ๋ฉฐ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋‹ค๋ฅธ ๋” ๋†’์€ ์ˆ˜์ค€์˜ ์†”๋ฃจ์…˜์„ ์‹คํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ˜„์žฌ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, getInitialState, componentWillMount ๋˜๋Š” renderToString์ด ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

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

react-dom/server์— "renderToStringAsync" ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜ renderToString๊ณผ์˜ ์ฐจ์ด์ ์€ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ตฌํ˜„ ์ธก๋ฉด์—์„œ ์œ ์ผํ•œ ์ฐจ์ด์ ์€ ๋น„๋™๊ธฐ ๋ฒ„์ „์ด Component ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค render()๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ๋จผ์ € "initialize()"๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๋Œ€๊ธฐํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ์— "์ดˆ๊ธฐํ™”" ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์œผ๋ฉด ์ฆ‰์‹œ render()๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‹ค์Œ ์˜ˆ์ œ ์•ฑ ๊ตฌ์กฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ:

    ComponentB
    ComponentC
        ComponentD
        ComponentE

ํ”„๋กœ์„ธ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1) instanciate componentA
2) await componentA.initialize();
3) componentA.render()
4) do in parallel(
    instanciate componentB, await componentB.initialize(), componentB.render()
    instanciate componentC, await componentC.initialize(), componentC.render(), do in parallel(
        instanciate componentD, await componentD.initialize(), componentD.render()
        instanciate componentE, await componentE.initialize(), componentE.render()
    )
)
5) render to string

๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒˆ๋กœ์šด ์„ ํƒ์  ๊ธฐ๋Šฅ์ธ "initialize"๋ฅผ ์‚ฌ์šฉํ•˜๋Š” "renderToStringAsync"๋ผ๋Š” ์ƒˆ ๊ธฐ๋Šฅ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@VanCoding ์€ ๋‚ด๊ฐ€ ์ž ์‹œ ๋™์•ˆ ์ƒ๊ฐํ–ˆ๋˜ ๊ฒƒ๊ณผ ๊ฐ™์€ ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์˜ componentDidMount์—์„œ initialize๊ฐ€ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋  ์ˆ˜๋„ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์„œ๋ฒ„์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

initialize()
render()

ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

render() // without data (unless available synchronously)
componentDidMount()
initialize()
render() // with data

react-router v4๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜์‘ ์„œ๋ฒ„ ๋ Œ๋”๋ง์„ ๊ตฌํ˜„ํ•˜๊ณ  GraphQL์„ ์‚ฌ์šฉํ•˜์—ฌ react-apollo๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ server-side-rendering-code-splitting-and-hot-reloading-with-react-router ์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

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

๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ  ์„œ๋ฒ„ ๋ Œ๋”๋ง์€ Nashorn ์Šคํฌ๋ฆฝํŠธ ์—”์ง„(JVM)์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”๋ง ์ฝ”๋“œ
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/main.js#L63 -L82

์„œ๋ฒ„ ๋ Œ๋”๋ง ์ฝ”๋“œ
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/main.js#L128 -L155

๊ฒฝ๋กœ์—์„œ ๋™๊ธฐํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋น„๋™๊ธฐํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ๋ณ„ํ•˜๋Š” ์ค‘์š”ํ•œ ์œ„์น˜๊ฐ€ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค.
Route์˜ ๋™๊ธฐํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/routes/Counter/Route.js#L10

RouteAsync์˜ ๋™๊ธฐํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/routes/Counter/RouteAsync.js#L7 -L23

์ฐธ๊ณ : ํŒŒ์ผ ์ด๋ฆ„์€ Route.js ๋˜๋Š” RouteAsync.js์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ํ•ญ์ƒ RouteAsync.js๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. Webpack์€ ์„œ๋ฒ„ ๋ Œ๋”๋ง์šฉ์œผ๋กœ ๋นŒ๋“œ๋œ ๊ฒฝ์šฐ ์ด๋ฅผ Route.js๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/build/webpack.config.js#L72 -L80

๋”ฐ๋ผ์„œ dist ๋ฐ dist_ssr ๋นŒ๋“œ์˜ ๋‘ ๊ฐ€์ง€ ๋ฒ„์ „์ด ์žˆ์Šต๋‹ˆ๋‹ค. dist ๋Š” ํด๋ผ์ด์–ธํŠธ์šฉ์ด๊ณ  dist_ssr ๋Š” ๊ณต๊ธ‰์—…์ฒด์™€ ์•ฑ์˜ ๋‘ ์ฒญํฌ๋งŒ ์žˆ๋Š” ์„œ๋ฒ„์šฉ์ž…๋‹ˆ๋‹ค. . ์ƒ์  ์ƒํƒœ๋Š” index.html์˜ <script> ์— __INITIAL_STATE__ ๋กœ ๋‚ด๋ณด๋‚ด์ง€๊ณ  ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ๋ฒ„์ „์˜ ๋นŒ๋“œ๊ฐ€ ์žˆ๋Š” ์ด์œ ๋Š” ReactDomServer.renderToString() ๊ฐ€ ์•„์ง ๋น„๋™๊ธฐ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‘ ๊ฐ€์ง€ ๋ฒ„์ „ ๋นŒ๋“œ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์œ ์ผํ•œ ๋ฌธ์ œ๋Š” ๊ฐœ๋ฐœ ๋ชจ๋“œ์— ๊ฒฝ๊ณ ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:

๊ทธ๋Ÿฌ๋‚˜ ํด๋ผ์ด์–ธํŠธ ๋ฒ„์ „๊ณผ ์„œ๋ฒ„ ๋ฒ„์ „์˜ ์ฐจ์ด์ ์€ Route.js์™€ RouteAsync.js๋ฟ์ด๋ฏ€๋กœ ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ์—์„œ๋Š” ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์ธก์—์„œ ๊ตฌ์„ฑ ์š”์†Œ ๋ Œ๋”๋ง ์ „์— ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์˜ ๊ฒฝ์šฐ:

  • Rest API: ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ์— ์ •์  loadData ์ถ”๊ฐ€
const { matchedRoutes, params } = matchRoutesToLocation(rootRoute.routes, 
                                                        location, [], {}, rootRoute.pattern)
matchedRoutes.filter(route => route.component.loadData).map(route =>
              route.component.loadData(store, params))

loadData ๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. MatchedRoutes๋Š” ๋ถ€๋ชจ๊ฐ€ 0 ์ธ๋ฑ์Šค์— ์žˆ๋Š” ์ผ์น˜ํ•˜๋Š” ๊ฒฝ๋กœ์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. loadData ๋Š” ์ˆœ์ฐจ์ ์œผ๋กœ ๋˜๋Š” ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • GraphQL ์ฟผ๋ฆฌ: getDataFromTree ์—์„œ react-apollo/server ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  GraphQL ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

BTW: Nashorn Script Engine์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•œ ๊ฐ€์ง€ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐํšŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณต๊ธ‰์—…์ฒด์—๋Š” ํ•œ ๋ฒˆ ์‹คํ–‰๋˜๊ณ  ์žฌ์‚ฌ์šฉ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ์™€ ํด๋ฆฌํ•„์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ดํ›„ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ์•ฑ ์ฒญํฌ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฒค๋” ์ฒญํฌ๋กœ ์ด๋™๋˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์€ src์— ์ž‘์€ ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋งŒ ํฌํ•จํ•˜๋ฏ€๋กœ ๋งค๋ฒˆ ๋ฒค๋” ์ฒญํฌ๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋น„ํ•ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. (๋ชจ๋“  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ•œ ๋ฒˆ ์ปดํŒŒ์ผ๋˜๊ณ  ์บ์‹œ๋˜์–ด ๋ชจ๋“  ์š”์ฒญ์— โ€‹โ€‹๋Œ€ํ•ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.)

์•ฑ ์ฒญํฌ์—๋Š” src ์ฝ”๋“œ๋งŒ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฑฐ์ง“๋ง์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ babel-runtime ๋ฐ core-js/library ์ฐธ์กฐํ•˜๋Š” ๋ณต์ œ๋œ babel-runtime ํ•ฉ๋‹ˆ๋‹ค. babel-runtime ๋Š” index.js ๋˜๋Š” ๊ธฐ๋ณธ ํ•ญ๋ชฉ์ด ์—†์œผ๋ฏ€๋กœ webpack์ด ๋ชจ๋“ˆ๋กœ ์ธ์‹ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ธ‰์—…์ฒด ์ฒญํฌ๋กœ ์ด๋™ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฝ”๋“œ ํฌ๊ธฐ๋Š” ์ž‘์Šต๋‹ˆ๋‹ค.

@VanCoding ์˜ ์˜ˆ๋ฅผ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. https://github.com/facebook/react/issues/1739#issuecomment -261577586

initialize๋Š” ์ข‹์€ ์ด๋ฆ„์ด ์•„๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์€ ์„œ๋ฒ„์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๊ฑฐ๋‚˜ ์ด ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋  ๋•Œ๊นŒ์ง€ ๋ Œ๋”๋ง์ด ์ง€์—ฐ๋˜๋Š” ํ™˜๊ฒฝ(์ผ๋ช… ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ)์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋„๋ก ์˜๋„๋˜์—ˆ์Œ์„ ๋ถ„๋ช…ํžˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„์ด๋””์–ด: getStaticProps , getServerProps , getInitialProps , getAsyncProps ...

๋˜ํ•œ ์ด๋Ÿฌํ•œ renderToStringAsync ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ๊ธฐ์ˆ ์ ์ธ ๋˜๋Š” ๋‹ค๋ฅธ ์žฅ์• ๋ฌผ์ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ•ต์‹ฌ ํŒ€์—์„œ ๋“ฃ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

@nmaro ๊ธ€์Ž„์š”, ํ•จ์ˆ˜๋Š” ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ "get"์œผ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ์ด๋ฆ„์„ ์„ ํ˜ธํ•˜์ง€๋งŒ ์ด๊ฒƒ ์™ธ์—๋Š” ์—ฌ์ „ํžˆ ์ด๊ฒƒ์ด ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๊ฒฐ๊ตญ ์–ด๋–ป๊ฒŒ ๋ถˆ๋ฆฌ๋Š”์ง€ ์ƒ๊ด€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ ์•ฝ 40์ค„์˜ ์ฝ”๋“œ๋กœ ์ด์— ๋Œ€ํ•œ ๊ฐœ๋… ์ฆ๋ช…์„ ์ˆ˜ํ–‰

๋”ฐ๋ผ์„œ ๋ฐ˜์‘ ํŒ€์ด ์—ฌ์ „ํžˆ ์ด๊ฒƒ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด renderToString์— ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
renderToString(Component, {async: true})

@nmaro ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ œ๊ณต๋œ ์˜ต์…˜์— ๋”ฐ๋ผ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์ด ๋‹ฌ๋ผ์ง€๋Š”๋ฐ, ์ด๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์œ ํ˜•์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@VanCoding ์ฝ”๋“œ ๋ฅผ ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@VanCoding ๋ฉ‹์ง€๋‹ค! ํ•˜์ง€๋งŒ ์†”์งํžˆ ๋ฐ˜์‘์˜ ๋‚ด๋ถ€ ๋ Œ๋”๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๊ทธ๊ฒƒ์„ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ค์šธ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. https://github.com/facebook/react/blob/master/src/renderers/dom/stack/server/ReactServerRendering.js๋ฅผ ํ™•์ธํ•˜๊ณ  ๋ฐ˜์‘์˜ ๋‚ด๋ถ€์—์„œ ๊ธธ์„ ์žƒ์Šต๋‹ˆ๋‹ค... IMO์—์„œ ๋ˆ„๊ตฐ๊ฐ€์˜ ์˜๊ฒฌ์ด ์ •๋ง ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•ต์‹ฌ.

@sedubois ์ผ๋ฐ˜ renderToString ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฌธ์ž์—ด์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ๋ฌธ์ž์—ด๋กœ ํ™•์ธ๋˜๋Š” Promise๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var react = require("react");
var renderAsync = require("react-render-async");
var MyComponent = require("./MyComponent");

renderAsync(react.createElement(MyComponent,{some:"props"}).then(function(html){
    console.log(html);
});

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

@nmaro ๋งž์Šต๋‹ˆ๋‹ค. ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ์ƒํƒœ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@firasdib ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ์ผ๋ถ€ ๋ฐ˜์‘ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๊ฒฌ์„ ์ œ์‹œํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

+1

Google ์ธ๋ฑ์‹ฑ ๋ฌธ์ œ๋Š” SSR์„ ์š”๊ตฌํ•˜๋ฉฐ ์•„๋ž˜์— ์„ค๋ช…๋œ ๋ชจ๋“  ์ง์€ ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด ๋ฌธ์ œ๋Š” React๊ฐ€ ์ผ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์„ฑ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

JavaScript๊ฐ€ Promise๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ–ˆ๋‹ค๋ฉด ์ „์ฒด ๋น„๋™๊ธฐ ๋ Œ๋”๋ง์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚ ์”จ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋กœ๋“œ๋ฅผ ๋™๊ธฐ์‹(SSR์˜ ๊ฒฝ์šฐ) ๋˜๋Š” ๋น„๋™๊ธฐ์‹(์‹ค์ œ ์›น ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฒฝ์šฐ)์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋กœ์ง์€ ๋ชจ๋“  โ€‹โ€‹React ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒ์„ฑ์ž์—์„œ ์•ฝ์†์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๊ณ  componentWillMount์—์„œ ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๊ฐ€ ์ดํ•ดํ•˜๋Š” ๋ฐ”์™€ ๊ฐ™์ด React ๊ฐœ๋ฐœ์ž๋Š” componentWillMount์˜ ์œ ์šฉ์„ฑ์— ์˜์‹ฌ์„ ํ‘œ์‹œํ•˜๊ณ  ์ƒ์„ฑ์ž๊ฐ€ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๊ถŒ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋Š ์ชฝ์ด๋“  ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

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

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

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

  • DOMtree๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค. ๋ถˆ์•ˆ์ •ํ•œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ƒํƒœ์—์„œ ์•ˆ์ •์ ์ธ "๋กœ๋“œ" ์ƒํƒœ๋กœ "์•ˆ์ฐฉ"ํ•˜๋Š” ๋ผ์ด๋ธŒ ์‹œ์Šคํ…œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ์‹œ์Šคํ…œ์ด ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š” ์‹œ์Šคํ…œ์—์„œ ์•ˆ์ •์ ์ธ "๋กœ๋“œ" ์ƒํƒœ์— ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ํƒ€์ž„์•„์›ƒ์„ ๋„์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ ๋น ๋ฅด์ง€ ์•Š์€ ํ”„๋กœ์„ธ์Šค๋กœ ์„œ๋ฒ„ ์ธก์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ›จ์”ฌ ๋” "์ง‘์ค‘์ ์œผ๋กœ" ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์ผ์„ ๋๋‚ด๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ๋ฅผ ์†์ƒ์‹œํ‚ฌ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. :)

๊ทธ ๋™์•ˆ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํ™˜๊ฒฝ์—์„œ SSR์„ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋ฐ์ดํ„ฐ ๋กœ๋“œ ํ˜ธ์ถœ์€ ์š”์ฒญ URL์—์„œ ํŒŒ์ƒ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: react-router). ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์•ฝ์†์„ ๋‹จ์ผ ์•ฝ์† ๋ชฉ๋ก์œผ๋กœ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ทธ ์ž์ฒด๊ฐ€ ์•ฝ์†์ธ Promise.all()์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์ด ์•ฝ์†์ด ์™„๋ฃŒ๋˜๋ฉด ๋กœ๋“œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๊ธฐ๋Šฅ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ชจ๋ธ์€ ํŠน์ • ๋””์ž์ธ ์•„ํ‚คํ…์ฒ˜์— ์–ฝ๋งค์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ”Œ๋Ÿญ์Šค/๋ฆฌ๋•์Šค๊ฐ€ ์•ฝ๊ฐ„ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฆฌ๋•์Šค ๋ชจ๋ธ์„ ํฌ๊ธฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ๋ชจ๋ธ์˜ ๋ฌธ์ œ๋Š” ์œ„์˜ ํ•ญ๋ชฉ #1์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํ˜ธ์ถœ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋…๋ฆฝ์ ์ธ "๋ชจ๋“ˆ"์ด ์žˆ๋Š” ๋ณต์žกํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด ๋ชจ๋ธ์€ ์›๋ž˜ React ๊ตฌ์„ฑ ์š”์†Œ ํŠธ๋ฆฌ์™€ ๋ Œ๋”๋ง ๋…ผ๋ฆฌ์˜ ์ผ์ข…์˜ ๋ณต์ œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

render() ํ•จ์ˆ˜์— ์ด๋ฏธ ์ž‘์„ฑ๋œ ๋…ผ๋ฆฌ๋ฅผ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๊ณ  ๋ณต์žกํ•œ ํ”„๋กœ์ ํŠธ์—์„œ SSR์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. Flux๊ฐ€ ํ•ด๊ฒฐ์ฑ…์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฒฝํ—˜์ด ์—†์–ด์„œ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•ญ๋ชฉ #1 ๊ตฌํ˜„์ด ๋ชจํ˜ธํ•ฉ๋‹ˆ๋‹ค. react-router ์˜ˆ์ œ์—์„œ ์šฐ๋ฆฌ๋Š” ๋ผ์šฐํ„ฐ๋กœ ํ•ด๋‹น ๊ฒฝ๋กœ์— ์†ํ•œ ์ตœ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

app.use(function(req, res, next) {
    match({ routes, location: req.url }, (error, redirectLocation, renderProps: any) => {
    if (error) {
        res.status(500).send(error.message)
    } else if (redirectLocation) {
        res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
        // You can also check renderProps.components or renderProps.routes for
        // your "not found" component or route respectively, and send a 404 as
        // below, if you're using a catch-all route.
        console.log("renderProps", renderProps)
        for (let eachComp of renderProps.components) {
            // create an instance of component
            // ask component to load its data
            // store data loading promise in a collection
            console.log("eachComp: ", eachComp)
        }
        res.status(200).send(renderToString(<RouterContext {...renderProps} />))
        } else {
        res.status(404).send('Not found')
        }
    })
});

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

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

๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ๋ณด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ SSR์˜ ์˜๋ฏธ๋ฅผ ๊นจ๋‹ฌ์•˜๋‹ค๋ฉด Google ์ธ๋ฑ์‹ฑ ๊ฐ€๋Šฅํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ React์˜ ์œ ์šฉ์„ฑ์— ๋Œ€ํ•ด ๋‘ ๋ฒˆ ์ƒ๊ฐํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ํ”Œ๋Ÿญ์Šค๊ฐ€ ์†”๋ฃจ์…˜์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ํ”Œ๋Ÿญ์Šค๋Š” ๋‹จ์ˆœํ•œ React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋ณด๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ „์ฒด ์ˆ˜์ค€์œผ๋กœ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋‚œ ๊ฑฐ๊ธฐ์— ๊ฐ€๋ณธ ์ ์žˆ์–ด. ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๊ธฐ๋Šฅ ๋Œ€์‹  ์—ฌ๋Ÿฌ ํŒŒ์ผ์—์„œ ๋‚ด ๋…ผ๋ฆฌ๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ก ์ ์ธ ์ˆ˜์ค€์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์ •๋ง ์ข‹์•„ ๋ณด์˜€์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์‚ฌ๋žŒ๋“ค์€ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ ๊ธฐ๋ฐ˜์—์„œ redux๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„์—๋Š” ๊ทธ๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  UI ๋””์ž์ธ์˜ ๋ณต์žก์„ฑ์— ๋Œ€ํ•œ ๋‹ต์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค :)

์ด๋ฒˆ ์ฃผ React Conf ์—์„œ React Fiber(React 16)๊ฐ€ ๋‚˜์˜จ ํ›„ ๋‹ค์Œ ์ž‘์—…์„ ๊ณ„ํšํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(React 17๋กœ ์ถ”์ •).

screen shot 2017-03-16 at 15 55 51

๋น„๋™๊ธฐ React ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ฌ ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

๊ธ€์Ž„, ์„ฌ์œ  ์žฌ๋ฃŒ๋Š” ๋Œ€๋ถ€๋ถ„ ๋” ๋น ๋ฅด๊ณ  ๋ถ€๋“œ๋Ÿฌ์šด ์žฌ ๋ Œ๋”๋ง์— ๊ด€ํ•œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๊นŒ? ์„œ๋ฒ„์—์„œ๋Š” ํ•œ ๋ฒˆ๋งŒ ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์— ์˜ํ–ฅ์„ ๋ฏธ์น ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@VanCoding ์€ ์•ฝ๊ฐ„ ๋ถˆ๋ถ„๋ช…ํ•œ ์œ„์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์„ฌ์œ ๊ฐ€ ๋Š๊ธด ์ดํ›„์— ๋Œ€ํ•œ ๊ทธ๋“ค์˜ ๊ณ„ํš์„ ์˜๋ฏธํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜์ฒ˜๋Ÿผ ์—ฌ๊ธฐ์— ๋„์ฐฉํ•œ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜์‘์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌํ˜„์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

https://github.com/siddharthkp/reaqt

ํ‚ค๋Š” ์„œ๋ฒ„์—์„œ๋งŒ ์‹คํ–‰๋˜๋Š” asyncComponentWillMount์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์–ธ๊ธ‰๋œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ง„์ž…์  ๊ตฌ์„ฑ ์š”์†Œ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@siddharthkp ๊ท€ํ•˜์˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์ •๋ง๋กœ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ? ์ตœ์ƒ์œ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ React ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด asyncComponentWillMount๋งŒ ์ง€์›ํ•œ๋‹ค๋ฉด ์™œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์™ธ๋ถ€์—์„œ ๊ทธ ์•ฝ์†์„ ํ•ด๊ฒฐํ•œ ๋‹ค์Œ render๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ๋†“์ณค๋‚˜์š”?

@fkrauthan

์™ธ๋ถ€์—์„œ ๊ทธ ์•ฝ์†์„ ํ•ด๊ฒฐํ•œ ๋‹ค์Œ render๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์ •ํ™•ํžˆ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

๋งค๋ ฅ์€ ํ•˜๋‚˜์˜ ๋ช…๋ น์œผ๋กœ ๋น„๋™๊ธฐ ssr(+ ์ฝ”๋“œ ๋ถ„ํ•  + hmr)์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ssr์ด ์‰ฝ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š” ์‚ฌ๋žŒ๋“ค์„ ๋งŽ์ด ๋ณด์•˜๊ณ  ๊ทธ๊ฒƒ์ด ๋™๊ธฐ์˜€์Šต๋‹ˆ๋‹ค.

์ตœ์ƒ์œ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ React ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด์„œ๋งŒ asyncComponentWillMount๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  1. ํ•˜๋‚˜์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€/ํ™”๋ฉด/์ง„์ž…์ ๋ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ( ์—ฌ๊ธฐ์„œ ์—ฌ๋Ÿฌ ์ง„์ž…์ ์„ ํ™๋ณด)

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

@siddharthkp ๊ท€ํ•˜์˜ repo๋Š” Next.js(React Conf BTW์—์„œ๋„ ๋ฐœํ‘œ๋จ)๋ณด๋‹ค ์–ด๋–ป๊ฒŒ ํ–ฅ์ƒ๋ฉ๋‹ˆ๊นŒ?

https://github.com/zeit/next.js

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

ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ๋…ผ์˜๋Š” ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚œ IMHO์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๊ฐ–๋Š” ๊ฒƒ์€ React ์ž์ฒด ๋‚ด์—์„œ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์™„์ „ํžˆ ๋™์˜ ํ•ด. reaqt ๋ฌธ์ œ์˜ ํŠน์ • ์งˆ๋ฌธ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•  ์ˆ˜

์ด์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” react-native ๋ฐ react-native-vector-icons๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” Promise์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ์— ์˜ํ•ด ์ปดํฌ๋„ŒํŠธ์˜ prop์ด ๊ฒฐ์ •๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

const AsyncUser = props => fetchUser()
  .then(data => (
     <User {...data} />
   ))

์ง€์›๋œ๋‹ค๋ฉด ๋งŽ์€ ๋ณต์žกํ•œ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ณ  ์ƒˆ๋กœ์šด ๋น„๋™๊ธฐ ํŒจํ„ด์„ ์—ด ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ssr์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ธก ์†Œํ’ˆ์„ ๊ฒ€์ƒ‰ํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ componentWillMount์—์„œ ์ž‘์—…์œผ๋กœ ๊ฐ€์ ธ์˜จ ์ฝ˜ํ…์ธ ๋„ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์†Œํ’ˆ์ด ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์†Œํ’ˆ์„ ๋ฌธ์ž์—ด๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

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

์ด ํ•จ์ˆ˜๋Š” ์„œ๋ฒ„ ๋ Œ๋”์—์„œ '๋™๊ธฐ์ ์œผ๋กœ' ์‹คํ–‰๋˜์ง€๋งŒ(์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Œ ;-) ์ตœ์ข… ๊ตฌ์„ฑ ์š”์†Œ ๋ Œ๋”๋Š” ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ์ฐจ๋‹จ๋˜๊ณ  ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”์—์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ ํŽ˜์ด์ง€๊ฐ€ ๋ฐฉ๊ธˆ ์‹คํ–‰๋œ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋‹ค์‹œ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋ Œ๋”๋ง. ๋˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ณ„๋กœ ์‹คํ–‰ ์‹œ์ ์„ ๋ณด๋‹ค ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ๋” ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋กœ๋”ฉ์— ์ •๋ง ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ ๊ฑฐ์˜ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ๋ฐ–์œผ๋กœ ์‹œ๋„! ๐Ÿ˜„

https://github.com/davnicwil/react-frontload

<AsyncComponent 
  delayRendering={LoadingComponent}
> 
   {/*return a promise that returns a component here*/}
</AsyncComponent>

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

์ด์— ๋™์ฐธํ•ฉ๋‹ˆ๋‹ค. ์•„์ง๊นŒ์ง€๋Š” React์— ๋ถ€์กฑํ•œ ํ•„์ˆ˜ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ด ์ฃผ์ œ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋”๋ผ๋„ ์ด๋Š” ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ตฌํ˜„์„ ์ƒ๊ฐํ•ด ๋ƒˆ์Šต๋‹ˆ๋‹ค. https://github.com/timurtu/react-render-async

์•„์ฃผ ์ข‹์€ ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ ์ธํ„ฐํŽ˜์ด์Šค, @timurtu.

...์—ฌ๋Ÿฌ๋ถ„, ์ด ์Šค๋ ˆ๋“œ์™€ ๋งค์šฐ ์ง์ ‘์ ์ธ ๊ด€๋ จ์ด ์žˆ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‚ฌํ•ญ์ด ์žˆ์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์— ์ฐธ์—ฌํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์˜ค๋žซ๋™์•ˆ ์ด ์Šค๋ ˆ๋“œ๋ฅผ ์ถ”์ ํ•ด ์™”์Šต๋‹ˆ๋‹ค.

  • ํ•˜๋‚˜๋Š” SSR์„ ๊ณ ๋ คํ•  ๋•Œ ๊ฒฝ๋กœ ์ˆ˜์ค€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๊ฐ€์žฅ ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    Redux-First Router ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ: ๋น„๋™๊ธฐ ๋ฏธ๋“ค์›จ์–ด์˜ 80% ์‚ฌ์šฉ ์‚ฌ๋ก€ ํ•ด๊ฒฐ
  • Redux๋ฅผ ์‚ฌ์šฉํ•œ ์„œ๋ฒ„ ๋ Œ๋”๋ง์€ ์ด์ œ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ๋ณธ ์ ์ด ์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ Redux-First Router ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. 10๋‹จ๊ณ„์˜ Pro /w Redux-First Router์™€ ๊ฐ™์€ ์„œ๋ฒ„ ๋ Œ๋”๋ง
  • ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฝ”๋“œ ๋ถ„ํ• ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‘˜ ๋‹ค ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: SSR + ๋ถ„ํ• ) . ๋‘ ๊ฐ€์ง€๋ฅผ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ฃผ์š” ๊ณจ์นซ๊ฑฐ๋ฆฌ ์˜€์œผ๋ฉฐ, ์†Œ์ˆ˜์— ์˜ํ•ด ์„ฑ๊ณต์ ์œผ๋กœ ๋‹ฌ์„ฑ๋˜์—ˆ์œผ๋ฉฐ ์ง€๊ธˆ๊นŒ์ง€ ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ๋•๊ธฐ ์œ„ํ•œ ์ผ๋ฐ˜ ํŒจํ‚ค์ง€๋ฅผ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. React Universal Component + babel-plugin-universal-import + webpack-flush-chunks (๋ฐ extract-css-chunks-webpack-plugin )๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์‹ค์ œ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ํŒจํ‚ค์ง€ ์ œํ’ˆ๊ตฐ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฒ˜์Œ์œผ๋กœ. ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ฒ„์—์„œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋™๊ธฐ์‹์œผ๋กœ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ดˆ๊ธฐ ๋™๊ธฐ์‹ ๋ Œ๋”๋ง์„ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ๋กœ ๋ Œ๋”๋ง๋œ ์ •ํ™•ํ•œ ์ฒญํฌ๋ฅผ ์ „์†กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. webpack ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ†ตํ•ด CSS ์ฒญํฌ ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ @timurtu๊ฐ€ ๊ณต์œ ํ•œ ๊ฒƒ๊ณผ main.js ๋กœ๋“œ, ๊ตฌ๋ฌธ ๋ถ„์„, ํ‰๊ฐ€, ๋ Œ๋”๋ง ๋ฐ ๋ช‡ ์ดˆ ํ›„์— ๋™์  ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์š”์ฒญํ•ด์•ผ ํ•˜๋Š” ๋งŽ์€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ด๋“ค์€ ์Šคํƒ€์ผ์ด ์ง€์ •๋˜์ง€ ์•Š์€ ์ฝ˜ํ…์ธ ์˜ ํ”Œ๋ž˜์‹œ(FOUC)๋ฅผ ํ•ด๊ฒฐํ•˜์ง€๋งŒ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ ์ •ํ™•ํ•œ ์ฒญํฌ๋ฅผ ํŽ˜์ด์ง€์— ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. Universal( ๋‚ด ํŒจํ‚ค์ง€ ์ œํ’ˆ๊ตฐ์˜ ์ด๋ฆ„)์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด ์›น์•ฑ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๋Š” ๋™๊ธฐ์‹ ๋ฐฉ์‹์œผ๋กœ TTI(Time to Interactive) ๋ฅผ ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React Universal Component 2.0 & babel-plugin-universal-import ์—์„œ ์ด์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฝ๋กœ ์ˆ˜์ค€ ๋Œ€ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€ ์žฅ๋‹จ์ ์„ ๋‹ค๋ฃจ์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ ์ฒซ ๋ฒˆ์งธ ๋งํฌ๋Š” ์ฃผ๋กœ ๊ทธ๊ฒƒ์— ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ (๋ณ‘๋ ฌ์ด ์•„๋‹Œ) ์ˆœ์„œ๋Œ€๋กœ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ์ค‘์ฒฉ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ SSR์— ์ข‹์ง€ ์•Š์€ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€์œผ๋กœ ์š”์•ฝ๋ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ๋‹น ํ•˜๋‚˜์˜ ๊ฐ€์ ธ์˜ค๊ธฐ๋งŒ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด componentDidMount ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๋Œ€์‹  ๋ฐ์ดํ„ฐ ์ข…์†์„ฑ์„ ๊ฒฝ๋กœ ์—”ํ„ฐํ‹ฐ์— ์ฒจ๋ถ€ํ•˜์—ฌ ๊ณ„์•ฝ์„ ๊ณต์‹ํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์œ„์˜ ๋งŽ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๋„ ์ด์™€ ๊ฐ™์€ ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. Redux-First Router ๋Š” Redux๋ฅผ ์ฆ๊ฒ๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ผ์ข…์˜ "๊ณ„์•ฝ"์— ๋”ฐ๋ผ ์ด๊ฒƒ์„ ๋งค์šฐ ํ›Œ๋ฅญํ•˜๊ฒŒ ๊ณต์‹ํ™”ํ•ฉ๋‹ˆ๋‹ค.

Redux-First Router ๋Š” ๋งŽ์€ ๊ธฐ์กด ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋‹ค์‹œ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€๋งŒ ๋†€๋ž๊ฒŒ๋„ Redux ์—์ฝ”์‹œ์Šคํ…œ์—์„œ ๋ˆ„๋ฝ๋œ ๋ถ€๋ถ„์œผ๋กœ ๋”ฑ ๋งž์Šต๋‹ˆ๋‹ค. Redux์˜ ์›Œํฌํ”Œ๋กœ์— ๊ณ ์œ ํ•œ ๋ผ์šฐํ„ฐ๋ฅผ ์›ํ–ˆ๋‹ค๋ฉด Redux-First Router๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋น„๊ต์  ์ƒˆ๋กญ๊ณ  ์˜คํ”ˆ ์†Œ์Šค๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์‚ฌ๋žŒ์ด์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ 1๋…„ ๋™์•ˆ ์ž‘์—…ํ•œ ์ž‘์—…์ด๋ฉฐ ์ถœ์‹œ๋œ ์ง€ 2๊ฐœ์›” ๋งŒ์— ๋งŽ์€ ๊ด€์‹ฌ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ฒƒ์„ ์‚ฌ๋ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ผญ ํ•œ๋ฒˆ ๋ณด์‹œ๊ณ  ๊ฒฐ์ •ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค :).

๋‹ค์Œ์€ React Router๋ณด๋‹ค Redux๋ฅผ ์œ„ํ•œ ํ›จ์”ฌ ๋” ๋‚˜์€ ์†”๋ฃจ์…˜๊ณผ ๋˜ํ•œ ์šฐ์ˆ˜ํ•œ Redux-Little Router๊ฐ€ ๋ถˆํ–‰ํžˆ๋„ ๋†“์นœ ๋ฐฉ์‹์œผ๋กœ ๋น„์ „์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” ์ถœ์‹œ ๊ธฐ์‚ฌ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
์‚ฌ์ „ ์ถœ์‹œ: Redux-First ๋ผ์šฐํ„ฐ โ€” Redux-Little-Router๋ฅผ ๋„˜์–ด์„  ๋‹จ๊ณ„

RLR๊ณผ RFR์˜ ์ฃผ์š” ์ฐจ์ด์ ์€ RFR์ด ํ•ญ์ƒ LOCATION_CHANGED ๋Œ€์‹ ์— ๊ฒฝ๋กœ๋‹น ๋‹ค๋ฅธ ์ž‘์—… ์œ ํ˜•(์˜ˆ: URL ๋ณ€๊ฒฝ)์„ ์ „๋‹ฌํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ์ž‘์—…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฆฌ๋“€์„œ์—์„œ URL ๋ณ€๊ฒฝ์„ ๊ณ ์œ ํ•œ ์œ ํ˜•์œผ๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ํฐ ์ฐจ์ด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Redux ๋žœ๋“œ์—์„œ๋Š” ๋ถˆํ•„์š”ํ•œ <Route /> ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Redux-First Router ๊ฐ€ thunks ๊ฒฝ๋กœ์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์—์„œ React Native, React Navigation, ์ฝ”๋“œ ๋ถ„ํ• , ํ”„๋ฆฌํŽ˜์นญ ๋“ฑ์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๋ฐฉ๋Œ€ํ•œ ๋ชฉ๋ก๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ๋žŒ๋“ค์˜ ์ƒ๊ฐ์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@faceyspacey ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ props๋ฅผ ์„ค์ •ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ react-native-vector-icons ๊ฐ€ ์•„์ด์ฝ˜์„ ์•ฝ์†์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ์‚ฌ๋ฌผ์„ ๋ณด๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๋น„๋™๊ธฐ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ƒํƒœ์— ์—ฐ๊ฒฐํ•˜๋Š” componentWillMount ๋˜๋Š” redux X_GET_START , X_GET_END ๋ฐ X_GET_ERROR ์ž‘์—… ์ƒ์šฉ๊ตฌ๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ์š”์ฒญ์„ ํ•œ ๋ฒˆ๋งŒ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ. ๋ฐ์ดํ„ฐ ํด๋ง๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ƒํƒœ ์ €์žฅ ๋ฐ redux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํ•ฉ๋ฆฌ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๋” ๋‚˜์€? ์–ด๋””์—? React Native์—์„œ? Facebook๊ณผ ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ์กฐ์ง์—์„œ React Native ์•ฑ์„ ์‚ฌ์šฉํ•˜์‹œ๋‚˜์š”?

์•„๋งˆ๋„ React Native์—์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ณด๊ธฐ์—๋Š” SSR์ด ์žˆ์„ ๋•Œ ๋…ผ์Ÿ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ ๋ฒˆ, ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜์˜ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ œํ•œํ•˜์ง€ ์•Š๋Š” ํ•œ ์š”์ฒญ๋‹น ์—ฌ๋Ÿฌ ๊ฐ€์ ธ์˜ค๊ธฐ ์—†์ด ์›ํ•˜๋Š” ์ž‘์—…์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ๊ฒฝ๋กœ ์—”ํ„ฐํ‹ฐ์™€์˜ ๊ณ„์•ฝ์„ ๊ณต์‹ํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

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

SSR์ด ์—†๊ณ  ํ…Œ์ŠคํŠธ ์ „๋žต์ด ์›ํ™œํ•˜๊ณ  ๋ฐฉํ•ด๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€์— ๋ฐ˜๋Œ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๊ฑฐ๋Œ€ ๊ธฐ์—…์ด๋ผ๋ฉด ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ์ตœ์ƒ์œ„ ๊ฒฝ๋กœ ๋ ˆ๋ฒจ์„ ๊ฑด๋“œ๋ฆด ํ•„์š”๊ฐ€ ์—†๊ณ  ์ž ์žฌ์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ ๊นจ๋œจ๋ฆด ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด FB๊ฐ€ Relay์™€ GraphQL์„ ํ†ตํ•ด ์ด ๊ฒฝ๋กœ๋ฅผ ๊ฐœ์ฒ™ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ์˜ ์‚ฌ์‹ค์€ ์ด ๋ฐฐ์— ์ง„์ •์œผ๋กœ ์„ธ๊ณ„์—์„œ 100๊ฐœ ํšŒ์‚ฌ๋งŒ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” ์ฝ”๋กœ์ผ€์ด์…˜์„ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ/์•ฑ/ํšŒ์‚ฌ์—์„œ ํ˜„์‹ค๋ณด๋‹ค ๊ณผ์žฅ๋œ ๊ฒƒ์œผ๋กœ ๋ด…๋‹ˆ๋‹ค. ์ผ๋‹จ ๋ผ์šฐํŠธ ์ˆ˜์ค€์„ ์ดํ•ดํ•˜๊ณ  Redux-First Router ์ฒ˜๋Ÿผ ์ž˜ ์ˆ˜ํ–‰ํ•˜๋Š” ํŒจํ‚ค์ง€๋ฅผ ๊ฐ–๊ฒŒ ๋˜๋ฉด ๊ตฌ์„ฑ์›์ด ๋ผ์šฐํŠธ ์ˆ˜์ค€์„ ๋งŒ์งˆ ์ˆ˜ ์žˆ๋Š” ํŒ€์„ ์œ„ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐœ๋ฐœํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ๋” ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค. ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค ํ™ˆํŽ˜์ด์ง€์—์„œ ๋ฐ๋ชจ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

https://www.codesandbox.io

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

๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ๋น„๋™๊ธฐ ๋ Œ๋” ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(๋ Œ๋”๋Š” ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค). ๋ฃจํŠธ ๊ตฌ์„ฑ ์š”์†Œ ๋Œ€๊ธฐ ์ž์‹ ๊ตฌ์„ฑ ์š”์†Œ ๋ Œ๋”๋ง์„ ํ—ˆ์šฉํ•˜๊ณ  ๋ฌผ๋ก  ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋Š” ์•ฝ์†์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” https://github.com/3axap4eHko/preact-async-example ์— preact์—์„œ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

@faceyspacey ์œ„์˜ ์ž์„ธํ•œ ๋‹ต๋ณ€์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ €๋Š” Redux-First Router์˜ ์•„์ด๋””์–ด๊ฐ€ ์ •๋ง ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ์ œ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์ด์ „๋ณด๋‹ค ํ›จ์”ฌ ๋” ํˆฌ๋ช…ํ•˜๊ณ  ๊นจ๋—ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

ํฐ ๊ฐ์‚ฌ๋ฅผ ๋“œ๋ฆฐ๋‹ค!

@raRaRa ๋งˆ์Œ์— ๊ฒฝ๋กœ ์ˆ˜์ค€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ๋Œ€ํ•œ ์ข‹์€ ์ถ”์ƒํ™”๊ฐ€ ์—†์—ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. React React v3์—๋Š” ์ฝœ๋ฐฑ์ด ์žˆ์—ˆ๊ณ  v4์—๋Š” ์šฐ์ˆ˜ํ•œ ํŒจํ„ด(ํŠนํžˆ react-router-config ํŒจํ‚ค์ง€)์ด ์žˆ์ง€๋งŒ ๋ช…ํ™•ํ•˜์ง€ ์•Š๊ณ  v4์—์„œ ์ผ๊ธ‰์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‚˜์ค‘์— ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€ Redux์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ redux ์‚ฌ์šฉ์ž๊ฐ€ ์™„์ „ํ•œ "๊ฒฝ๋กœ ์ˆ˜์ค€" ์ถ”์ƒํ™”๋ฅผ ๊ฐ–๊ฒŒ ๋œ ๊ฒƒ์€ ์ด์ œ์„œ์•ผ ์ฒ˜์Œ์ž…๋‹ˆ๋‹ค.

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

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

React Native + Apollo์˜ ๊ฒฝ์šฐ SSR์ด ์—†์œผ๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ์ˆœ์ฐจ์  ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ™”๋ฉด์ด ๋„ˆ๋ฌด ์ž‘์„ ๋•Œ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ์ •๋ง๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๊นŒ? ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ธก๋ฉด์—์„œ ๊ฐ "์žฅ๋ฉด"์— ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑ๋งŒ ๊ฐœ์˜ ๊ทธ๋ž˜ํ”„, ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ” ๋“ฑ์ด ์žˆ๋Š” ๋ฐ์Šคํฌํƒ‘ ์›น ํŒจ๋„ ๋Œ€์‹œ๋ณด๋“œ์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ์•„๋งˆ๋„ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜์ค€์ด ์ดํ•ด๋˜๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ฃผ์š” ์žฅ์†Œ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฑฐ๊ธฐ์—์„œ๋„ ๋ชจ๋“  ์œ„์ ฏ์— ๋Œ€ํ•œ ๋ชจ๋“  ์š”๊ตฌ ์‚ฌํ•ญ์„ ํ•œ ๊ณณ์—์„œ ์ง€์ •ํ•˜๊ณ  Apollo๋ฅผ ํ†ตํ•ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ง ์ถฉ๋ถ„ํžˆ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ๊ธฐ๋ณธ ์•„์ด๋””์–ด๋Š” GraphQL ๋ฐ์ดํ„ฐ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๊ฒฝ๋กœ์— ์ฒจ๋ถ€ํ•œ ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ๋‹ค๋ฅธ Redux ๋ฐ์ดํ„ฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฐ์ดํ„ฐ์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ณด๋‹ค ๊ตฌ์ฒด์ ์œผ๋กœ ๋งํ•˜๋ฉด react-redux์˜ connect ์™€ Apollo์˜ ๋™๋“ฑํ•œ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹จ์ง€ ํ•˜๋‚˜๋ฅผ ์›ํ•˜๊ณ  ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์ด ๋” ์•„์ฒจํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. Apollo๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์ง„์ •์œผ๋กœ ์›ํ•˜๋Š” ๊ฒƒ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ๋” ๊นŠ์ด ์ค‘์ฒฉ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋น„์ „์€ ์ผ๋ฐ˜ Redux์™€ ๊ฒฝ๋กœ ์ˆ˜์ค€์—์„œ graphql ์‚ฌ์–‘์„ ๋”ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๊ฐ„์‹ ํžˆ ์‚ดํŽด๋ดค๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ธฐ์—๋Š” ๋‹ค์†Œ ์‹œ๊ธฐ์ƒ์กฐ์ด์ง€๋งŒ, ๊ฒฝ๋กœ ์ˆ˜์ค€์ด ์•ฑ์— ๋Œ€ํ•œ ์˜ฌ๋ฐ”๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด๋ผ๋ฉด Apollo + GraphQL๋„ ์˜ˆ์™ธ๋Š” ์•„๋‹ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

@faceyspacey ์ „์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Apollo๋‚˜ GraphQL์„ ์‚ฌ์šฉํ•ด ๋ณธ ์ ์ด ์—†์Œ์„ ์ธ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ํ™•์ธํ•˜๊ณ  ์‚ฌ์šฉ ์‚ฌ๋ก€์— ์–ด๋–ป๊ฒŒ ๋งž๋Š”์ง€ ํ™•์ธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

View ๋ถ€๋ถ„์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” MVC ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณด์•˜๋Š”๋ฐ ๋”์ฐํ•ฉ๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ์ผ๋ถ€ ๋ณด๊ธฐ/๊ตฌ์„ฑ ์š”์†Œ์— ์ˆจ๊ฒจ์ ธ ์žˆ๊ณ  ํ…Œ์ŠคํŠธ๊ฐ€ ๋” ์–ด๋ ค์›Œ์ง€๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์ ธ์˜ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ „ํ˜€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

์ €์—๊ฒŒ Redux-First Router๋Š” MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ ๋ถ€๋ถ„๊ณผ ๋งค์šฐ ํก์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋งค์šฐ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค :)

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•˜๋ฃจ๊ฐ€ ๋๋‚˜๋ฉด ์ƒˆ๋กœ์šด ์Šคํƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋‚จ: ๋ฆฌ๋•์Šค
V: ๋ฐ˜์‘
C: Redux-First ๋ผ์šฐํ„ฐ(๊ณง "Rudy" ๋กœ ์ด๋ฆ„ ๋ณ€๊ฒฝ ์˜ˆ์ •)

React(ํŠนํžˆ Redux)๊ฐ€ ๋‚˜์™”์„ ๋•Œ ์šฐ๋ฆฌ ๋ชจ๋‘๋Š” MVC์˜ ๊ณ ๋Œ€ ์ง€ํ˜œ๋ฅผ ๋ฒ„๋ฆฌ๊ณ  ์‹ถ์–ดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ถ๊ทน์ ์œผ๋กœ ๋‹จ์ˆœํžˆ ์ด๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ๊ฐ€ ์•„์ง ๊ตฌ์ถ•๋˜์ง€ ์•Š์€ ๊ฒƒ ์ด์ƒ์€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ์šฐ๋ฆฌ๋Š” ๋ฐ˜์‘์ ์ธ ํด๋ผ์ด์–ธํŠธ ์šฐ์„  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋„ ์—ฌ์ „ํžˆ MVC์˜ ์ด์ ์„ ํฌ๊ฒŒ ๋ˆ„๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ํด๋ผ์ด์–ธํŠธ ์šฐ์„  ์Šคํƒ๊ณผ ๊ธฐ์กด ์„œ๋ฒ„ ์ธก MVC์—์„œ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ผํ•œ 3 ๋ถ„๋ฆฌ๋œ ๊ด€์‹ฌ์‚ฌ์ž…๋‹ˆ๋‹ค.

3 ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ/๋™์ž‘์˜ ์ฐจ์ด์ ์ด ๋ฌด์—‡์ธ์ง€์— ๊ด€ํ•ด์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ณผ๊ฑฐ์—๋Š” ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ๋ชจ๋ธ์„ ์–ป์€ ๋‹ค์Œ ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ์ปจํŠธ๋กค๋Ÿฌ(RFR)๊ฐ€ ๋ทฐ๋ฅผ ์ฆ‰์‹œ ๋ Œ๋”๋งํ•˜๊ณ ("UI ๋ชจ๋ธ", ์ฆ‰ Redux ์ƒํƒœ๋ฅผ ํ†ตํ•ด ์„ ํƒ๋จ) ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋„๋ฉ”์ธ ๋ชจ๋ธ (Redux ์ƒํƒœ์—๋„ ์ €์žฅ๋จ)์„ ์ฐพ์œผ๋ฉด ๋ทฐ๋ฅผ ๋‘ ๋ฒˆ์งธ ๋กœ

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ์ด ๋งํฌ๋ฅผ ๋ณด์‹ญ์‹œ์˜ค. ๋‹ค์Œ์€ ๋ฐ์ดํ„ฐ ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง ์˜ˆ์ž…๋‹ˆ๋‹ค. https://github.com/bananaoomarang/isomorphic-redux

@harut55555 idk

๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฆด๋ฆฌ์Šค 16 ๋ฐ˜์‘ ๋ฐ ๋Œ€๋ถ€๋ถ„์˜ ์†”๋ฃจ์…˜์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Œ

ํ˜„์žฌ ์ ‘๊ทผ ๋ฐฉ์‹์€ redux observable ๋˜๋Š” redux thunk์™€ ๊ฐ™์€ ๋„๊ตฌ์™€ ํ•จ๊ป˜ redux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚˜์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€

<App>
    <Page>
        <AsyncModule hre="different.com/Button.react.js" /> downloaded from external url on server or client
    </Page>
</App>

๋ฌธ์ œ๋Š” ์•ฑ์„ ๋ Œ๋”๋งํ•˜๊ธฐ ์ „์— ๋‚ด๊ฐ€ ๊ฐ€์งˆ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ข…๋ฅ˜๋ฅผ ๋ชจ๋ฅธ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹จ์ง€ ๊ถ๊ธˆํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๋Œ€์‹  ๋ฐ์ดํ„ฐ/์ปจํ…์ธ ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์–ธ์ œ? ๋™์  ํŽ˜์ด์ง€๊ฐ€ ์žˆ๊ณ  ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์„ ์ˆ˜๋„ ์žˆ๊ณ  ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ์›ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค https://reactjs.org/docs/conditional-rendering.html

๋ผ์šฐํŒ… ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜์‘์€ ๋ Œ๋”๋ง ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์š”์ฒญํ•˜์ง€ ์•Š๊ณ  ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Apollo์˜ @graphql ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋กœ๋“œ๊ฐ€ ๋งค์šฐ ๊ฐ„๋‹จํ•ด์ง€๊ณ  React-Router v4 ๊ตฌ์„ฑ ์š”์†Œ ๊ธฐ๋ฐ˜ API๋Š” ๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•œ ๋ผ์šฐํŒ…์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค Redux์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ์™€ ์ง๊ตํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋‹จ์ผ ํŒจ์Šค ์ŠคํŠธ๋ฆฌ๋ฐ ๋ Œ๋”๋ง์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด render() ๊ฐ€ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์ง€๊ธˆ์ฒ˜๋Ÿผ, ์„œ๋ฒ„์—์„œ๋Š” ์•ฝ์†๋งŒ ๋ฐ˜ํ™˜).

๊ทธ๋Ÿฌ๋ฉด @graphql ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋กœ๋“œ๋œ ํ›„ render()์— ๋Œ€ํ•œ ์•ฝ์†์„ ๊ฐ„๋‹จํžˆ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€๋Š” ๋ชจ๋‘ ํ‰๋ฒ”ํ•œ React์ž…๋‹ˆ๋‹ค.

๋ช‡ ๋‹ฌ ์ „ ๋‚˜๋Š” JSConf ์•„์ด์Šฌ๋ž€๋“œ์—์„œ React์˜ ๋‹ค๊ฐ€์˜ค๋Š” ๋น„๋™๊ธฐ ๋ Œ๋”๋ง ๊ธฐ๋Šฅ์„ ์„ค๋ช…ํ•˜๋Š” ์—ฐ์„ค์„ ํ–ˆ์Šต๋‹ˆ๋‹ค(๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„ ์ฐธ์กฐ): https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react -16.html. ์ด๊ฒƒ์€ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ @acdlite ๋Š” React ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ๋Œ€๊ธฐํ•˜๊ณ  ์ค€๋น„๊ฐ€ ๋˜๋ฉด ๋งˆํฌ์—…์„ ์ ์ง„์ ์œผ๋กœ ํ”Œ๋Ÿฌ์‹œํ•˜๋Š” ๋ฐ ๋™์ผํ•œ ๊ฐœ๋…์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค. https://www.youtube.com/watch?v= z-6JC0_cOns

์ด ๊ฐ•์—ฐ์„ ์ฆ๊ฒ๊ฒŒ ์‹œ์ฒญํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค! 1๋…„ ์ •๋„ ์ง€๋‚˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๋งˆ๋ฌด๋ฆฌํ•˜๊ณ  ์ด์— ๋Œ€ํ•œ ๊ณต์‹ ์ „๋žต์„ ์„ธ์šธ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ง์ด ์ƒ๊ฐ๋‚˜๋„ค์š”. ์šฐ๋ฆฌ๋Š” ๋ฏธ๋ž˜๋ฅผ ํ•จ๊ป˜ ๊ณ„ํšํ•˜๋ฉฐ ๊ฒฐํ˜ผํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๊ทธ๋งŒํ•˜๊ณ  ์ €๋ฅผ ๋งŒ๋‚˜๋Ÿฌ ์˜ค์„ธ์š”. ์‹œ๊ฐ„์€ ํ•ญ์ƒ ์‚ฌ๋ž‘

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

react-baconjs : render-to-html.js ์—์„œ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ทจํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•˜๋Š” ๋‹ค๋ฅธ ๋ฌธ์ œ์—์„œ @gaearon์ด ์ž‘์„ฑํ•œ ๋Œ“๊ธ€์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

@steve-tailor ์˜ˆ, ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋˜ํ•œ ๋ชจ๋“  React ์•ฑ์—์„œ ์ž‘๋™ํ•˜๋Š” ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ ๋ชฉ์ ์˜ ์†”๋ฃจ์…˜์ธ react-frontload ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

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

๋ถ„๋ช…ํžˆ ์•ฝ๊ฐ„์˜ ๋‚ญ๋น„๊ฐ€ ์žˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ถฉ๋ถ„ํžˆ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค(์ฒซ ๋ฒˆ์งธ ๋ Œ๋”์˜ ์ถœ๋ ฅ์€ ๋‹จ์ง€ ์•ฝ์† ๊ทธ ์ด์ƒ์ด๋ฉฐ, ๊ทธ๋ƒฅ ๋ฒ„๋ ค์ง€๋Š” ์‹ค์ œ HTML์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค). ์ง„์ •ํ•œ ๋น„๋™๊ธฐ ์„œ๋ฒ„ ๋ Œ๋”๋ง์ด React๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉด ๋†€๋ž์Šต๋‹ˆ๋‹ค.

@davnicwil ์ž˜ํ–ˆ์–ด! ํŠน์ • ๋น„๋™๊ธฐ SSR ์†”๋ฃจ์…˜์„ ์ผ๋ฐ˜ํ™”ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. react-frontload๊ฐ€ ๋ฌด์ œํ•œ ๋น„๋™๊ธฐ ๊นŠ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๊นŒ? "๋‘ ๋ฒˆ"์ด๋ผ๊ณ  ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌป๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@steve-tailor ๊ฑด๋ฐฐ! ์˜ˆ, ๊นŠ์ด๊ฐ€ ํŠธ๋ฆฌ์˜ ๊ตฌ์„ฑ ์š”์†Œ ๊นŠ์ด๋ฅผ ์˜๋ฏธํ•œ๋‹ค๋ฉด ๋ฌด์ œํ•œ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ์ž์ฒด(๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ ํฌํ•จ)์—์„œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์—์„œ ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์‹คํ–‰๋˜๊ณ  ์•ฝ์†์ด ์ˆ˜์ง‘๋ฉ๋‹ˆ๋‹ค.

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

์ฆ‰, ์ค‘์ฒฉ ๋ฌธ์ œ(์‹ค์ œ๋กœ ์ด ์ „์ฒด ๋น„๋™๊ธฐ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฌธ์ œ)๋Š” ๊ฐ€๊นŒ์šด ์žฅ๋ž˜์— React์— ํฌํ•จ๋  Suspense ํ•ญ๋ชฉ์œผ๋กœ ํ•ด๊ฒฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿคž

์ฐธ๊ณ ๋กœ ์ด ์ž‘์—…์„ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#suspense -for-server-rendering

๋ฉ‹์ง€๋‹ค @gaearon!

@davnicwil react-baconjs ์€ ๋ฌด์ œํ•œ ๊นŠ์ด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

@gaearon ๋‚˜๋Š” ์ด๊ฒƒ์ด ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ๋ฐœ์‚ฌ JSX๋ฅผ ๋ฐ˜์‘ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒ์„ฑ ๊ตฌ๋…์—์„œ ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ์ง€์›์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์‹ถ์€ ์ด์œ ๋Š” ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๋จผ์ € ๋‚ด ์•ฑ์—์„œ ์ƒํƒœ๋Š” ์›น ์ž‘์—…์ž์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์š”๊ตฌํ•˜๋Š” ํ•ด๋‹น ์ƒํƒœ์˜ ๋น„ํŠธ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ ๋น„๋™๊ธฐ ์ž‘์—…์ด์ง€๋งŒ 5ms ์ •๋„ ๊ฑธ๋ฆฌ๋ฉฐ React๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ์•„๋ฌด ๊ฒƒ๋„ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‘˜์งธ, ์ง€๊ธˆ ๋‹น์žฅ์€ ์˜ต์ €๋ฒ„๋ธ”์„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ณดํŽธ์ ์ธ ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ์˜ต์ €๋ฒ„๋ธ”์ด ์ฒซ ๋ฒˆ์งธ ๊ฐ’์„ ๋™๊ธฐ์ ์œผ๋กœ ๋ฐฉ์ถœํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ตฌ๋…ํ•˜๊ณ , ๊ตฌ๋…์„ ์ทจ์†Œํ•˜๊ณ , ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, Replay create-observable ๋ฌธ์„œ์˜ ์ฃผ์ œ ์˜ˆ). ๊ทธ๋ฆฌ๊ณ  ๋น„๋™๊ธฐ์‹์œผ๋กœ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์„ ๋‚ด๋ณด๋‚ด๋Š” ๊ฒฝ์šฐ ์ฒ˜์Œ์—๋Š” null์„ ๋ Œ๋”๋งํ•˜๊ณ  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ˆ˜์‹  ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.

@steve-taylor react-frontload๋Š” ์ด์ œ 1.0.7 ๋ฆด๋ฆฌ์Šค์™€ ํ•จ๊ป˜ ๊ตฌ์„ฑ ์š”์†Œ ์ค‘์ฒฉ์˜ ๋ฌด์ œํ•œ ๊นŠ์ด๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

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

์šฐ๋ฆฌ๋Š” ์•ฑ์ด React Hooks๋กœ ๋นŒ๋“œ๋  ๋•Œ ์ด ๋ฌธ์ œ๋ฅผ ๊ฒช์—ˆ๊ณ  ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด

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

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰