์žฌ๋ฐŒ๊ฒŒ ํ•ฉ์‹œ๋‹ค

๊ธฐ๋กํ•˜๊ธฐ, ๊ฐ€์‹œํ™”ํ•˜๊ธฐ

Vanilla JS

Vanilla Javascript๋กœ SPA ๊ตฌํ˜„ํ•˜๊ธฐ(ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ์‡ผํ•‘๋ชฐ SPA)

์€๋˜๋”” 2022. 11. 11. 02:50

โœ… SPA(Single Page Application) ์ดํ•ดํ•˜๊ธฐ

ํŽ˜์ด์ง€ ์ด๋™์˜ ๊ณผ์ •์„ ๊ฐ€์žฅ ๋‹จ์ˆœํ•˜๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ๋กœ์šด url์„ ์š”์ฒญํ•œ๋‹ค. (์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜, ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ๋“ฑ)
  2. ์š”์ฒญํ•œ url์— ๋งž๋Š” ๋ฆฌ์†Œ์Šค(html, css, js)๋ฅผ
  3. ํ™”๋ฉด์— ๋ Œ๋”๋งํ•œ๋‹ค.


๊ฐ„๋‹จํ•˜์ฃ ?

MPA(Multiple Page Application), SPA(Single Page Application) ๋ชจ๋‘ ํŽ˜์ด์ง€ ์ด๋™์˜ ๊ณจ์ž๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ MPA์™€ SPA๋กœ ๊ตฌ๋ถ„์ด ๋ฉ๋‹ˆ๋‹ค.

 

MPA์˜ ๋ฆฌ์†Œ์Šค ์š”์ฒญ ๋ฐฉ์‹

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ๋กœ์šด url์„ ์š”์ฒญ
  2. ํ•ด๋‹น url์— ๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์„œ๋ฒ„์— ์š”์ฒญ
  3. ์„œ๋ฒ„์—์„œ ๋ฐ›์€ ์‘๋‹ต์œผ๋กœ ํ™”๋ฉด์„ ๋ Œ๋”๋ง

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

์•ต์ปค(a) ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•œ ํŽ˜์ด์ง€ ์ด๋™ ๋ฐฉ์‹์„ ๋– ์˜ฌ๋ฆฌ๋ฉด ์ดํ•ด๊ฐ€ ๋˜์‹ค๊ฒ๋‹ˆ๋‹ค.

<nav>
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/service.html">Service</a></li> 
        <li><a href="/about.html">About</a></li>
        // ํด๋ฆญ ์‹œ ์„œ๋ฒ„์— '/about.html'์— ํ•ด๋‹นํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญ
    </ul>
</nav>

์ฐธ๊ณ ๋กœ ํ•ด๋‹น ๋ฐฉ์‹์€ ์„œ๋ฒ„ ๋‹จ์—์„œ ์™„์„ฑํ•ด์ค€ html์„ ๊ทธ๋Œ€๋กœ ๋ Œ๋”๋งํ•œ๋‹ค๋Š” ์ ์—์„œ SSR(Server Side Rendering)์ด๋ผ๊ณ ๋„ ์นญํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด SPA์˜ ๋ฆฌ์†Œ์Šค ์š”์ฒญ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

SPA์˜ ๋ฆฌ์†Œ์Šค ์š”์ฒญ ๋ฐฉ์‹

  1. ์ฒซ ํŽ˜์ด์ง€ ์š”์ฒญ ์‹œ, ํ•ด๋‹น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์„œ๋ฒ„์— ์š”์ฒญ
  2. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ๋กœ์šด url์„ ์š”์ฒญ
  3. ํ•ด๋‹น url์— ๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™์ ์œผ๋กœ ์ƒ์„ฑ(1๋ฒˆ์—์„œ ๋ฐ›์€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™œ์šฉํ•ด์„œ)
  4. ์ƒ์„ฑํ•œ ๋ฆฌ์†Œ์Šค๋กœ ํ™”๋ฉด์„ ๋ Œ๋”๋ง

“url์„ ์š”์ฒญํ•˜๋ฉด url์— ๋งž๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๋ณด๋‚ด์ค€๋‹ค” ๋ผ๋Š” ์„œ๋ฒ„์˜ ์—ญํ• ์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ผ์ • ๋ถ€๋ถ„ ๋Œ€์ฒดํ–ˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”! ์ƒˆ๋กœ๊ณ ์นจ ์—†์ด ํ•œ ํŽ˜์ด์ง€ ๋‚ด์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ”๊ฟ” ๋ผ์šฐ๊ธฐ๋งŒ ํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ Single Page Application์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.


๐Ÿ’๐Ÿป‍โ™€๏ธ ๋ผ์šฐํŒ…์ด๋ž€?

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

 

