Frontend/Vue.js

[Vue CLI] 라우팅 구성 (hashchange) | vue-router 사용하기

gamzaggang7 2024. 5. 27. 20:03
728x90

라우팅: 웹 페이지 간의 이동 방법

 

서버 측 라우팅 / 클라이언트 측 라우팅

서버 측 라우팅은 사용자가 방문하는 url 경로에 기반하여 서버가 응답을 보내는 것을 의미한다. 전통적인 서버 렌더링 웹 앱에서 링크를 클릭하면 브라우저는 서버로부터 html 응답을 받고 새 html로 전체 페이지를 다시 로드한다.

 

그러나 싱글 페이지 애플리케이션(SPA)에서는 클라이언트 측 js가 탐색을 가로채고 새 데이터를 동적으로 가져와 전체 페이지를 다시 로드하지 않고 현재 페이지를 업데이트할 수 있다.

 

* 싱글 페이지 애플리케이션(SPA): 페이지를 이동할 때마다 서버에 웹 페이지를 요청하여 새로 갱신하는 것이 아니라 미리 해당 페이지들을 받아 놓고 페이지 이동 시에 클라이언트의 라우팅을 이용하여 화면을 갱신하는 패턴을 적용한 애플리케이션.

웹 사이트의 전체 페이지를 하나의 페이지에 담아 동적으로 화면을 바꿔가며 표현한다.

 

이러한 SPA에서 라우팅은 브라우저의 클라이언트 측에서 수행된다. 클라이언트 측 라우터는 History API 또는 hashchange 이벤트와 같은 브라우저 API를 사용하여 애플리케이션의 렌더링된 View를 관리한다.

 

다음은 간단한 라우팅 예이다.

<template>
  <a href="#">Home</a> |
  <a href="#/about">About</a> |
  <a href="#/not-existent-path">Wrong Link</a>
  <component :is="currentView"></component>
</template>

<script setup>
import Home from "./components/HomeComponent.vue";
import About from "./components/AboutComponent.vue";
import NotFound from "./components/NotFound.vue";
import { computed, ref } from "vue";

const routes = {
  "/": Home,
  "/about": About,
};

const currentPath = ref(window.location.hash);

window.addEventListener("hashchange", () => {
  currentPath.value = window.location.hash;
});

const currentView = computed(() => {
  return routes[currentPath.value.slice(1) || "/"] || NotFound;
});
</script>
<template>
  <h1>Home</h1>
</template>
<template>
  <h1>About</h1>
</template>
<template>
  <h1>404 Not Found</h1>
</template>

  • computed, ref: Vue의 Composition API에서 제공하는 반응형 상태 관리 도구
  • routes 객체: URL 경로를 해당 컴포넌트에 매핑
  • currentPath: 현재 URL 해시를 저장하는 ref. window.location.hash를 사용하여 현재 URL 해시 값을 가져옴
  • hashchange 이벤트 리스너를 추가하여 URL 해시가 변경될 때마다 currentPath 값을 업데이트
  • currentView: 현재 경로에 해당하는 컴포넌트를 계산하는 computed
    • currentPath.value.slice(1): 해시에서 # 문자를 제거한 경로를 가져옴
    • routes[ currentPath.value.slice(1) || "/" ]: 현재 경로에 해당하는 컴포넌트를 routes 객체에서 찾음. 현재 경로가 없으면 "/"를 사용
    • 경로에 해당하는 컴포넌트가 없으면 NotFound 컴포넌트를 반환
728x90

vue-router 라이브러리

vue-router는 vue에서 라우팅 기능을 구현할 수 있도록 지원하는 vue.js의 공식 라우터이다. 대부분의 싱글 페이지 앱(SPA)은 vue-router 라이브러리를 사용하는 것이 좋다. vue router는 vue 컴포넌트 시스템에 기반하여 구축되며, 라우트를 구성하여 각 URL 경로에 대해 어떤 컴포넌트를 보여줄지 vue router에 알려준다.

 

vue router를 구현할 때 필요한 특수 태그와 기능은 다음과 같다.

  • <router-link to="url값">: 페이지 이동 태그. 화면에서는 <a>로 표시되며 클릭하면 to에 지정한 url로 이동한다.
  • <router-view>: 페이지 표시 태그. 변경되는 url에 따라 해당 컴포넌트를 뿌리는 영역이다. 

 

