๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป dev

๐Ÿ‘‹ ๊ตฟ๋ฐ”์ด CRA (Sunsetting Create React App)

TLDR;

๋ฆฌ์•กํŠธ ์•ฑ์„ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด CRA๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์…จ๋‚˜์š”? ์ด์ œ๋Š” CRA๊ฐ€ deprecate ๋ฉ๋‹ˆ๋‹ค.
ํ•ด๋‹น ์ด์œ ๋Š” ํฌ๊ฒŒ CRA๋Š” ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ fetching, ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ์„ ์ž์ฒด์ ์œผ๋กœ ์ง€์›ํ•˜์ง€ ์•Š์•„ 
์ถ”๊ฐ€์ ์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์˜์กดํ•ด์•ผํ–ˆ๋‹ค๋Š” ์ , ์ตœ๊ทผ ๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ด ํ•ด๋‹น ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ–ˆ๊ณ  ํ•ด๋‹น ๊ธฐ๋Šฅ๋“ค์„ ์œ„ํ•ด CRA๊ด€๋ฆฌ๊ฐ€ ๋ถˆํ•„์š”ํ•ด์กŒ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋นŒ๋“œ ํˆด๋กœ ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋น„๋ก CRA+๋นŒ๋“œ ํˆด๋„ ์„ ํƒ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์ด์ง€๋งŒ ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ fetching, ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ ๊ธฐ๋Šฅ์„ “์ž˜” ํ†ตํ•ฉํ•ด๋†“์€ Next.js, React Router, Expo์™€ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

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

 

ํ•ด๋‹น ๊ธ€์€ February 14, 2025 by Matt Carroll and Ricky Hanlon์ด ์ž‘์„ฑํ•œ Sunsetting create react app์„ ๋ฒˆ์—ญ/์˜์—ญ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

Create React App๋ฅผ deprecateํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

CRA๋กœ ๋งŒ๋“ค์–ด์ง„ ์•ฑ๋“ค์€ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•˜๊ฑฐ๋‚˜ vite, parcel ์ด๋‚˜ RSBuild ์™€ ๊ฐ™์€  build tool๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

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

 

2016๋…„์— Create React app์„ ์ถœ์‹œํ–ˆ์„ ๋‹น์‹œ, React app์„ ‘์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค’๋Š” ๊ทœ์น™์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

React ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” JSX, lint, hot reloading์™€ ๊ฐ™์€ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋“ค์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ํˆด๋“ค์„ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค์น˜ํ•ด์•ผํ–ˆ์ฃ . ์ด ๊นŒ๋‹ค๋กœ์šด ์ผ์„  ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๋งŒ๋“  boilerplates๊ฐ€ ํ•ธ๋“ค๋งํ–ˆ์—ˆ์ง€๋งŒ, boilerplate์€ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ๋„ ์–ด๋ ต๊ณ  fragmentation์€ ๋ฆฌ์•กํŠธ๊ฐ€ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

 

CRA๋Š” ์ด ๋ฌธ์ œ๋ฅผ ํ•˜๋‚˜์˜ ํ†ต์ผ๋œ ๊ถŒ์žฅ ์„ค์ •๋ฐฉ์‹์œผ๋กœ ์—ฌ๋Ÿฌ ํˆด๋“ค์„ ํ•ฉ์ณ์„œ ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์—ˆ์ฃ . 

์ด ๋ฐฉ์‹์œผ๋กœ ์•ฑ๋“ค์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒˆ๋กœ์šด ํˆด๊ณผ ๊ธฐ๋Šฅ์„ ์ง€๋‹Œ ๋ฒ„์ ผ์œผ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ํ•˜๊ฑฐ๋‚˜, ๋ฆฌ์•กํŠธ ํŒ€์ด ์ž‘์ง€ ์•Š์€ ํˆด ๋ณ€ํ™”(Fast Refresh support, React Hooks lint rules)๋ฅผ ๊ฐ€๋Šฅํ•œ ๋งŽ์€ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์ฃ . ์ด ๋ชจ๋ธ์˜ ์ธ๊ธฐ์— ํž˜์ž…์–ด ์˜ค๋Š˜๋‚ ์—๋Š” ํ•ด๋‹น ๋ฐฉ์‹์œผ๋กœ ์ž‘์—…ํ•˜๋Š” ํˆด๋“ค๋งŒ์˜ ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์•„์˜ˆ ์žˆ์„ ์ •๋„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

