๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โญ Personal_Study/Vue

Vue Router

by ํฌ์ŠคํŠธ์‰์ดํฌ 2022. 11. 18.

Vue Router

Routing

Routing

โœ” ๋„คํŠธ์›Œํฌ์—์„œ ๊ฒฝ๋กœ๋ฅผ ์„ ํƒํ•˜๋Š” ํ”„๋กœ๋ ˆ์Šค
โœ” ์›น ์„œ๋น„์Šค์—์„œ์˜ ๋ผ์šฐํŒ…: ์œ ์ €๊ฐ€ ๋ฐฉ๋ฌธํ•œ URL์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ๊ฒฐ๊ณผ๋ฅผ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ

Routing in SSR

โœ” Server๊ฐ€ ๋ชจ๋“  ๋ผ์šฐํŒ…์„ ํ†ต์ œ
โœ” URL๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์‘๋‹ต์œผ๋กœ ์™„์„ฑ๋œ HTML ์ œ๊ณต

  • Django๋กœ ๋ณด๋‚ธ ์š”์ฒญ์˜ ์‘๋‹ต HTML์€ ์™„์„ฑ๋ณธ์ธ ์ƒํƒœ

โœ” ๊ฒฐ๋ก ์ ์œผ๋กœ, Routing(URL)์— ๋Œ€ํ•œ ๊ฒฐ์ •๊ถŒ์€ ์„œ๋ฒ„๊ฐ€ ๊ฐ€์ง„๋‹ค.

Routing in SPA / CSR

โœ” ์„œ๋ฒ„๋Š” ํ•˜๋‚˜์˜ HTML(index.html)๋งŒ์„ ์ œ๊ณต
โœ” ์ดํ›„์— ๋ชจ๋“  ๋™์ž‘์€ ํ•˜๋‚˜์˜ HTML ๋ฌธ์„œ ์œ„์—์„œ JavaScript ์ฝ”๋“œ ํ™œ์šฉ

  • DOM์„ ๊ทธ๋ฆฌ๋Š”๋ฐ ํ•„์š”ํ•œ ์ถ”๊ฐ€์ ์ธ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด axios์™€ ๊ฐ™์€ AJAX ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์ฒ˜๋ฆฌ

โœ” ์ฆ‰ ํ•˜๋‚˜์˜ URL๋งŒ ๊ฐ€์ง„๋‹ค.

Why routing?

โœ” ๋™์ž‘์— ๋”ฐ๋ผ URL์ด ๊ผญ ๋ฐ”๋€” ํ•„์š”๋Š” ์—†์œผ๋‚˜ ์œ ์ €์˜ ์‚ฌ์šฉ์„ฑ ๊ด€์ ์—์„œ๋Š” ํ•„์š”ํ•˜๋‹ค

โœ” Routing์ด ์—†๋‹ค๋ฉด

  • ์œ ์ €๊ฐ€ URL์„ ํ†ตํ•œ ํŽ˜์ด์ง€์˜ ๋ณ€ํ™” ๊ฐ์ง€ ๋ถˆ๊ฐ€
  • ํŽ˜์ด์ €๊ฐ€ ๋ฌด์—‡์„ ๋ Œ๋”๋ง ์ค‘์ธ์ง€์— ๋Œ€ํ•œ ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์—†๋‹ค.
  • ๋’ค๋กœ ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๋ถˆ๊ฐ€

Vue Router

Vue Router

โœ” Vue์˜ ๊ณต์‹ ๋ผ์šฐํ„ฐ
โœ” SPA ์ƒ์—์„œ ๋ผ์šฐํŒ…์„ ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ ์ œ๊ณต
โœ” ๋ผ์šฐํŠธ(routes)์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งคํ•‘ํ•œ ํ›„, ์–ด๋–ค URL์—์„œ ๋ Œ๋”๋ง ํ• ์ง€ ์•Œ๋ ค์ค€๋‹ค
โœ” SPA๋ฅผ MPA์ฒ˜๋Ÿผ URL์„ ์ด๋™ํ•˜๋ฉด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Vue Router ์‹œ์ž‘ํ•˜๊ธฐ

$ vue create vue-router-app

$ cd vue-router-app

$ vue add router

โœ” History Mode: Y

History mode

โœ” ๋ธŒ๋ผ์šฐ์ €์˜ History API๋ฅผ ํ™œ์šฉํ•œ ๋ฐฉ์‹

  • ์ƒˆ๋กœ ๊ณ ์นจ ์—†์ด URL ์ด๋™ ๊ธฐ๋ก์„ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