먼저 프로젝트에 vue-router를 설치한다.

npm install vue-router@4

 

App.vue

<template>
  <h1>Hello Vue !</h1>
  <p><strong>현재 라우트 경로:</strong> {{ $route.fullPath }}</p>
  <nav>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
  </nav>
  <main>
    <router-view></router-view>
  </main>
</template>
  • 일반적인 a 태그 대신 url을 변경할 때 페이지를 다시 로드하지 않고 url 생성, 인코딩 및 기타 다양한 기능을 처리할 수 있게 하는 커스텀 컴포넌트 router-link를 사용한다.
  • router-view 컴포넌트는 현재 라우트 컴포넌트를 렌더링할 위치는 vue router에 알려준다. App.vue에 있을 필요는 없으며, 레이아웃에 맞게 어디에든 배치할 수 있지만 어딘가에 포함되어 있어야 한다. 그렇지 않으면 vue router가 아무것도 렌더링하지 않는다.
  • $route를 사용하여 현재 라우트를 나타내는 객체에 접근할 수 있다.

 

src/router/index.js

라우터 인스턴스를 생성한다. 라우터 인스턴스는 createRouter()함수를 호출하여 생성한다.

import { createMemoryHistory, createRouter } from "vue-router";

import Home from '../components/HomeComponent.vue'
import About from '../components/AboutComponent.vue'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

const router = createRouter({
  history: createMemoryHistory(),
  routes,
})

export default router
  • routes옵션: 라우트 자체를 정의하여 url 경로를 컴포넌트에 매핑한다. component 옵션으로 지정된 컴포넌트는 App.vue에서 router-view에 의해 렌더링될 컴포넌트이다.
  • history옵션: 라우트가 url에 어떻게 매핑되는지, 그리고 그 반대의 경우에 대해 제어한다. 현재 예제에서는 createMemoryHistory()를 사용하여 브라우저 url을 완전히 무시하고 자체 내부 url을 사용한다.

 

main.js

라우터 플러그인을 등록한다. mount() 호출 전에 use() 호출이 이루어져야 한다.

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index.js'

createApp(App)
  .use(router)
  .mount('#app')

 

HomeComponent.vue (Option API 사용)

<template>
  <h2>HomeView</h2>
  <button @click="gotoAbout">Go to About</button>
</template>

<script>
export default {
  methods: {
    gotoAbout() {
      this.$router.push('/about')
    }
  }
}
</script>
  • methods: 컴포넌트에 사용할 메서드를 정의한다.
  • this.$router: 현재 라우터 인스턴스를 참조한다. Vue 컴포넌트에서 $router를 통해 라우터 인스턴스에 접근할 수 있다.
  • push(): 라우터의 push 메서드를 호출하여 url 경로를 변경. 이 경로에 해당하는 컴포넌트가 router-view에 렌더링된다.

AboutComponent.vue (Option API 사용)

<template>
  <h2>AboutView</h2>
  <label> Search: <input v-model.trim="search" maxlength="20" /> </label>
</template>

<script setup>
import { computed } from "vue";
import { useRoute, useRouter } from "vue-router";

const router = useRouter();
const route = useRoute();

const search = computed({
  get() {
    return route.query.search ?? "";
  },
  set(search) {
    router.replace({ query: { search } });
  }
});
</script>
  • v-model.trim="search": 입력 필드 값을 search에 바인딩하며 양쪽 공백을 자동 제거한다.
  • Vue Router에서 현재 라우트 정보(useRoute)와 라우트 인스턴스(useRouter)를 가져오고 초기화한다.
  • const search = computed({}): search라는 계산 속성을 정의한다.
    • get(): 현재 url의 쿼리 파라미터 search 값을 반환한다. search 파라미터가 없으면 빈 문자열을 반환한다.
    • set(search): 새로운 search 값을 설정하고 이를 url 쿼리 파라미터로 업데이트한다. router.replace를 사용하여 url을 변경하며 이때 페이지가 리로드되지 않는다.

결과 )

 

 

* 공부 사이트

https://ko.vuejs.org/guide/scaling-up/routing.html

 

Vue.js

Vue.js - The Progressive JavaScript Framework

vuejs.org

https://router.vuejs.kr/guide/

 

Vue Router | Vue.js의 공식 라우터

Vue 3에 필요한 최신 공식 라우터

router.vuejs.kr

 

728x90