Deprecating Create React App

 

๋น„๋ก CRA๋กœ ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ๋Š” ์‰ฝ์ง€๋งŒ, ํ”„๋กœ๋•์…˜ ์•ฑ์œผ๋กœ์จ ์ตœ์ƒ์˜ ๊ธฐ๋Šฅ๋“ค์„ ํ•˜๊ธฐ์—๋Š”  ์—ฌ๋Ÿฌ ์ œ์•ฝ๋“ค ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. 

์›์น™๋Œ€๋กœ๋ผ๋ฉด ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋ฐœ์ „์‹œ์ผœ์„œ ํ•ด๊ฒฐํ•  ๋ฌธ์ œ์ด์ง€๋งŒ, CRA๋Š” ํ˜„์žฌ ์œ ์ง€๋ณด์ˆ˜ ๊ด€๋ฆฌ์ž๋“ค์ด ์—†๊ณ , 

์ด๋ฏธ ์ด ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ด ์ˆ˜๋‘‘ํ•ด์„œ CRA๋ฅผ deprecateํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. 

 

์˜ค๋Š˜๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด app์„ CRA๋กœ ์„ค์น˜ํ•  ๊ฒฝ์šฐ deprecation ๊ฒฝ๊ณ ๋ฅผ ๋ณด์‹œ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ

 

์ด์ œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ƒˆ๋กœ์šด ๋ฆฌ์•กํŠธ์•ฑ ์ƒ์„ฑํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๊ถŒ์žฅํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋žœ๋”๋ง(CSR)๊ณผ  ์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์•ฑ(SPA)์„ ์ง€์›ํ•˜๊ณ , CDN์ด๋‚˜ ์„œ๋ฒ„์—†์ด ์ •์  ํ˜ธ์ŠคํŒ… ์„œ๋น„์Šค๋กœ ๋ฐฐํฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฏธ CRA๋กœ ๋งŒ๋“ค์–ด์ง„ ์•ฑ์€ ๋‹ค์Œ์˜ ๊ฐ€์ด๋“œ๋ฅผ ํ†ตํ•ด ์ˆœ์ˆ˜ ํด๋ผ์ด์–ธํŠธ(client-only) ๊ธฐ๋ฐ˜์˜ SPA๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋นŒ๋“œ ํˆด๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ

 

์•ฑ์ด ๋…ํŠนํ•œ ์ œ์•ฝ์ด ์žˆ๊ฑฐ๋‚˜, ์ง์ ‘ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ฑฐ๋‚˜, ๋ฆฌ์•กํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ง€ ๋ผˆ๋Œ€๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด Vite, Parcel ๋‚˜ Rsbuild๋ฅผ ํ†ตํ•ด ๋ฆฌ์•กํŠธ ์„ธํŒ…์„ ์ปค์Šคํ…€๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜์˜ ๋งํฌ๋“ค์€ CRA๋กœ ๋งŒ๋“ค์–ด์ง„ ์•ฑ์„ ๋นŒ๋“œํˆด๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค: 

 

Vite, Parcel ๋‚˜ Rsbuild๋กœ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ๋„์›€์ด ํ•„์š”ํ•˜์‹œ๋ฉด Building a React App from Scratch๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

๐Ÿค” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ• ๊นŒ์š”?

