Unit5 - [React] React SPA

๊ฐ•์„ฑ์ผยท2023๋…„ 5์›” 22์ผ
0
post-thumbnail

โœ… TIL


React SPA ์˜ ๊ฐœ๋… & ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

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

์˜ˆ์‹œ ๊ทธ๋ฆผ์€ ๋™์ผํ•œ ํŽ˜์ด์ง€ ์ „ํ™˜์„ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋‹ค.

์ „ํ†ต์ ์ธ ์›น์‚ฌ์ดํŠธ๋Š” ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ๋กœ๋”ฉํ•˜๊ณ (๊นœ๋นก์ธ๋‹ค๊ณ  ํ‘œํ˜„),
SPA๋Š” Menu์™€ Footer์™€ ๊ฐ™์ด ํŽ˜์ด์ง€ ์ „ํ™˜ ์ „ํ›„์— ์ค‘๋ณต๋˜๋Š” ๋ถ€๋ถ„์€ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š๋Š”๋‹ค.

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

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

1990๋…„๋Œ€ ํ›„๋ฐ˜์— HTML ๋ฌธ์„œ ์ „์ฒด๊ฐ€ ์•„๋‹Œ, ์—…๋ฐ์ดํŠธ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์„œ๋ฒ„์—์„œ ์ „๋‹ฌ๋ฐ›์•„ ์ด ๋ฐ์ดํ„ฐ๋ฅผ JavaScript๊ฐ€ ๋™์ ์œผ๋กœ HTML ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•ด์„œ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์ด ๊ฐœ๋ฐœ๋˜์–ด ์‚ฌ์šฉ๋˜๊ธฐ ์‹œ์ž‘ํ•˜์˜€๋‹ค.

2000๋…„๋Œ€ ์ค‘๋ฐ˜๋ถ€ํ„ฐ ์ด๋Ÿฌํ•œ ๊ฐœ๋ฐœ ๋ฐฉ์‹์„ ์ด์šฉํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณดํŽธํ™”๋˜์—ˆ์œผ๋ฉฐ,
์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ ๋ฐฐ์šฐ๊ณ  ์žˆ๋Š” ์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ์ฆ‰ SPA์ด๋‹ค.


React SPA ๋ž€?

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


SPA ์žฅ์ 

์šฐ๋ฆฌ๊ฐ€ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” SNS๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ๋‹ค.

์นœ๊ตฌ๊ฐ€ ์˜ฌ๋ฆฐ ์‚ฌ์ง„์— "์ข‹์•„์š”"๋ฅผ ๋ˆ„๋ฅด๊ณ , ๋Œ“๊ธ€์„ ๋‹ฌ๊ณ , ๊ถ๊ธˆํ•  ๋• ๊ฒ€์ƒ‰์„ ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

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

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

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

์ด๋Ÿฐ SPA ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ๋Œ€ํ‘œ์ ์ธ ์„œ๋น„์Šค๋กœ๋Š” Youtube ๊ฐ€ ์žˆ๋‹ค.
์ด ๋ฐ–์— facebook, Gmail, airbnb, Netflix ๋“ฑ ์šฐ๋ฆฌ๊ฐ€ ์ผ์ƒ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค๋“ค์ด SPA ๋ฐฉ์‹์œผ๋กœ ์ œ์ž‘๋˜์–ด ์žˆ๋‹ค.

๋ฌผ๋ก  ์ด๋Ÿฌํ•œ SPA์—๋„ ๋‹จ์ ์€ ์žˆ๋‹ค.


SPA ๋‹จ์ 

๋ธŒ๋ผ์šฐ์ €๋Š” ์ฒซ ํ™”๋ฉด ๋กœ๋”ฉ ์‹œ์— HTML ํŒŒ์ผ์„ ์ฝ์–ด๋“ค์ธ ํ›„
๊ทธ ์•ˆ์˜ script ์š”์•ˆ์— ์žˆ๋Š” JavaScript ํŒŒ์ผ์„ ๋‹ค์‹œ ๋ฐ›์•„์˜ค๋Š” ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค.

์ด๋•Œ ์ฒซ ํ™”๋ฉด ๋กœ๋”ฉ ์‹œ ์ฝ์–ด๋“ค์ธ HTML ํŒŒ์ผ์€ ๊ฑฐ์˜ ๋น„์–ด์žˆ๊ณ ,
๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ๋Š” JavaScript ํŒŒ์ผ ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค ๋ณด๋‹ˆ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ JS ํŒŒ์ผ์ด ๋ฌด๊ฑฐ์›Œ์ง„๋‹ค.
๋•Œ๋ฌธ์— ์ด JavaScript ํŒŒ์ผ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„์œผ๋กœ ์ธํ•ด ์ฒซ ํ™”๋ฉด์˜ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง€๊ฒŒ ๋œ๋‹ค.