์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ URL ๋˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ํ•ด์„ํ•ด, ํŽ˜์ด์ง€๋ฅผ ์ „ํ™˜ํ•˜๋Š” ์ผ๋ จ์˜ ํ–‰์œ„

 

์‚ฌ์šฉ์ž์˜ ํ–‰์œ„์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž๋ฅผ ์•Œ๋งž์€ ๊ฒฝ๋กœ๋กœ ๋ณด๋‚ด์ฃผ๋Š” ๊ฒƒ! ์ •๋„๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”. "route"์˜ ์‚ฌ์ „์  ์ •์˜์™€๋„ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด router ๋ผ๋Š” ๊ฒƒ์€ route๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋„๊ตฌ๋ฅผ ์˜๋ฏธํ•˜๊ฒ ๋„ค์š”.

 

route์˜ ์‚ฌ์ „์  ์ •์˜

 

๐Ÿ’ก ๊ตฌํ˜„ ํ•ต์‹ฌ ์•„์ด๋””์–ด

SPA์™€ ๋ผ์šฐํŒ…์— ๋Œ€ํ•ด ์ดํ•ดํ•˜์…จ๋‹ค๋ฉด, ์ด์ œ ๊ตฌํ˜„์„ ํ•ด๋ด…์‹œ๋‹ค! ๊ตฌํ˜„์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

routes ๋ฐฐ์—ด

url(path)๊ณผ ์ปดํฌ๋„ŒํŠธ๋ฅผ 1:1 ๋งคํ•‘ํ•˜๋Š” ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. routes ๋ผ๊ณ  ์นญํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด๋•Œ ์ปดํฌ๋„ŒํŠธ๋Š” ์œ„์—์„œ ๋งํ–ˆ๋˜ ๋ฆฌ์†Œ์Šค(html, css, js)์˜ ์ง‘ํ•ฉ์ฒด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ .

 

AngularJS์˜ ์ •์  ๋ผ์šฐํŒ… ์˜ˆ์‹œ

 

url์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ ๊ต์ฒดํ•˜๊ธฐ

url์— ๋”ฐ๋ผ main.App ์š”์†Œ์˜ innerHTML์„ ๊ต์ฒด ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ 1๋ฒˆ์—์„œ ์„ ์–ธํ•œ routes ๋ฐฐ์—ด์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ‘/about’ ์ด๋ผ๋Š” url์ด ์š”์ฒญ๋๋‹ค๋ฉด, routes ๋ฐฐ์—ด์—์„œ ‘/about’์— ํ•ด๋‹นํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐพ์•„ main.App ์˜ ํ•˜์œ„์— ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.


ํ•œ ํŽ˜์ด์ง€ ๋‚ด์—์„œ ๋ฆฌ์†Œ์Šค๋งŒ ๊ฐˆ์•„๋ผ์šด๋‹ค ๋ผ๋Š” ๋ง์ด ์ด์ œ ์ดํ•ด๊ฐ€ ๋˜์‹œ๋‚˜์š”?

// index.html
<html>
  <body>
    <main class="App"></main> // ์ด ์š”์†Œ์˜ innerHTML์„ ๋ณ€๊ฒฝํ• ๊ฒ๋‹ˆ๋‹ค.
    <script type="module" src="./src/main.js"></script>
  </body>
</html>

 

History API๋กœ url ๋ณ€๊ฒฝ ์š”์ฒญํ•˜๊ธฐ

์ฃผ์†Œ์ฐฝ์˜ url์„ ๋ณ€๊ฒฝํ•˜๋˜, ์„œ๋ฒ„๋กœ ์ง์ ‘ http ์š”์ฒญ์„ ๋ณด๋‚ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. (๊ทธ๊ฑด SPA๊ฐ€ ์•„๋‹ˆ๋‹ˆ๊นŒ์š”!) ์–ด๋–ป๊ฒŒ ์„œ๋ฒ„ ์š”์ฒญ ์—†์ด url๋งŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?


History API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค! History ๊ฐ์ฒด๋Š” Web API์˜ ์ผ์ข…์œผ๋กœ, Window ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. history ๊ฐ์ฒด์˜ pushState ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์†Œ์ฐฝ์˜ url์„ ๋ณ€๊ฒฝํ•˜๊ณ , ํ•ด๋‹น url์„ ๋ธŒ๋ผ์šฐ์ €์˜ ์„ธ์…˜ ๊ธฐ๋ก์— ์ถ”๊ฐ€ํ•˜์ง€๋งŒ, ์„œ๋ฒ„๋กœ http ์š”์ฒญ์„ ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.