๋Œ€๋ถ€๋ถ„์˜ ์•ฑ๋“ค์€ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋•์„ ๋ณด๊ฒ ์ง€๋งŒ, ํŠน์ • ๊ฒฝ์šฐ์—๋Š” ๋ฆฌ์•กํŠธ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ƒˆํŒ…ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ์‚ดํŽด๋ณผ ๊ฒƒ์€ ์•ฑ์ด ๋ผ์šฐํŒ…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋ผ๋ฉด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
Svelte๊ฐ€ Sveltekit์ด ์žˆ๊ณ , Vue๋Š” Nuxt๊ฐ€ ์žˆ๊ณ , Solid๊ฐ€ SolidStart๊ฐ€ ์žˆ๋“ฏ์ด, ๋ฆฌ์•กํŠธ๋Š” data-fetching ์™€ code-splitting๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ๋“ค์ด ๋ผ์šฐํŒ…์— ์ฒ˜์Œ๋ถ€ํ„ฐ ์™„์ „ํžˆ ํ†ตํ•ฉ๋˜์–ด ์žˆ๋Š”  ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ์„ค์ •์„ ์ง์ ‘ํ•ด์•ผํ•˜๋Š” ์ˆ˜๊ณ ์Šค๋Ÿฌ์›€์„ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ด ํ•ด๊ฒฐํ•˜์ฃ . ํ•˜์ง€๋งŒ Vite, Parcel ๋˜๋Š” Rsbuild์™€ ๊ฐ™์€ ๋นŒ๋“œ ํˆด๋กœ ๋ฆฌ์•กํŠธ ์•ฑ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋งŒ๋“œ๋Š” ๊ฒƒ ๋˜ํ•œ ์–ธ์ œ๋‚˜ ์„ ํƒ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ฆฌ์•กํŠธ๊ฐ€  ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ ์™€  ๋นŒ๋“œ ํˆด์˜ ํ•œ๊ณ„์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋นŒ๋“œ ํˆด์˜ ํ•œ๊ณ„

 

CRA์™€ ๋นŒ๋“œ ํˆด์„ ํ†ตํ•ด ๋ฆฌ์•กํŠธ ์•ฑ์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์‰ฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค.

npx create-react-app my-app๋ฅผ ์‹คํ–‰ํ•˜๋ฉด dev ์„œ๋ฒ„, linting, production ๋นŒ๋“œ๋ฅผ ํฌํ•จํ•ด ์ถฉ๋ถ„ํžˆ ์„ค์ •์ด ๋œ ๋ฆฌ์•กํŠธ ์•ฑ๊ฐ€ ๋งŒ๋“ค์–ด์ง€์ฃ .

 

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‚ด๋ถ€ ์–ด๋“œ๋ฏผ ํˆด์„ ๋งŒ๋“ค๊ณ ์ž ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋žœ๋”ฉ ํŽ˜์ด์ง€๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: 

 

export default function App() {

  return (

    <div>

      <h1>Welcome to the Admin Tool!</h1>

    </div>

  )

}

 

 

JSX์™€ ๊ฐ™์€ ๋ฆฌ์•กํŠธ ๊ธฐ๋Šฅ๋“ค์„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋”ฉ์„ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋””ํดํŠธ ๋ฆฐํŠธ ๊ทœ์น™, dev ์™€ prod ๊ฐ๊ฐ์—์„œ ์‹คํ–‰๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๋Š” ๋ฒˆ๋“ค๋Ÿฌ๊ฐ€ ์žˆ์ง€๋งŒ, ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ์—๋Š” ํ•„์ˆ˜์ ์ธ ํˆด๋“ค์ด ๋ถ€์žฌํ•˜์ฃ .

๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๋•์…˜ ์•ฑ๋“ค์€ routing, data fetching ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ ์Šคํ”„๋ฆฟํ•˜๊ธฐ ๋“ฑ์˜ ๊ธฐ๋Šฅ๋“ค์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

๋ผ์šฐํŒ…

 

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

 

import {useState} from 'react';



import Home from './Home';

import Dashboard from './Dashboard';



export default function App() {

  // โŒ Routing in state does not create URLs

  const [route, setRoute] = useState('home');

  return (

    <div>

      {route === 'home' && <Home />}

      {route === 'dashboard' && <Dashboard />}

    </div>

  )

}

 

CRA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์•ฑ๋“ค์€ React Router ๋‚˜Tanstack Router์™€ ๊ฐ™์€ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ผ์šฐํŒ… ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์•ฑ์— ์ถ”๊ฐ€์ ์ธ ๋ผ์šฐํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ์•ฑ์˜ ๊ตฌ์กฐ์— ๋Œ€ํ•œ opinion์„ ์ œ๊ณตํ•˜๋ฉฐ ๋ผ์šฐํŠธ์— ํ•ด๋‹น๋˜๋Š” ๋งํฌ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

 React Router์˜ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ผ์šฐํŠธ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์ฃ : 

 

import {RouterProvider, createBrowserRouter} from 'react-router';



import Home from './Home';

import Dashboard from './Dashboard';



// โœ… Each route has it's own URL