โœ” ์šฐ๋ฆฌ์—๊ฒŒ ์ต์ˆ™ํ•œ URL ๊ตฌ์กฐ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • ex) http://localhost:8080/index




โœ” router/index.js ์ƒ์„ฑ
โœ” views ํด๋” ์ƒ์„ฑ

router-link

โœ” aํƒœ๊ทธ์™€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ -> URL ์ด๋™

  • routes์— ๋“ฑ๋ก๋œ ์ปดํฌ๋„ŒํŠธ์™€ ๋งคํ•‘
  • ํžˆ์Šคํ† ๋ฆฌ์— ๋ชจ๋“œ์—์„œ router-link๋Š” ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ฐจ๋‹จํ•˜์—ฌ aํƒœ๊ทธ์™€ ๋‹ฌ๋ฆฌ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋กœ๋“œํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค

โœ” ๋ชฉํ‘œ ๊ฒฝ๋กœ๋Š” 'to'์†์„ฑ์œผ๋กœ ์ง€์ •

router-view

โœ” ์ฃผ์–ด์ง„ URL์— ๋Œ€ํ•ด ์ผ์น˜ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
โœ” ์‹ค์ œ component๊ฐ€ DOM์— ๋ถ€์ฐฉ๋˜์–ด ๋ณด์ด๋Š” ์ž๋ฆฌ ์˜๋ฏธ
โœ” router-link๋ฅผ ํด๋ฆญํ•˜๋ฉด routes์— ๋งคํ•‘๋œ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง

โœ” Django์—์„œ์˜ block tag์™€ ์œ ์‚ฌ

  • App.vue๋Š” base.html ์—ญํ• 
  • router-view๋Š” block ํƒœ๊ทธ๋กœ ๊ฐ์‹ผ ๋ถ€๋ถ„

src/router/index.js

// src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

โœ” ๋ผ์šฐํ„ฐ์— ๊ด€๋ จ๋œ ์ •๋ณด ๋ฐ ์„ค์ •์ด ์ž‘์„ฑ๋˜๋Š” ๊ณณ
โœ” Django์˜ urls.py์— ํ•ด๋‹น
โœ” routes์— URL์™€ ์ปดํฌ๋„ŒํŠธ ๋งคํ•‘

src/Views

โœ” router-view์— ๋“ค์–ด๊ฐˆ component ์ž‘์„ฑ
โœ” ๊ธฐ์กด์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋˜ ๊ณณ์€ componet ํด๋”๋ฟ์ด์—ˆ์ง€๋งŒ ์ด์ œ ๋‘ ํด๋”๋กœ ๋‚˜๋‰˜์–ด์ง„๋‹ค
โœ” ๊ฐ ํด๋” ์•ˆ์˜ .vue ํŒŒ์ผ๋“ค์ด ๊ธฐ๋Šฅ์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค

ํด๋”๋ณ„ ์ปดํฌ๋„ŒํŠธ ๋ฐฐ์น˜(๊ทœ์•ฝ์€ ์•„๋‹ˆ๋‹ค)

โœ” views/

  • routes์— ๋งคํ•‘๋˜๋Š” ์ปดํฌ๋„ŒํŠธ, ์ฆ‰ ์˜ ์œ„์น˜์— ๋ Œ๋”๋ง ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชจ์•„๋‘๋Š” ํด๋”
  • ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด View๋กœ ๋๋‚˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ ๊ถŒ์žฅ

โœ” components/

  • routes์— ๋งคํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์˜ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชจ์•„๋‘๋Š” ํด๋”
  • HomeView ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ HelloWorld ์ปดํฌ๋„ŒํŠธ

Vue Router ์‹ค์Šต

์ฃผ์†Œ ์ด๋™ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•

  1. ์„ ์–ธ์  ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜
  2. ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜

1. ์„ ์–ธ์  ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜

// App.vue

<template>
  <div id="app">
    <nav>
      <router-link :to="{ name: 'home'}">Home</router-link> |
      <router-link :to="{ name: 'about' }">About</router-link>
    </nav>
    <router-view/>
  </div>
</template>

โœ” router-link์˜ 'to'์†์„ฑ์œผ๋กœ ์ฃผ์†Œ ์ „๋‹ฌ
โœ” ๋™์ ์ธ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— v-bind ์‚ฌ์šฉ

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <button @click="toHome">ํ™ˆ์œผ๋กœ!</button>
  </div>
</template>

<script>
export default {
  name: 'AboutView',
  methods: {
    toHome() {
      this.$router.push({name: 'home'})
    }
  },
}
</script>