๋”ฐ๋ผ์„œ ์•ต์ปค ํƒœ๊ทธ ๋Œ€์‹  history.pushState() ๋ฅผ ์‚ฌ์šฉํ•ด url์„ ๋ณ€๊ฒฝํ•˜๊ณ , ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•ด ๋ณ€๊ฒฝ๋œ url์— ๋งž๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ routes ๋ฐฐ์—ด์—์„œ ์ฐพ์•„ ๋ Œ๋”๋ง ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป ์‹ค์ œ ๊ตฌํ˜„

 

index.html, main.js, ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ

์šฐ์„  index.html ํŒŒ์ผ์„ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค! head ํƒœ๊ทธ๋Š” ํŽธ์˜์ƒ ์ƒ๋žตํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

Home, About ํŽ˜์ด์ง€์— ํ•ด๋‹นํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค๋„ ๋งŒ๋“ค์–ด์ค„๊ฒŒ์š”. ๊ฐ ํŒŒ์ผ์—์„œ ๋‚ด๋ณด๋‚ธ(export) ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋“ค์„ ์ถ”ํ›„์— routes ๋ฐฐ์—ด์— ๋“ฑ๋ก ํ•ด์ค„๊ฑฐ์˜ˆ์š”. template ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ ๋งˆํฌ์—…์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. 

 

 

routes ๋ฐฐ์—ด ์ƒ์„ฑ

path์™€ ์ปดํฌ๋„ŒํŠธ์˜ ๋งคํ•‘ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” routes ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค. ์ € ๊ฐ™์€ ๊ฒฝ์šฐ path๋ช…์œผ๋กœ ๋ฐ”๋กœ ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์–ด์„œ ๋ฐฐ์—ด ๋Œ€์‹  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค~

 

์•ฑ์˜ ์ฒซ ๊ตฌ๋™ ์‹œ์—๋Š” "/" ์— ํ•ด๋‹นํ•˜๋Š” Home ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง ํ•ฉ๋‹ˆ๋‹ค.

 

history.pushState๋ฅผ ์ด์šฉํ•œ url๋ณ€๊ฒฝ ๊ตฌํ˜„

Home, About ํŽ˜์ด์ง€์˜ ๋ฒ„ํŠผ์ด ํด๋ฆญ๋์„ ๋•Œ ์ด changeUrl ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ๋ฆฌ์Šค๋„ˆ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๋“ฑ๋กํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

nlf๋ฒ„ํŠผ ํด๋ฆญ์„ ํ†ตํ•œ ํŽ˜์ด์ง€ ์ด๋™์ด ์ž˜ ๋˜๋Š” ๋ชจ์Šต

url๊ณผ ํ™”๋ฉด์ด ์ž˜ ๋ณ€๊ฒฝ๋˜๊ณ  ์žˆ์ฃ ?

 

๋’ค๋กœ๊ฐ€๊ธฐ ๊ตฌํ˜„

๋’ค๋กœ๊ฐ€๊ธฐ์˜ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ € ์ž์ฒด์˜ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ํ†ตํ•ด ์ด๋ค„์ง€๊ธฐ ๋•Œ๋ฌธ์—, ๋”ฐ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. popstate ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ๋’ค๋กœ๊ฐ€๊ธฐ์˜ ๋ฐœ์ƒ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋’ค๋กœ๊ฐ€๊ธฐ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, window.location.pathname ์„ ์‚ฌ์šฉํ•ด ๋ณ€๊ฒฝ๋œ url์„ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค. ํ•ด๋‹น url๋กœ changeUrl ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. 

 

๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ํ†ตํ•œ ํŽ˜์ด์ง€ ์ด๋™์ด ์ž˜ ๋˜๋Š” ๋ชจ์Šต

 

โœจ ์ „์ฒด ์ฝ”๋“œ

 


 

์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•œ ๋ฐฉ์‹์œผ๋กœ SPA๋ฅผ ๊ตฌํ˜„ํ•ด๋ดค์Šต๋‹ˆ๋‹ค! ํ˜„์žฌ๋Š” ํŽธ์˜์ƒ main.js ๋‚ด์— ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ–ˆ์ง€๋งŒ, ์ถ”ํ›„์—๋Š” ๋ผ์šฐํŒ… ๊ธฐ๋Šฅ์— ํ•ด๋‹นํ•˜๋Š” ์ฝ”๋“œ๋“ค์„ ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ด ๋ณด์ž…๋‹ˆ๋‹ค. ๋˜ window ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ์— ์ด๋ฒคํŠธ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ถ€์ฐฉํ•˜๋Š” ๊ฒƒ์ด ์ข€ ๋” ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์„๊นŒ ์‹ถ๋„ค์š”:) ์ด ๊ธ€์ด ๋„์›€์ด ๋˜์…จ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค!