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

 

1. SPA์™€ ๋ผ์šฐํ„ฐ์˜ ๊ด€๊ณ„ 

• SPA๋Š” ์„œ๋ฒ„์— ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋งŒ ์š”์ฒญํ•˜์—ฌ ์ „์ฒด ์›น์•ฑ์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋•Œ ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋Š” CSR, AJAX ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜์—ฌ, ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ๋ฆฌ๋กœ๋“œ ์—†์ด ๋ผ์šฐํŒ…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. 

• MPA์™€ ๋‹ค๋ฅด๊ฒŒ, ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ํ•˜๋‚˜์˜ ์•ฑ์˜ ๊ตฌ์„ฑ์š”์†Œ๋กœ ๋ณด๊ณ , ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ ๊ฐ„์˜ ์Šคํƒ€์ผ, ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•œ๋‹ค.

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

SPA์˜ ๊ธฐ์ˆ ์  ์žฅ์ 

• ์„œ๋ฒ„์—์„œ ํŽ˜์ด์ง€๋ฅผ(์„œ๋ฒ„ ๋žœ๋”๋ง) ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ CDN์— ์บ์‹ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

• ๋งค๋ฒˆ ํŽ˜์ด์ง€ ์š”์ฒญ์„ ํ•  ํ•„์š”๊ฐ€ ์—†์–ด ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ์ค„์–ด๋“ ๋‹ค.

• ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๋“ฑ์„ ์บ์‹ฑํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋“ฑ ์ œ์•ฝ ์กฐ๊ฑด์ด ์ค„์–ด๋“ ๋‹ค.

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

SPA์˜ ๊ธฐ์ˆ ์  ๋‚œ๊ด€๋“ค

• MPA๋ฐฉ์‹ ๋ณด๋‹ค๋Š” Search Engine Optimization์— ๋ถˆ๋ฆฌํ•˜๋‹ค.

• ํ•˜๋‚˜์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์•ฑ์ด ์ง€์†ํ•˜๋ฏ€๋กœ, ๋ฐ์ดํ„ฐ ํ™œ์šฉ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ์„ฑ๋Šฅ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

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

MPA ๋ž€? 

• Multi Page Application์€ ์„œ๋ฒ„์— ๋ฏธ๋ฆฌ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ๋‘๊ณ , ์œ ์ €๊ฐ€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์‹œ ์š”์ฒญ์— ์ ํ•ฉํ•œ ํŽ˜์ด์ง€๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

• ๋ฏธ๋ฆฌ ์„œ๋ฒ„์—์„œ ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ ๋นŒ๋“œํ•ด ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „์†ก๋œ๋‹ค.

• ์„œ๋ฒ„์— ๋ผ์šฐํŒ…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๊ณ , ์„œ๋ฒ„์—์„œ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

• ํŽ˜์ด์ง€ ์š”์ฒญ๋งˆ๋‹ค ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ๋‹ค์‹œ ๋ฐ›์•„์˜ค๋ฏ€๋กœ, ํŽ˜์ด์ง€ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌํ™œ์šฉํ•˜๊ธฐ ํž˜๋“ค๋‹ค.

SPA์—์„œ์˜ ๋ผ์šฐํŒ…

• ์ฃผ๋กœ HTML5์˜ History API (ํ˜น์€ URL Hash)๋ฅผ ์ด์šฉํ•ด ํŽ˜์ด์ง€ ๋ฆฌ๋กœ๋“œ ์—†๋Š” ํŽ˜์ด์ง€ ์ „ํ™˜์„ ๊ตฌํ˜„ํ•œ๋‹ค

• hashRouter: URL์— #๊ฐ€ ๋ถ™๋Š”๋‹ค. ํ•˜์ง€๋งŒ github page๊ฐ™์€ ๊ณณ์—์„œ ๋นŒ๋“œํ•  ๋•Œ ์œ ๋ฆฌํ•˜๋‹ค

• history, location ๋“ฑ HTML5 API๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

• visibilitychange, popstate, beforeunload ๋“ฑ window event๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ์ „ํ™˜ ์ด๋ฒคํŠธ ์‹œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜์—ฌ ํ™œ์šฉํ•œ๋‹ค.

• react-router, reach-router ๋“ฑ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด, ๋ผ์šฐํŒ… ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

2. react-router 

• React์˜ JSX๋ฅผ ์ด์šฉํ•˜๊ฑฐ๋‚˜, History API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•œ๋‹ค.

Declarative routing ๋ฐฉ๋ฒ•: JSX: <Link to ="/path"></Link>

Imperative routing ๋ฐฉ๋ฒ•: History API:  push('/path')