๋‘ ๋ฒˆ์งธ ๋‹จ์ ์œผ๋กœ๋Š” ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”๊ฐ€ ์ข‹์ง€ ์•Š๋‹ค.

๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”๋ž€ ๊ตฌ๊ธ€์ด๋‚˜ ๋„ค์ด๋ฒ„ ๊ฐ™์€ ๊ฒ€์ƒ‰์—”์ง„์ด ์ž๋ฃŒ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์ข‹๋„๋ก ์›น ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๋œปํ•œ๋‹ค.

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

๊ฒ€์ƒ‰ ๋กœ๋ด‡์€ ์ž๋ฃŒ๋ฅผ ์ˆ˜์ง‘ํ•  ๋•Œ์— ์›น ํŽ˜์ด์ง€์˜ URL์€ ๋ฌผ๋ก ์ด๊ณ  HTML ๋ฌธ์„œ ๋‚ด์˜ ๊ฐ์ข… ํƒœ๊ทธ๋‚˜ ๋งํฌ ๋“ฑ์„ ๋ถ„์„ํ•œ๋‹ค.

SPA๋Š” HTML์ด ๊ฑฐ์˜ ๋น„์–ด์žˆ๋‹ค ๋ณด๋‹ˆ ๊ฒ€์ƒ‰ ๋กœ๋ด‡์ด ์ถฉ๋ถ„ํ•œ ์ž๋ฃŒ๋ฅผ ์ˆ˜์ง‘ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค.

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

๋‹ค๋งŒ SPA์—์„œ๋„ ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”์— ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒ€์ƒ‰ ์—”์ง„์ด ๋ฐœ์ „ํ•˜๊ณ  ์žˆ์–ด์„œ, ์ ์ฐจ ์ด ๋‹จ์ ์€ ์‚ฌ๋ผ์ง€๊ณ  ์žˆ๋Š” ์ถ”์„ธ๋‹ค.



Wireframe


๋จผ์ € React์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‚˜๋ˆ„์–ด์•ผ ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์ปดํฌ๋„ŒํŠธ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์™œ ๊ณ ๋ฏผ์ด ํ•„์š”ํ•œ์ง€ ์ƒ๊ฐํ•ด๋ณด์ž.

Wireframe์€ ๋””์ž์ธ์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „ ๋‹จ๊ณ„๋กœ
์„ (wire)๋ฅผ ์ด์šฉํ•ด ์œค๊ณฝ์„ (frame)์„ ์žก๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

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

์ž, ์ด์ œ ์œ ํŠœ๋ธŒ ๊ฐœ๋ฐœ์ž์ธ ์—ฌ๋Ÿฌ๋ถ„์€ React๋ฅผ ์ด์šฉํ•ด
์–ด๋–ป๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์ง€ ์„ค๊ณ„๋ฅผ ํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์ž.

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

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

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



React Router

SPA๋Š” ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ์‚ฌ์‹ค ํ•œ ์ข…๋ฅ˜์˜ ํ™”๋ฉด๋งŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Twittler์™€ ๊ฐ™์€ SPA๋ฅผ ๋งŒ๋“ค ๋•Œ, ๋ฉ”์ธ ํŠธ์œ— ๋ชจ์Œ ํŽ˜์ด์ง€, ์•Œ๋ฆผ ํŽ˜์ด์ง€, ๋งˆ์ด ํŠธ์œ— ํŽ˜์ด์ง€ ๋“ฑ์˜ ํ™”๋ฉด์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ ์ด ํ™”๋ฉด์— ๋”ฐ๋ผ "์ฃผ์†Œ"๋„ ๋‹น์—ฐํžˆ ๋‹ฌ๋ผ์ง„๋‹ค.

์ด๋ ‡๊ฒŒ ๋‹ค๋ฅธ ์ฃผ์†Œ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ณผ์ •์„
"๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝํ•œ๋‹ค."๋ผ๋Š” ์˜๋ฏธ๋กœ ๋ผ์šฐํŒ…(Routing)์ด๋ผ๊ณ  ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ React ์ž์ฒด์—๋Š” ์ด ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค.
๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ฃผ์†Œ๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ค˜์•ผ ํ•œ๋‹ค.

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” React Router๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.

React Router์˜ ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ๋Š” ํฌ๊ฒŒ 3๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

๋ผ์šฐํ„ฐ ์—ญํ• ์„ ํ•˜๋Š” BrowserRouter, ๊ฒฝ๋กœ๋ฅผ ๋งค์นญํ•ด์ฃผ๋Š” Routes ์™€ Route,
๊ทธ๋ฆฌ๊ณ  ๊ฒฝ๋กœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” Link์ด๋‹ค.

์ด ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” React Router ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋”ฐ๋กœ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•œ๋‹ค.

๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

import๋Š” ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์—ญํ• ๋กœ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น(destructuring awssignment)๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ด์šฉํ•ด์„œ ๋ผ์šฐํŒ…์„ ํ•˜๋„๋ก ํ•˜์ž.