const router = createBrowserRouter([

  {path: '/', element: <Home />},

  {path: '/dashboard', element: <Dashboard />}

]);



export default function App() {

  return (

    <RouterProvider value={router} />

  )

}

 

 

์ด์ œ /dashboard๋งํฌ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ณ , ์•ฑ์ด ๋Œ€์‰ฌ๋ณด๋“œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์ฃ . 

๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ค‘์ฒฉ ๋ผ์šฐํŠธ(nested routes), ๋ผ์šฐํŠธ ๊ฐ€๋“œ(route guard), ๋ผ์šฐํŠธ ํŠธ๋žœ์ง€์…˜(route transition)์™€ ๊ฐ™์ด ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ธฐ๋Šฅ๋“ค์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

๋น„๋ก ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์•ฑ์˜ ๋ณต์žก๋„๋ฅผ ๋†’์ด์ง€๋งŒ ์—†์œผ๋ฉด ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ์ถ”๊ฐ€ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ธฐ๋„ ํ•˜์ฃ .

 

๋ฐ์ดํ„ฐ fetching

 

CRA์˜ ํฐ ๋ฌธ์ œ์  ์ค‘ ํ•˜๋‚˜๋Š” data fetching์ด ์—ˆ์Šต๋‹ˆ๋‹ค. CRA๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์ด ํŠน์ •๋˜์–ด ์žˆ์ง€ ์•Š๊ณ , ์ด์ œ ๋ง‰ ์‹œ์ž‘ํ•˜๊ณ  ์žˆ๋Š” ์ž…์žฅ์ด๋ผ๋ฉด useEffect์•ˆ์— ๋ฐ์ดํ„ฐ๋ฅผ fetchํ•ด์„œ ๋กœ๋“œํ•˜๋Š” ์˜ต์…˜์„ ๊ณ ๋ คํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ๋ฐฉ์‹์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋œ ์ดํ›„์— ๋ฐ์ดํ„ฐ๊ฐ€ fetch๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋„คํŠธ์›Œํฌ waterfall๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ waterfall์€ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•˜๊ณ  ์žˆ์„ ๋•Œ ๋ณ‘๋ ฌ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ fetchํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์•ฑ์ด ๋žœ๋”๋  ๋•Œ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

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

 

export default function Dashboard() {

  const [data, setData] = useState(null);



  // โŒ Fetching data in a component causes network waterfalls

  useEffect(() => {

    fetch('/api/data')

      .then(response => response.json())

      .then(data => setData(data));

  }, []);



  return (

    <div>

      {data.map(item => <div key={item.id}>{item.name}</div>)}

    </div>

  )

}

 

 

React Query, SWR, Apollo, or Relay ์™€ ๊ฐ™์€ fetch ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ prefetchํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”ํ•˜๊ธฐ ์ „์— ์š”์ฒญ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ฃ . 

 

๋‹ค์Œ ์˜ˆ์‹œ์™€ ๊ฐ™์ด ๋ผ์šฐํŒ… loader ํŒจํ„ด์™€ ํ•จ๊ป˜ ๋ผ์šฐํŠธ ๋ ˆ๋ฒจ์˜ ๋ฐ์ดํ„ฐ ์˜์กด์„ฑ์„ ๋ถ€์—ฌํ•˜๋ฉด ๋ผ์šฐํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ fetch๋ฅผ ํŠน์ •ํ™”ํ•˜์—ฌ ์ตœ์ ํ™”ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: 

export async function loader() {

  const response = await fetch(`/api/data`);

  const data = await response.json();

  return data;

}



// โœ… Fetching data in parallel while the code is downloading

export default function Dashboard({loaderData}) {

  return (

    <div>

      {loaderData.map(item => <div key={item.id}>{item.name}</div>)}

    </div>

  )

}

 

์ฒซ ๋กœ๋“œ ์‹œ  ๋ผ์šฐํ„ฐ๋Š” ๋ผ์šฐํŠธ๋ฅผ ๋žœ๋”ํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๋กœ fetchํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

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

 

ํ•˜์ง€๋งŒ ํ•ด๋‹น ๋ฐฉ์‹์€ ๋กœ๋”๋ฅผ ์ ์ ˆํžˆ configureํ•ด์•ผํ•˜๊ณ , ์„ฑ๋Šฅ๊ณผ ๋ณต์žก์„ฑ ๊ฐ„์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค.

 