โœ” Vue ์ธ์Šคํ„ด์Šค ๋‚ด๋ถ€์—์„œ ๋ผ์šฐํ„ฐ ์ธ์Šคํ„ด์Šค์—์„œ $router๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅ
โœ” ๋‹ค๋ฅธ URL๋กœ ์ด๋™ํ•˜๊ฒจ๋ฉด this.$router.push ์‚ฌ์šฉ

  • history stack์— ์ด๋™ํ•  URL์„ ๋„ฃ๋Š” ๋ฐฉ์‹
  • history stack์— ๊ธฐ๋ก์ด ๋‚จ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์˜ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ด์ „ URL๋กœ ์ด๋™ ๊ฐ€๋Šฅ

โœ” <router-link :to='...'>๋ฅผ ํด๋ฆญํ•˜๋Š” ๊ฒƒ๊ณผ $router.push(...)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋™์ž‘

Dynamic Route Matching

// router/index.js

import HelloView from '@/views/HelloView'

Vue.use(VueRouter)

const routes = [
  ...
  {
    path: '/hello/:username',
    name: 'hello',
    component: HelloView
  }
]
// views/HelloView.vue

<template>
  <div></div>
</template>

<script>
export default {
  name: 'HelloView'
}
</script>

<style>

</style>

โœ” $route.params๋กœ ๋ณ€์ˆ˜์— ์ ‘๊ทผ ๊ฐ€๋Šฅ

// views/HelloView.vue

<template>
  <div>
    <h1>hello, {{ $route.params.userName }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloView'
}
</script>

<style>

</style>

โœ” ๋‹จ, HTML์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค๋Š” data์— ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ถŒ์žฅ

<template>
  <div>
    <h1>hello, {{ userName }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloView',
  data() {
    return {
      userName: this.$route.params.userName
    }
  },
}
</script>

<style>

</style>

Dynamic Route Matching - ์„ ์–ธ์  ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜

// App.vue

<template>
  <div id="app">
    <nav>
      <router-link :to="{ name: 'home'}">Home</router-link> |
      <router-link :to="{ name: 'about' }">About</router-link> |
      <router-link :to="{ name: 'hello', params: { userName: 'sunjun' }}">Hello</router-link>
    </nav>
    <router-view/>
  </div>
</template>

โœ” App.vue์—์„œ sunjun์œผ๋กœ ์ธ์‚ฌํ•˜๋Š” ํŽ˜์ด์ง€๋กœ ์ด๋™
โœ” params ์ด์šฉํ•˜์—ฌ ๋™์  ์ธ์ž ์ „๋‹ฌ ๊ฐ€๋Šฅ

Dynamic Route Matching - ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹ ๋„ค๋น„๊ฒŒ์ด์…˜

// AboutView.vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <button @click="toHome">ํ™ˆ์œผ๋กœ!</button>
    <input 
      type="text"
      @keyup.enter="goToHello"
      v-model='inputData'
      >
  </div>
</template>

<script>
export default {
  name: 'AboutView',
  data() {
    return {
      inputData : null
    }
  },
  methods: {
    toHome() {
      this.$router.push({name: 'home'})
    },
    goToHello() {
      this.$router.push({ name: 'hello', params: { userName: this.inputData }})
    }
  },
}
</script>

route์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋˜๋‹ค๋ฅธ ๋ฐฉ๋ฒ•

โœ” router/index.js์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋˜๋‹ค๋ฅธ ๋ฐฉ์‹

lazy-loading (์ง€์—ฐ ๋กœ๋”ฉ)

โœ” ๋ชจ๋“  ํŒŒ์ผ์„ ํ•œ ๋ฒˆ์— ๋กœ๋“œํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋ชจ๋“  ๊ฑธ ๋‹ค ์ฝ๋Š” ์‹œ๊ฐ„์ด ๋งค์šฐ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค
โœ” ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜์ง€ ์•Š๊ณ  ํŠน์ • ๋ผ์šฐํŠธ์— ๋ฐฉ๋ฌธํ•  ๋•Œ ๋งคํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์˜ ์ฝ”๋“œ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ์‹์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ

  • ๋‹น์žฅ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋จผ์ € ๋กœ๋“œํ•˜์ง€ ์•Š๋Š”๋‹ค

'โญ Personal_Study > Vue' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Article with Vue  (0) 2022.11.19
Navigation Guard  (0) 2022.11.19
UX & UI  (0) 2022.11.18
Todo: Local Storage  (0) 2022.11.16
Vuex ํ™œ์šฉํ•ด Todo SPA ์•ฑ ๋งŒ๋“ค๊ธฐ  (0) 2022.11.15

๋Œ“๊ธ€