๋จผ์ € create-react-app ํ›„์—, React Router ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์„ค์น˜ํ•ด์ค€๋‹ค!

๊ทธ๋‹ค์Œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊บผ๋‚ด์˜ค๊ธฐ ์œ„ํ•œ import ๊ตฌ๋ฌธ์„ ๋„ฃ์–ด์ฃผ๊ณ ,
๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๋งํฌ์™€ ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•ด์ค€๋‹ค.


function App () {
  return (
   <BrowserRouter>
      <div>
        <nav>
          <ul>
            <li>
              Home
            </li>
            <li>
              MyPage
            </li>
            <li>
              Dashboard
            </li>
          </ul>
        </nav>

    {/* ์ฃผ์†Œ ๊ฒฝ๋กœ์™€ ์•„๊นŒ ๋งŒ๋“  3๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐํ•ด ์ค๋‹ˆ๋‹ค. */}
       {/* Routes ์ปดํฌ๋„ŒํŠธ๋Š” Route ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฐ์‹ธ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
        <Routes>
          {/* ๊ฒฝ๋กœ๋Š” path๋กœ ์ปดํฌ๋„ŒํŠธ๋Š” element๋กœ ์—ฐ๊ฒฐํ•ด ์ค๋‹ˆ๋‹ค. */}
          <Route path="/" element={<Home />} /> 
          <Route path="/mypage" element={<MyPage />} /> 
          <Route path="/dashboard" element={<Dashboard />} />
        </Routes>
      </div>
   </BrowserRouter>
  )
}

export default App;


๐Ÿ’ฌ Sprint Review


import React from "react";
import "./App.css";
import "./global-style.css";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
// TODO - react-router-dom์„ ์„ค์น˜ ํ›„, import ๊ตฌ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ BrowserRouter, Routes, Route ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์„ธ์š”.

import Sidebar from "./Sidebar";
import Tweets from "./Pages/Tweets";
import MyPage from "./Pages/MyPage";
import About from "./Pages/About";
// TODO - import๋ฌธ์„ ์ด์šฉํ•˜์—ฌ MyPage, About ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์„ธ์š”.

function App() {
  return (
    <BrowserRouter>
      <div>
        {/* TODO - BrowserRouter ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. */}
        <div className="App">
          <main>
            <Sidebar />
            <section className="features">
              <Routes>
                <Route path="/" element={<Tweets />} />
                <Route path="/about" element={<About />} />
                <Route path="/mypage" element={<MyPage />} />
              </Routes>
            </section>
          </main>
        </div>
      </div>
    </BrowserRouter>
  );
}

// ! ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ˆ˜์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
export default App;

import React from "react";
import { dummyTweets } from "../static/dummyData";
import "./MyPage.css";
// ! ์œ„ ์ฝ”๋“œ๋Š” ์ˆ˜์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

// TODO - import๋ฌธ์„ ์ด์šฉํ•˜์—ฌ Footer ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
import Footer from "../Footer";

const MyPage = () => {
  // TODO - filter ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ username์ด kimcoding์ธ ์š”์†Œ๋งŒ ์žˆ๋Š” ๋ฐฐ์—ด์„ filteredTweet์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.
  const filteredTweets = dummyTweets;

  let MypostDummy = dummyTweets.filter((post) => {
    //kimcoding ์ด ์“ด ํŠธ์œ—๋“ค
    return post.username === "kimcoding";
  });

  return (
    <section className="myInfo">
      <div className="myInfo__container">
        <div className="myInfo__wrapper">
          <div className="myInfo__profile">
            <img src={filteredTweets[0].picture} />
          </div>
          <div className="myInfo__detail">
            <p className="myInfo__detailName">
              {filteredTweets[0].username} Profile
            </p>
            <p>28 ํŒ”๋กœ์›Œ 100 ํŒ”๋กœ์ž‰</p>
          </div>
        </div>
      </div>
      <ul className="tweets__mypage">
        {/* let isKimcoding =  */}

        {/* TODO : dummyTweets์ค‘ kimcoding ์ด ์ž‘์„ฑํ•œ ํŠธ์œ— ๋ฉ”์„ธ์ง€๋งŒ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
        {MypostDummy.map((post) => {
          console.log(post);
          console.log(post.id);
          return (
            <li className="tweet" key={post.id}>
              <div className="tweet__profile">
                <img src={post.picture} />
              </div>
              <div className="tweet__content">
                <div className="tweet__userInfo">
                  <span className="tweet__username">{post.username}</span>
                  <span className="tweet__createdAt">{post.createdAt}</span>
                </div>
                <div className="tweet__message">{post.content}</div>
              </div>
            </li>
          );
        })}
      </ul>

      <Footer />
    </section>
  );
};

export default MyPage;
profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€