์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๊ธฐ

 

CRA์˜ ํฐ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๊ธฐ์ž…๋‹ˆ๋‹ค.

CRA๋Š” ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ์„ ํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ •๋œ ํ•ด๊ฒฐ์ฑ…์„ ์ œ์‹œํ•˜์ง€ ์•Š์ฃ . ๋ฆฌ์•กํŠธ๋ฅผ ๋ง‰ ์‹œ์ž‘ํ•œ ์ž…์žฅ์ด๋ผ๋ฉด ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๋Š” ๊ฒƒ ์ž์ฒด๋ฅผ ์•„์˜ˆ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ•ด๋‹น ๊ฒฝ์šฐ, ์•ฑ์ด ์‹ฑ๊ธ€ ๋ฒˆ๋“ค์˜ ๊ฒฝ์šฐ  bundle.js : 75kb๋กœ ์ œ๊ณต๋œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ์œ ์ €๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ์—๋งŒ ๋ฒˆ๋“ค์„ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜๋ฉด  ์ด์ƒ์ ์ด์ฃ .

์œ ์ €๊ฐ€ ํ˜„์žฌ ์žˆ๋Š” ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ฝ”๋“œ๋งŒ ๋‹ค์šด๋กœ๋“œํ•ด๋„ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์„ ๋กœ๋“œํ•˜๊ธฐ๊นŒ์ง€ ๋Œ€๊ธฐ์‹œ๊ฐ„์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • core.js      25kb
  • home.js      25kb
  • dashboard.js 25kb

 

์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” React.lazy๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋˜๊ธฐ ์ „๊นŒ์ง€ ์ฝ”๋“œ fetch๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๊ณ , ์ด๋Š” ๋„คํŠธ์›Œํฌ waterfall๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ ์ ˆํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์ฝ”๋“œ๊ฐ€ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์žˆ์„ ๋•Œ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ fetchํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ผ์šฐํ„ฐ feature๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

์˜ˆ๋ฅผ ๋“ค์–ด React Router๋Š” lazy ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํŠน์ • ๋ผ์šฐํŠธ์—์„œ๋Š” ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ์„ ํ•˜์—ฌ ๋กœ๋“œ๋  ๋•Œ ์ตœ์ ํ™”๋ฅผ ํ•ด์ค๋‹ˆ๋‹ค:  

 

import Home from './Home';

import Dashboard from './Dashboard';



// โœ… Routes are downloaded before rendering

const router = createBrowserRouter([

  {path: '/', lazy: () => import('./Home')},

  {path: '/dashboard', lazy: () => import('Dashboard')}

]);

 

์ตœ์ ํ™”๋œ ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๊ธฐ๋Š” ์‰ฝ์ง€ ์•Š๊ณ , ์œ ์ €๋“ค์ด ํ•„์š” ์ด์ƒ์œผ๋กœ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ฒŒ๋” ํ•˜๋Š” ์‹ค์ˆ˜๋กœ ์ด์–ด์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์บ์‹ฑ ์ตœ๋Œ€ํ™”ํ•˜๊ธฐ, ๋ณ‘๋ ฌ fetch, "์ƒํ˜ธ์ž‘์šฉ ์‹œ์— ์ž„ํฌํŠธํ•˜๊ธฐ (import on interaction)" ํŒจํ„ด๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด์•ผ ๋ผ์šฐํ„ฐ์™€ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํ•ด๊ฒฐ์ฑ…์„ ์ž˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ฃ .

 

+ CRA๋ฅผ ๋ณด๋‚ด์ฃผ๋Š” ์ถ”๊ฐ€์ ์ธ ์ด์œ ๋“ค…

 

๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ fetching, ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๊ธฐ ๋“ฑ์˜ ๊ธฐ๋Šฅ ๋ถ€์žฌ๋Š” CRA๋ฅผ ๋ณด๋‚ด์ค˜์•ผํ•˜๋Š” ์—ฌ๋Ÿฌ ์ด์œ ๋“ค ์ค‘ ๋ช‡๊ฐ€์ง€์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€ํ•˜๊ณ ๋„ pending state ๊ณ ๋ คํ•˜๊ธฐ, ๋„ค๋น„๊ฒŒ์ด์…˜ ์ธํ„ฐ๋Ÿฝ์…˜, ์‚ฌ์šฉ์ž๋“ค์„ ์œ„ํ•œ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ revalidateํ•˜๊ธฐ ๋“ฑ ์‹ค์ œ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ ํ•ด๊ฒฐํ•  ๋ฌธ์ œ๋“ค์ด ์กด์žฌํ•˜์ฃ .

 

์‹ค์ œ ์œ ์ €๋“ค์„ ์œ„ํ•ด์„œ ํ•ด๊ฒฐํ•ด์•ผํ•  ๋ฌธ์ œ ์นดํ…Œ๊ณ ๋ฆฌ๋“ค์„ ๋‚˜์—ดํ•˜์ž๋ฉด: 

 

  • Accessibility
  • Asset loading
  • Authentication
  • Caching
  • Error handling
  • Mutating data
  • Navigations
  • Optimistic updates
  • Progressive enhancement
  • Server-side rendering
  • Static site generation
  • Streaming

 

์ด ๋ชจ๋‘ ์ตœ์ ์˜  ๋กœ๋”ฉ ์‹œํ€€์Šค(loading sequence)๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•จ๊ป˜ ๊ณ ๋ คํ•ด์•ผํ•  ์‚ฌํ•ญ์ด์ฃ .

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

 

ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ 

 

์–ด์ฐŒ์ €์ฐŒ CRA์™€ ๋นŒ๋“œ ํˆด(e.g. Vite, Parcel)์„ ํ†ตํ•ด ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๊ฒ ์ง€๋งŒ, “์ž˜”ํ•˜๊ธฐ๋Š” ์‰ฝ์ง€ ์•Š๋‹ค๋Š”๊ฒŒ ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. CRA๊ฐ€ ์—ฌ๋Ÿฌ ๋นŒ๋“œ ํˆด๊ณผ ํ†ตํ•ฉ๋˜์—ˆ๋“ฏ์ด, ์œ ์ €์—๊ฒŒ ์ตœ์ ์˜ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ๊ธฐ๋Šฅ๋“ค์„ ์ง€๋‹Œ ํˆด๋“ค์„ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•œ ๋…ธ๋ ฅ์ด ํ•„์š”ํ•˜์ฃ .

ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ(๋นŒ๋“œ ํˆด, ๋žœ๋”๋ง, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ fetching, ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟํ•˜๊ธฐ)์˜ ํˆด๋“ค์„ ํ†ตํ•ฉํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ “ํ”„๋ ˆ์ž„ ์›Œํฌ”์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ ์ž์ฒด๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ๋ผ๊ณ  ๋ถ€๋ฅด์‹ ๋‹ค๋ฉด, ํˆด๋“ค์„ ํ†ตํ•ฉํ•ด๋†“์€ ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ “๋ฉ”ํƒ€ ํ”„๋ ˆ์ž„์›Œํฌ”๋ผ๊ณ ๋„ ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๊ฒ ์ฃ .

 

ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋นŒ๋“œ ํˆด๋“ค์ด ํˆด ์‚ฌ์šฉ์ด ์šฉ์ดํ•˜๋„๋ก opinion์„ ๊ฐ•์ œํ•˜๋“ฏ์ด, ๋” ์ข‹์€ ์œ ์ € ๊ฒฝํ—˜์„ ์œ„ํ•ด ์•ฑ์„ ํŠน์ • ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค๋„๋ก opinion์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

์•ž์„œ ๋งํ•œ ์ด์œ ๋•Œ๋ฌธ์— ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ๊ฒฝ์šฐ  Next.js, React Router , Expo๋ฅผ  ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์€ CRA๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๊ฐ™์€ ๊ฒฝํ—˜๊ณผ ๋”๋ถˆ์–ด ์œ ์ €๋“ค์ด ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์•ฑ๋“ค์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํ•ด๊ฒฐ์ฑ…๋“ค์„ ์ œ์‹œํ•˜์ฃ .

 

๐Ÿค” ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋žœ๋”๋ง์ด ํ•„์ˆ˜์ธ๊ฐ€์š”?

์•ž์„œ ๊ถŒ์žฅํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค ๋ชจ๋‘ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋žœ๋” ๊ธฐ๋ฐ˜์˜ ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
ํŠน์ • ๊ฒฝ์šฐ CSR๊ฐ€ ํŽ˜์ด์ง€์— ์ ์ ˆํ•œ ์„ ํƒ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒ๋‹ˆ๋‹ค. ์•ฑ ๋Œ€๋ถ€๋ถ„์ด  ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ๋ผ๊ณ  ํ•ด๋„  static-site generation (SSG) ๋‚˜ server-side rendering (SSR)์˜ ๋•์„ ๋ณผ ํŽ˜์ด์ง€๋“ค์ด ์ข…์ข… ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ์ด์šฉ ์•ฝ๊ด€ ํŽ˜์ด์ง€(Terms of Service page), ๋„ํ๋ฉ˜ํ…Œ์ด์…˜ ๋“ฑ์ด ํ•ด๋‹น๋˜์ฃ .  

์„œ๋ฒ„ ๋žœ๋”๋ง์€ ์ฃผ๋กœ ํด๋ผ์ด์–ธํŠธ ์ชฝ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์— ๋œ ๋ณด๋‚ด๊ณ , ์™„์„ฑ๋œ HTML ๋ฌธ์„œ๋ฅผ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์— Total Blocking Time (TBD)๋ฅผ ์ค„์—ฌ First Contentful Paint (FCP)๊ฐ€ ๋น ๋ฅด๊ฒŒ ์ด๋ฃจ์–ด์ ธ  Interaction to Next Paint (INP)๋ฅผ ๊ฐ์†Œ์‹œ์ผœ ์ค๋‹ˆ๋‹ค. 
์ด๋Ÿฌํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ํฌ๋กฌ ํŒ€์€ static ์ด๋‚˜ server-side ๋žœ๋”๋ฅผ ์ˆœ์ˆ˜ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋žœ๋” ๋ณด๋‹ค ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์— ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋“ค์ด ์žˆ๊ณ  ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ ์ตœ์„ ์˜ ์„ ํƒ์ด ์•„๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

ํŽ˜์ด์ง€๋ฅผ ์„œ๋ฒ„์—์„œ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ๋น„์šฉ๊ณผ ์‹œ๊ฐ„์€ Time to First Byte (TTFB)๋ฅผ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์ ํ•ฉํ•œ ๋žœ๋”๋ง ๋ฐฉ์‹์„ ํ•„์š”์— ๋”ฐ๋ผ ์ทจ์‚ฌ์„ ํƒํ•˜์—ฌ ์ตœ์ ํ™”๋œ ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

 

๊ทธ๋Ÿผ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š”?

 

์•ž์„œ ์–ธ๊ธ‰ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ ๋ชจ๋‘ ๋ฆฌ์•กํŠธ  ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋ผ์šฐํŒ…๊ณผ ๋ฐ์ดํ„ฐ fetching ๋ฌธ์ œ๋“ค์„ ์„œ๋ฒ„์—์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ ์Šคํ”Œ๋ฆฟ์„  ๋žœ๋”ํ•ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด๋‚ด์•ผํ•˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์–‘์„ ์ค„์ด๊ณ   loading sequence๋ฅผ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

 

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.CI ์„œ๋ฒ„์—์„œ static-site generated app (SSG) ์•ฑ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋นŒ๋“œ ํƒ€์ž„ ์‹œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๊ณ , ์›น ์„œ๋ฒ„์—์„œ SSR(์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋žœ๋”)๋œ ์•ฑ์—์„œ ๋Ÿฐํƒ€์ž„์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 ๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ ์ œ๋กœ-๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์†Œ๊ฐœ ์™€ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ถ”๊ฐ€์ ์ธ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ—’๏ธ ์„œ๋ฒ„ ๋žœ๋”๋ง์€ SEO๋งŒ์„ ์œ„ํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

 

์„œ๋ฒ„ ๋žœ๋”๋ง์ด SEO๋งŒ์„ ์œ„ํ•œ ๊ฒƒ์ด๋ผ๋Š” ํ”ํ•œ ์˜คํ•ด๊ฐ€ ์žˆ๋‹ค.

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

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

 

 


 

Reference

 

Sunsetting Create React App

 

Sunsetting Create React App – React

The library for web and native user interfaces

react.dev