• ์›น์—์„œ๋Š” react-router-dom์„ ์‚ฌ์šฉํ•œ๋‹ค. (react-router-native)

• ์ ์šฉ ์‹œ, ์„œ๋ฒ„์˜ ๋ชจ๋“  path์—์„œ ๊ฐ™์€ ์•ฑ์„ ์„œ๋น™ํ•˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

 

3. react-router-dom ์‚ฌ์šฉํ•˜๊ธฐ

• <BrowserRouter>๋กœ ๊ฐ์‹ธ Router Context๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.

• Route๋กœ path๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ทธ ์•ˆ์— ๋ Œ๋”๋งํ•˜๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ๋Š”๋‹ค.

• Link๋กœ ํŠน์ • ํŽ˜์ด์ง€๋กœ ์ด๋™ ์‹œ, ๋ฆฌ๋กœ๋“œ ์—†์ด ํŽ˜์ด์ง€๊ฐ€ ์ด๋™ํ•œ๋‹ค.

• Switch๋กœ, ๋งค์นญ๋˜๋Š” ๋ผ์šฐํŠธ ํ•˜๋‚˜๋ฅผ ๋ Œ๋”๋งํ•˜๊ฒŒ ํ•œ๋‹ค.

 

1) BrowserRouter

• HTML5์˜ History API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, UI์™€ URL์˜ ์‹ฑํฌ๋ฅผ ๋งž์ถ”๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

• ๋ชจ๋“  URL์— ๋Œ€ํ•ด ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„œ๋ฒ„ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.

• ๋ชจ๋“  path ์•ž์˜ basename์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ex) basename="/ko"  ๋‹ค๊ตญ์–ด์ง€์›

• forceRefresh๋กœ, ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ๋ฆฌํ”„๋ ˆ์‹œํ•  ๊ฒƒ์ธ์ง€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

<BrowserRouter>
	<Switch>
    	<Route path="/about"><AboutPage/></Route>
        <Route path="/contact"><ContacPage/></Route>
        <Route path="/"><HomePage/></Route>
    </Switch>
</BrowserRouter>

2) Link, NavLink, Redirect

Link

• Link ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ฆญํ•˜๋ฉด ๋‹ค๋ฅธ ์ฃผ์†Œ๋กœ ์ด๋™์‹œํ‚จ๋‹ค.
๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ• ๋• <a> ํƒœ๊ทธ ๋Œ€์‹  <Link> ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.
a ํƒœ๊ทธ์˜ ๊ธฐ๋ณธ์ ์ธ ์†์„ฑ์€ ํŽ˜์ด์ง€๋ฅผ ์ด๋™์‹œํ‚ค๋ฉด์„œ, ํŽ˜์ด์ง€๋ฅผ ์•„์˜ˆ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์—, ๋ฆฌ์•กํŠธ ์•ฑ์ด ์ง€๋‹ˆ๊ณ ์žˆ๋Š” ์ƒํƒœ๋“ค๋„ ์ดˆ๊ธฐํ™”๋˜๊ณ , ๋ Œ๋”๋ง๋œ ์ปดํฌ๋„ŒํŠธ๋„ ๋ชจ๋‘ ์‚ฌ๋ผ์ง€๊ณ  ์ƒˆ๋กœ ๋ Œ๋”๋ง์„ ํ•˜๊ฒŒ๋œ๋‹ค.

• <Link> ์ปดํฌ๋„ŒํŠธ๋Š” HTML5 History API ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ๋งŒ ๋ฐ”๊ฟ€๋ฟ, ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ์˜ค์ง€๋Š” ์•Š๋Š”๋‹ค.

NavLink

• to prop์„ ํŠน์ • URL๋กœ ๋ฐ›์•„, ํด๋ฆญ ์‹œ ๋„ค๋น„๊ฒŒ์ด์…˜ ํ•œ๋‹ค.

• NavLink์˜ ๊ฒฝ์šฐ, ๋งค์นญ ์‹œ ์–ด๋–ค ์Šคํƒ€์ผ์„ ๊ฐ€์งˆ์ง€ ๋“ฑ์˜ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. (ํ˜„์žฌ path์— ๋”ฐ๋ผ ์Šคํƒ€์ผ ์ ์šฉ ๊ฐ€๋Šฅ)

• to์— location object๋‚˜ ํ•จ์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

Redirect

• Link์™€ ๋น„์Šทํ•˜๋‚˜, ๋ Œ๋”๋ง๋˜๋ฉด to prop์œผ๋กœ ์ง€์ •ํ•œ path๋กœ ์ด๋™ํ•œ๋‹ค.

