Skip to content

Latest commit

ย 

History

History
324 lines (217 loc) ยท 23.8 KB

File metadata and controls

324 lines (217 loc) ยท 23.8 KB
title Create React App ์ง€์› ์ข…๋ฃŒ
author Matt Carroll and Ricky Hanlon
date 2025/02/14
description ์ƒˆ๋กœ์šด ์•ฑ์— ๋Œ€ํ•œ Create React App ์‚ฌ์šฉ์„ ์ค‘๋‹จํ•˜๋ฉฐ, ๊ธฐ์กด ์•ฑ์€ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ Vite, Parcel, RSBuild ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ”„๋กœ์ ํŠธ์™€ ๋งž์ง€ ์•Š๊ฑฐ๋‚˜, ์ž์‹ ๋งŒ์˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ๊ฑฐ๋‚˜, ํ˜น์€ React๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ฐฐ์šฐ๊ธฐ ์œ„ํ•ด React ์•ฑ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด ๋ณด๊ณ  ์‹ถ์€ ์‚ฌ์šฉ์ž๋“ค์„์„ ์œ„ํ•œ ๋ฌธ์„œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

2025๋…„ 2์›” 14์ผ, Matt Carroll, Ricky Hanlon


์ƒˆ๋กœ์šด ์•ฑ์— ๋Œ€ํ•œ Create React App ์‚ฌ์šฉ์„ ์ค‘๋‹จํ•˜๋ฉฐ, ๊ธฐ์กด ์•ฑ์€ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ Vite, Parcel, RSBuild ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

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


2016๋…„ Create React App์„ ์ฒ˜์Œ ์ถœ์‹œํ•˜์˜€์„ ๋•Œ๋Š” React ์•ฑ์„ ์ƒˆ๋กœ ๊ตฌ์ถ•ํ•  ๋ช…ํ™•ํ•œ ๋ฐฉ๋ฒ•์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹น์‹œ React ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” JSX, Linting, Hot Reloading๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ง์ ‘ ์„ค์น˜ํ•˜๊ณ  ์—ฐ๊ฒฐํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋งค์šฐ ๊นŒ๋‹ค๋กœ์› ๊ธฐ ๋•Œ๋ฌธ์—, ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์„ค์ •์— ๋Œ€ํ•œ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋Š” ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์กฐ๊ฐํ™”๋กœ ์ธํ•ด React ํŒ€์ด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์ด ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.

Create React App์€ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ํ•˜๋‚˜์˜ ๊ถŒ์žฅ ์„ค์ •์œผ๋กœ ํ†ตํ•ฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์•ฑ์ด ์ƒˆ๋กœ์šด ๋„๊ตฌ ๊ธฐ๋Šฅ์œผ๋กœ ์‰ฝ๊ฒŒ ์—…๊ทธ๋ ˆ์ด๋“œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์œผ๋ฉฐ, React ํŒ€์€ ์ž๋ช…ํ•˜์ง€ ์•Š์€ ๋„๊ตฌ ๋ณ€๊ฒฝ (Fast Refresh ์ง€์›, React Hooks Lint ๊ทœ์น™ ๋“ฑ)์„ ๊ฐ€๋Šฅํ•œ ๋งŽ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

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

Create React App์˜ ์ง€์› ์ข…๋ฃŒ {/deprecating-create-react-app/}

Create React App์€ ์‹œ์ž‘์„ ์‰ฝ๊ฒŒ ํ•ด์ฃผ์ง€๋งŒ, ๊ณ ์„ฑ๋Šฅ์˜ ํ”„๋กœ๋•์…˜ ์•ฑ ๊ตฌ์ถ•์„ ์–ด๋ ต๊ฒŒ ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์›์น™์ ์œผ๋กœ๋Š” ์ด๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋ฐœ์ „์‹œ์ผœ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ํ˜„์žฌ Create React App์€ ์ ๊ทน์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋‹ด๋‹น์ž๊ฐ€ ์—†๊ณ , ์ด๋ฏธ ๋งŽ์€ ๊ธฐ์กด ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์ž˜ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์„ ์ค‘๋‹จํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์˜ค๋Š˜๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด ์•ฑ ์„ค์น˜ ์‹œ์—๋Š” ์ง€์› ์ข…๋ฃŒ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

