νλ‘ νΈ κΈ°μ μλμ κ°ννκΈ° μν΄ JavaScript κΈ°λ° SPA νλ‘μ νΈλ₯Ό μ§ννμ΅λλ€. μλ² νλ‘μ νΈλ₯Ό μ§ννλ©΄μ 리μνΈ, λ·°μμ μ¬μ©νλ μΉν©, λΌμ°ν° λ±μ κΈ°μ μ΄ μ μ¬μ©νλμ§, μ΄λ€ μλ¦¬λ‘ λμλλμ§ λ°°μλ³Ό μ μμλ κ²½νμ΄μκ³ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ§ μκ³ μμ μλ°μ€ν¬λ¦½νΈλ§μ μ΄μ©ν΄ μ¬λ¬ λ‘μ§μ κ³ λ―Όνλ©° μΉκ°λ°μλ‘μ νμΈ΅ μ±μ₯ν μ μλ κΈ°νμλ€κ³ μκ°ν©λλ€.
κΈμ μμλ ν¬κ² μλμ κ°μ΄ μ§ννκ² μ΅λλ€.
- SPA κ°λ°μ μ¬μ©ν κΈ°μ μκ°
- μ£Όμ λ‘μ§
SPA? μλ°μ€ν¬λ¦½νΈλ§μΌλ‘ μ΄λ»κ² κ°λ°νμ§
κ·Έλμ νλ‘ νΈ κ°λ°μ ν΄μ€λ©΄μ 리μνΈ, λ·° λΌμ΄λΈλ¬λ¦¬λ₯Ό μ΄μ©ν΄ μ무 μκ° μμ΄ μ½λλ₯Ό μ§λ€λ³΄λ, μ μ SPA κΈ°μ μ΄ μ΄λ»κ² λμλλμ§ λͺ¨λ₯΄λ κ²½μ°κ° μμ΅λλ€. μ΄λ¬ν μν©μμ κ°μκΈ° μλ°μ€ν¬λ¦½νΈλ§μΌλ‘ κ°λ°μ΄ μ£Όμ΄μ§ κ²½μ° λ§μ°ν μ΄λ ΅κ²λ§ λ€κ°μμ΅λλ€. κ·Έλμ μ§μ§ λΌμ΄λΈλ¬λ¦¬ λμμμ΄ μμ μλ°μ€ν¬λ¦½νΈλ§μ μ΄μ©ν κ°λ°μ μλνμ΅λλ€.
κ·Έλμ μ νν λ°©λ²μ΄ hash(Hash History)
λ°©μ!
μλ°μ€ν¬λ¦½νΈλ§μΌλ‘ SPA κ°λ°νλ λ°©μμ ν¬κ² 2κ°μ§κ° μμ΅λλ€. νλλ history(Browser History), λνλλ hash λ₯Ό μ΄μ©ν΄ SPAλ₯Ό ꡬνν μκ° μμμ΅λλ€. μ¬κΈ°μ μ λ hash
λ°©μμ μ νν΄μ νλ‘μ νΈλ₯Ό μ§ννμ΅λλ€.
κ·Έ μ΄μ λ μλ°μ€ν¬λ¦½νΈλ§μΌλ‘ μ μ μΉμλ²μ λ°°ν¬λ₯Ό ν΄λ³΄κ³ μΆμκΈ° λλ¬Έμ λλ€. history λ°©μμ express μλ² κ΅¬μΆμ΄ νμνκΈ°μ μ λ μλ² κ΅¬μΆμ΄ νμμλ hash λ°©μμ μ ννμ΅λλ€.
hash
μ¬μ©ν΄ SPA κ°λ°ν΄λ³΄μ
ν¬κ² λ‘μ§μ μλμ κ°μ κ΅¬μ‘°λ‘ μ§νλκ² λ©λλ€. μ¬κΈ°μ hash
λ User μμ²μ λμ
λΆλΆμΈ λΌμ°ν°μ μμΉνκ² λ©λλ€.
μμ²μ 첫 μμμ Navigation
μ¬κΈ°μ hash
μ μν μ΄ κΆκΈν κ»λλ€. hashλ #
μ΅μ»€λ₯Ό ν΅ν΄ μ΄λνλ λ°©λ²μΌλ‘ site/#path
μ κ°μ΄ urlμ΄ ννλ©λλ€. λ³΄ν΅ μ μ νμ΄μ§μμ μ¬μ©λλ©° λΈλ‘κ·Έμ μ£Ό μ λͺ©μ ν΄λ¦ ν μ΅μ»€ μ΄λ μ urlμ #
μ΄ λΆλ λͺ¨μ΅μ λ³΄μ€ μ μμ΅λλ€.
window.addEventListener("hashchange", () => {
router(window.location.hash);
})
const router = (route) => {
rootContent.innerHTML = '';
switch (route) {
case '#/':
return rootContent.appendChild(pages.home());
case '#/detail':
return rootContent.appendChild(pages.detail());
case '#/post':
return rootContent.appendChild(pages.post());
default:
return rootContent.appendChild(pages.notFound());
}
}
window.location.hash
μ΄μ©ν΄ λΌμ°ν
λ³κ²½μ΄ λλ©° μ΄λ hash λ³κ²½ μ hashchange
μ΄λ²€νΈκ° λ°μνκΈ° λλ¬Έμ λΌμ°ν
μ΄ κ°λ₯ν΄μ§λλ€.
Controller
μνλ νμ΄μ§ μμ±λκ²λ ν΄μ£Όμ
ν΄λΉ hashμ λ§λ κ²½λ‘λ‘ μ΄λ μ νμ΄μ§λ₯Ό 보μ¬μ£Όλ λ°©λ²μ λλ€. μμ ꡬ쑰μ κ°μ΄ λΌμ°ν μ κ±°μ³ μ»¨νΈλ‘€λ¬μ μμ²μ΄ λ€μ΄κ°μ§κ² λ©λλ€. λ€μμΌλ‘ μμ²μ λ§λ νμ΄μ§ μμ±μ μν μλΉμ€ λ‘μ§μ΄ μ€νλκ² λ©λλ€.
// μ€λͺ
μ μν μ΅μνμ μ½λμ
λλ€. ν΄λΉ μ½λμ μ€μ axiosλ₯Ό μ΄μ©ν λ°μ΄ν° μ²λ¦¬ λ‘μ§λ λ΄κ²λ©λλ€.
import views from '../views/post/post.html'
export default () => {
const divElement = document.createElement('div')
divElement.classList = "post-section";
divElement.innerHTML = views;
return divElement;
}
μ½λμ λ³΄μ€ μ μλ―μ΄ ν΄λΉ μλ λ¨ΌνΈλ₯Ό μμ± ν μμλ€ λ―Έλ¦¬ μμ±λ html
λ·°λ₯Ό μ§μ΄λ£λ λ°©μμΌλ‘ νμ΄μ§ κ΅μ²΄κ° μ§νλκ² λ©λλ€.
μΆκ°λ‘ history(browser hisotry) λ?
url ννλ site/path
μ κ°μ΄ ννλλ©° μ΄ λ°©λ²μ μλ² μΈ‘ μ§μμ΄ μΌλΆ νμν©λλ€. μλ₯Ό λ€μ΄ μ‘΄μ¬νμ§ μλ κ²½λ‘λ‘ μ μν κ²½μ° μ€λ₯λ₯Ό μΆλ ₯νλ©° μ΄λ° λ¬Έμ λ₯Ό ν΄κ²°νκ³ λ체ν urlμ μλ²μ μ§μ ν΄μΌ λ©λλ€.
history APIμ pushstate
popstate
μ΄λ²€νΈλ₯Ό μ΄μ©ν©λλ€. history.pushstate
ν΅ν΄ μ λ°μ΄ν° μ λ¬μ μν μν, μ λͺ©, url μ§μ μ΄ κ°λ₯ν©λλ€.
λλμ
κ·Έλμ νλ μμν¬, λΌμ΄λΈλ¬λ¦¬μ λμμ μ€λͺ μ λ³΄κ³ λ¨μν κΈ°λ₯ λμνλ κ°λ°λ§ νμλλ° μ€μ μ΄λ―Έ ꡬνλ κΈ°λ₯μ μ²μλΆν° κ°λ°μ ν΄λ³΄λ©΄μ κΈ°λ₯μ μ리λ₯Ό μ’λ μ΄ν΄ν μ μμμ΅λλ€. κ·Έλ¦¬κ³ μ§§μ μκ° λ΄ κ°λ°μ μ§ννλ©° ν μ€νΈ λ° μ¬μ©μμ ν΄λ¨Ό μλ¬λ₯Ό λ§μ΄ κ³ λ €νμ§ μκ³ μλ€λ λΆλΆμμ μμ¬μ μ΅λλ€. νμ§λ§ μλ² νλ‘μ νΈλ₯Ό ν΅ν΄ κ°μΈμ μΈ κ°λ° μ±μ₯μ λ¬μ±νλ€λ μ μμ μ¬λ°μλ νλ‘μ νΈμλ€κ³ μκ°ν©λλ€.
μ½λκ° κΆκΈνμλ€λ©΄?
GitHub