• Switch ์•ˆ์—์„œ ์“ฐ์ผ ๊ฒฝ์šฐ, from, to๋ฅผ ๋ฐ›์•„ ์ด๋™ํ•˜๊ฒŒ ๋งŒ๋“ฆ. ex) from="/" to="/login"

<Link to="/about"><aboutPage></Link>

 

3) Route

<BrowserRouter>
      <Navigation />
      <Route path="/" exact={true}><Home /></Route>
      <Route path="/about" component={About} />
      <Route path="/movie/:id" render={(props) => props.id > 10 ? <Deatails> : ""} />
</BrowserRouter>
  • ๋ผ์šฐํ„ฐ๋Š” ์ƒ์œ„ path๊ฐ€ ์žˆ์œผ๋ฉด ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต๋œ๋‹ค.
  • path์™€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งค์นญํ•œ๋‹ค.
  • ๋งค์นญ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” children์œผ๋กœ ๋„ฃ์–ด์ฃผ๊ฑฐ๋‚˜, component prop์œผ๋กœ ๋„˜๊ธด๋‹ค.
  • render prop์œผ๋กœ ๋งค์นญ๋˜์—ˆ์„ ๋•Œ ์‹ค์ œ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋žœ๋”๋งํ• ์ง€ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Router๋กœ ๋žœ๋”๋ง ๋˜๋Š” ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋Š” match, location, history๋ฅผ prop์œผ๋กœ ๋ฐ›๋Š”๋‹ค.

 

4) switch

• ์—ฌ๋Ÿฌ Route ์ค‘ ๋งค์น˜๋˜๋Š” Route ์œ„์—์„œ๋ถ€ํ„ฐ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ Œ๋”๋งํ•œ๋‹ค.

• ๋งค์นญ๋˜๋Š” Route๊ฐ€ ์—†์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋ณด์—ฌ์ฃผ์ง€ ์•Š๋Š”๋‹ค. fallback์šฉ์œผ๋กœ 404 Not Found Page๋ฅผ ๋งจ ์•„๋ž˜์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค

• path="/"์˜ ๊ฒฝ์šฐ ๋ชจ๋“  path์— ๋งค์นญ๋˜๋ฏ€๋กœ exact ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๊ฐ€์žฅ ์•„๋ž˜๋กœ ๋‚ด๋ฆฐ๋‹ค.

<Switch>
  <Route exact path='/'>
    <Home mbtiArray={mbtiArray} />
  </Route>
  <Route path='/chat'>
    <Chat userObj={userObj} />
  </Route>
  <Route path='/profile'>
    <Profile userObj={userObj} typeInit={typeInit} />
  </Route>
  <Route>
    <Redirect to='/' />
  </Route>
</Switch>;

5. useHistory, useLocation, useParams, useRouteMatch

์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„, hook์œผ๋กœ react-router ๊ด€๋ จ ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ.

• history, location, params, match ๊ฐ์ฒด์— ์ ‘๊ทผํ•จ.

 

6. Private Router

ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜์ง€ ์•Š์•˜์„ ๋•Œ, ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ Redirect ํ•˜๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
• ์œ ์ €์˜ ์ƒ์„ธ ํŽ˜์ด์ง€, ๊ฐœ์ธ์ •๋ณด ๋ณ€๊ฒฝ ํŽ˜์ด์ง€ ๋“ฑ์„ ์ด๋™ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

Declartive ๋ฐฉ๋ฒ•

function PrivateRoute({ component: Component, ...props }) {
  return (
    <Route
      {...props}
      render={(props) => {
        const isLoggedIn = !!getUserInfo();
        if (!isLoggedIn) {
          return <Redirect to='/login' />;
        }
        return <Component {...props} />;
      }}
    ></Route>
  );
}

Imperative ๋ฐฉ๋ฒ•

function usePrivateRoute(validateFunc) {
  //  imperative
  const history = useHistory();
  useEffect(() => {
    if (!validateFunc()) {
      history.push('/login');
    }
  }, []);
}

6. query string

function App() {
  ...
  return (
    <Link to='/contact?email=example@example.com&address=Seoul'>Contact</Link>
  );
}
function ContactPage() {
  const location = useLocation();
  const searchParams = new URLSearchParams(location.search);
  
  const email = searchParams.get('email'); // query์˜ key๊ฐ’์„ ์ด์šฉ
  const address = searchParams.get('address');
  
  return (
    <PageLayout header='Contact Page'>
      <em>{email}</em>
      <br />
      <strong>{address}</strong>
    </PageLayout>
  );
}

• URL์˜ query string ์ •๋ณด๋ฅผ ํ™œ์šฉํ•ด ์•ฑ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

• URLSearchParamsAPI, useLocation์„ ํ™œ์šฉํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•