create-react-app is deprecated. {'\n\n'} You can find a list of up-to-date React frameworks on react.dev For more info see: react.dev/link/cra {'\n\n'} This error message will only be shown once per install.

Create React App ์›น์‚ฌ์ดํŠธ์™€ GitHub ์ €์žฅ์†Œ์—๋„ ์ง€์› ์ข…๋ฃŒ ์•ˆ๋‚ด๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. Create React App์€ ์œ ์ง€ ๋ณด์ˆ˜ ๋ชจ๋“œ๋กœ ๊ณ„์† ๋™์ž‘ํ•˜๋ฉฐ, React 19์™€ ํ˜ธํ™˜๋˜๋Š” ์ƒˆ๋กœ์šด ๋ฒ„์ „์„ ๋ฐฐํฌํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ• {/how-to-migrate-to-a-framework/}

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

๊ธฐ์กด ์•ฑ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ ์•ˆ๋‚ด์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์ „์šฉ SPA๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋นŒ๋“œ ๋„๊ตฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ• {/how-to-migrate-to-a-build-tool/}

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

๊ธฐ์กด ์•ฑ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ ์•ˆ๋‚ด์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๋นŒ๋“œ ๋„๊ตฌ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Vite, Parcel ๋˜๋Š” RSBuild๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๊ธฐ ์œ„ํ•ด React ์•ฑ ๊ตฌ์ถ•ํ•˜๊ธฐ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋ฌธ์„œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ• ๊นŒ์š”? {/do-i-need-a-framework/}

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

Svelte์—๋Š” SvelteKit, Vue์—๋Š” Nuxt ๊ทธ๋ฆฌ๊ณ  Solid์—๋Š” SolidStart๊ฐ€ ์žˆ๋“ฏ์ด, React๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ผ์šฐํŒ…์„ ํฌํ•จํ•œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ, ์ฝ”๋“œ ๋ถ„ํ•  ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ํ†ตํ•ฉํ•œ ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ณต์žกํ•œ ์„ค์ •์„ ์ง์ ‘ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜, ์‚ฌ์‹ค์ƒ ์ž์ฒด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ๋ถ€๋‹ด์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ Vite, Parcel, Rsbuild ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด React ์•ฑ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ง์ ‘ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œ ๋„๊ตฌ์˜ ํ•œ๊ณ„์™€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๋ฉด ๊ณ„์† ์ฝ์–ด๋ณด์„ธ์š”.

๋นŒ๋“œ ๋„๊ตฌ์˜ ํ•œ๊ณ„ {/limitations-of-build-tools/}

Create React App๊ณผ ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋Š” React ์•ฑ์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. npx create-react-app my-app์„ ์‹คํ–‰ํ•˜๋ฉด ๊ฐœ๋ฐœ ์„œ๋ฒ„, Linting, ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๊ฐ€ ์™„์ „ํžˆ ์„ค์ •๋œ React ์•ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด๋ถ€ ๊ด€๋ฆฌ์ž ๋„๊ตฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒฝ์šฐ ๋žœ๋”ฉ ํŽ˜์ด์ง€๋ถ€ํ„ฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export default function App() {
  return (
    <div>
      <h1>Welcome to the Admin Tool!</h1>
    </div>
  )
}

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

๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๋•์…˜ ์•ฑ์€ ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ, ์ฝ”๋“œ ๋ถ„ํ• ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ผ์šฐํŒ… {/routing/}

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

import {useState} from 'react';

import Home from './Home';
import Dashboard from './Dashboard';

export default function App() {
  // โŒ ๋ผ์šฐํŒ…์€ State ๋‚ด์—์„œ URL์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  const [route, setRoute] = useState('home');
  return (
    <div>
      {route === 'home' && <Home />}
      {route === 'dashboard' && <Dashboard />}
    </div>
  )
}

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

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

import Home from './Home';
import Dashboard from './Dashboard';

// โœ… ๊ฐ๊ฐ์˜ ๋ผ์šฐํŠธ๋Š” ์ž์‹ ๋งŒ์˜ URL์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
const router = createBrowserRouter([
  {path: '/', element: <Home />},
  {path: '/dashboard', element: <Dashboard />}
]);

export default function App() {
  return (
    <RouterProvider value={router} />
  )
}

์ด ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด /dashboard๋กœ ๋งํฌ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ณ , ์•ฑ์ด ๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ค‘์ฒฉ ๋ผ์šฐํŠธ, ๋ผ์šฐํŠธ ๋ณดํ˜ธ, ๋ผ์šฐํŠธ ์ „ํ™˜ ๋“ฑ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์•ฑ์— ๋ณต์žก์„ฑ์„ ๋”ํ•ด์ฃผ์ง€๋งŒ, ์•ฑ ์—†์ด๋Š” ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ธฐ๋Šฅ๋„ ์ถ”๊ฐ€ํ•˜๋Š” Trade-Off๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ {/data-fetching/}

Create React App์˜ ๋˜ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Create React App์€ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์†”๋ฃจ์…˜์„ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ ์‹œ์ž‘ํ•œ๋‹ค๋ฉด, ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด Effect ๋‚ด์—์„œ fetch๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

export default function Dashboard() {
  const [data, setData] = useState(null);

  // โŒ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด ๋„คํŠธ์›Œํฌ ํญํฌ์ˆ˜ ํ˜„์ƒ์„ ์ผ์œผํ‚ต๋‹ˆ๋‹ค.
  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>
  )
}

<<<<<<< HEAD Effect์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๊ฒƒ์€, ๋ฐ์ดํ„ฐ๋ฅผ ๋” ์ผ์ฐ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด๊ธฐ ์œ„ํ•ด ๋” ์˜ค๋ž˜ ๊ธฐ๋‹ค๋ ค์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๊ธฐ ์ „์— ์š”์ฒญ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐ์ดํ„ฐ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋Š” React Query, SWR, Apollo ๋˜๋Š” Relay์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Fetching in an effect means the user has to wait longer to see the content, even though the data could have been fetched earlier. To solve this, you can use a data fetching library like TanStack Query, SWR, Apollo, or Relay which provide options to prefetch data so the request is started before the component renders.

bd87c394dc1daf0e54759126f847fcfa927e5a75

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

export async function loader() {
  const response = await fetch(`/api/data`);
  const data = await response.json();
  return data;
}

// โœ… ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•  ๋™์•ˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ‘๋ ฌ๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
export default function Dashboard({loaderData}) {
  return (
    <div>
      {loaderData.map(item => <div key={item.id}>{item.name}</div>)}
    </div>
  )
}

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

๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์•ฑ์—์„œ ๋กœ๋”๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑํ•ด์•ผ ํ•˜๋ฉฐ, ์„ฑ๋Šฅ์„ ์œ„ํ•ด ๋ณต์žก์„ฑ์„ ๊ฐ์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ๋ถ„ํ•  {/code-splitting/}

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

์ด๋Š” ์•ฑ์ด ํ•˜๋‚˜์˜ ๋ฒˆ๋“ค๋กœ ์ œ๊ณต๋˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

- bundle.js    75kb

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

- core.js      25kb
- home.js      25kb
- dashboard.js 25kb

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

import Home from './Home';
import Dashboard from './Dashboard';

// โœ… ๋ผ์šฐํ„ฐ๋Š” ๋ Œ๋”๋ง๋˜๊ธฐ ์ „์— ๋‹ค์šด๋กœ๋“œ ๋ฉ๋‹ˆ๋‹ค.
const router = createBrowserRouter([
  {path: '/', lazy: () => import('./Home')},
  {path: '/dashboard', lazy: () => import('Dashboard')}
]);

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

๊ทธ๋ฆฌ๊ณ ... {/and-more/}

์ด๊ฒƒ๋“ค์€ Create React App์˜ ๋ช‡ ๊ฐ€์ง€ ์ œํ•œ ์‚ฌํ•ญ ์˜ˆ์‹œ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

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

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

์ด ๋ชจ๋“  ๊ฒƒ๋“ค์ด ํ•จ๊ป˜ ์ž‘๋™ํ•˜์—ฌ ๊ฐ€์žฅ ์ตœ์ ํ™”๋œ ๋กœ๋”ฉ ์ˆœ์„œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

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

ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ  {/why-we-recommend-frameworks/}

Create React App, Vite, Parcel๊ณผ ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ์—์„œ ๋ชจ๋“  ์š”์†Œ๋ฅผ ์ง์ ‘ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๋ฅผ ์ž˜ ์ˆ˜ํ–‰ ํ•˜๊ธฐ์—๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. Create React App ์ž์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, ์ด์ œ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ†ตํ•ฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ตœ์ƒ์˜ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œ ๋„๊ตฌ, ๋ Œ๋”๋ง, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ฐ ์ฝ”๋“œ ๋ถ„ํ• ์„ ํ†ตํ•ฉํ•˜๋Š” ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋„๊ตฌ๋“ค์„ "ํ”„๋ ˆ์ž„์›Œํฌ"๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” React ์ž์ฒด๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•˜์ง€๋งŒ, ์ด๋“ค์„ "๋ฉ”ํƒ€ํ”„๋ ˆ์ž„์›Œํฌ"๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ”„๋ ˆ์ž„์›Œํฌ๋Š” Create React App๊ณผ ๋™์ผํ•œ ์‹œ์ž‘ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์•ฑ์—์„œ ๊ฒฐ๊ตญ์—๋Š” ํ•ด๊ฒฐํ•ด์•ผ๋งŒ ํ•˜๋Š” ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๋ Œ๋”๋ง์€ ์„ ํƒ์ ์ž…๋‹ˆ๋‹ค {/server-rendering-is-optional/}

์ €ํฌ๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์€ ๋ชจ๋‘ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(CSR) ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

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

์„œ๋ฒ„ ๋ Œ๋”๋ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์— ๋” ์ ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ „์†กํ•˜๊ณ , ์™„์ „ํ•œ HTML ๋ฌธ์„œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ด ์ฐจ๋‹จ ์‹œ๊ฐ„(TBT)์„ ์ค„์ž„์œผ๋กœ์จ ๋” ๋น ๋ฅธ ์ตœ์ดˆ ์ฝ˜ํ…์ธ  ํŽ˜์ธํŠธ(FCP)๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์ด๋Š” ์ƒํ˜ธ์ž‘์šฉ์—์„œ ๋‹ค์Œ ํŽ˜์ธํŠธ๊นŒ์ง€(INP)๋„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด Chrome ํŒ€์ด ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์ตœ์ƒ์˜ ์„ฑ๋Šฅ์„ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์™„์ „ํ•œ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์ ‘๊ทผ ๋ฐฉ์‹๋ณด๋‹ค ์ •์  ๋˜๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ๊ณ ๋ คํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

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

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

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์–ด๋–ค๊ฐ€์š” {/server-components/}

์ €ํฌ๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋Š” React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

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

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

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ œ๋กœ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์†Œ๊ฐœ ๋ฐ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์„œ๋ฒ„ ๋ Œ๋”๋ง์€ SEO๋งŒ์„ ์œ„ํ•œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค {/server-rendering-is-not-just-for-seo/}

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

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

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


Dan Abramov์—๊ฒŒ Create React App์„ ๋งŒ๋“ค์–ด์ค˜์„œ ๊ฐ์‚ฌํ•˜๋ฉฐ, Joe Haddad, Ian Schmitz, Brody McKee, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์™ธ ๋งŽ์€ ๋ถ„๋“ค๊ป˜ ์˜ค๋žœ ๊ธฐ๊ฐ„ Create React App์„ ์œ ์ง€๋ณด์ˆ˜ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋˜ํ•œ, Brooks Lybrand, Dan Abramov, Devon Govett, Eli White, Jack Herrington, Joe Savona, Lauren Tan, Lee Robinson, Mark Erikson, Ryan Florence, Sophie Alpert, Tanner Linsley, ๊ทธ๋ฆฌ๊ณ  Theo Browne์—๊ฒŒ ์ด ๊ธ€์„ ๊ฒ€ํ† ํ•˜๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.