Vue Router: Vue 공식 라우터
https://v3.router.vuejs.org/kr/
Vue Router 추가
- Vite로 프로젝트 생성 시 Router를 추가한다.

- 서버 실행 후 Router로 인한 프로젝트 변화를 확인할 수 있다.
-> Home, About 링크에 따라 URL과 새로 렌더링되는 화면이 바뀐다.

- 프로젝트 구조도 변화된 것을 확인할 수 있다.
-> App.vue 코드가 바뀌고, router 폴더 및 views 폴더가 생성된다.

1) App.vue
- RouterLink: 페이지를 다시 로드하지 않고 URL을 변경하고 URL 생성 및 관련 로직을 처리한다. HTML의 a 태그를 렌더링한다.
- RouterView: URL에 해당하는 컴포넌트를 표시한다. 어디에나 배치하여 레이아웃에 맞출 수 있다.

2) router/index.js
- 라우팅에 관련된 정보 및 설정이 작성되는 곳
- router에 URL과 컴포넌트를 매핑한다.
3) views
- RouterView 위치에 렌더링 할 컴포넌트를 배치한다.
- 기존 components 폴더와 기능적으로 다른 것은 없으며 단순 분류의 의미로 구성된다.
- 일반 컴포넌트와 구분하기 위해 컴포넌트 이름을 View로 끝나도록 작성하는 것 권장
라우팅 기본
1. index.js에 라우터 관련 설정을 작성한다. (주소, 이름, 컴포넌트)
// index.js
const router = createRouter({
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
...
]
})
2. RouterLink의 'to' 속성으로 index.js에서 정의한 주소 속성 값(path)을 사용한다.
<!-- App.vue -->
<RouterLink to="/">Home</RouterLink>
Named Routes
- 경로에 이름을 지정하는 라우팅
- 하드코딩 된 URL을 사용하지 않아도 됨
- URL 입력 시 오타 방지
1. name 속성 값에 경로에 대한 이름 지정
// index.js
const router = createRouter({
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
...
]
})
2. 경로에 연결하려면 RouterLink에 v-bind를 사용해 'to' prop 객체로 전달
<!-- App.vue -->
<RouterLink :to="{ name: 'home' }">Home</RouterLink>
매개변수를 활용한 동적 경로 매칭
- 주어진 패턴 경로를 동일한 컴포넌트에 매핑해야 하는 경우 활용한다.
- 예를 들어 모든 사용자의 ID를 활용하여 프로필 페이지 url을 설계한다면?
user/1, user/2, user/3, ... => 일정한 패턴의 URL 작성을 반복해야 함
1. UserView 컴포넌트 라우트 등록. 매개변수는 콜론(:)으로 표기
// index.js
import UserView from "@/views/UserView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
...,
{
path: "/user/:id",
name: "user",
component: UserView,
},
],
});
2. RouterLink에 v-bind를 사용해 'to' prop 객체로 이름과 매개변수 전달
<!-- App.vue -->
<RouterLink :to="{ name: 'user', params: {id:1}}">User</RouterLink>
3. 라우트의 매개변수는 컴포넌트에서 $route.params로 참조 가능
<!-- UserView.vue -->
<template>
<div>
<h1>UserView</h1>
<h2>{{ $route.params.id }}번 User 페이지</h2>
</div>
</template>

다만, 다음과 같이 Composition API 방식으로 작성하는 것 권장
<!-- UserView.vue -->
<script setup>
import { ref } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const userId = ref(route.params.id);
</script>
<template>
<div>
<h1>UserView</h1>
<h2>{{ userId }}번 User 페이지</h2>
</div>
</template>
프로그래밍 방식 Navigation
- router의 인스턴스 메서드를 사용해 RouterLink로 a 태그를 만드는 것처럼 프로그래밍으로 네비게이션 관련 작업을 수행할 수 있다.
1. 다른 위치로 이동하기 - router.push()
- 새 항목을 history stack에 push하므로 사용자가 브라우저 뒤로가기 버튼을 클릭하면 이전 URL로 이동할 수 있다.
- RouterLink를 클릭했을 때 내부적으로 호출되는 메서드이므로 <RouterLink :to="...">를 클릭하는 것은 router.push(...)를 호출하는 것과 같다.
- UserView 컴포넌트에서 HomeView 컴포넌트로 이동하는 버튼 만들기
<script setup>
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
...
const router = useRouter();
const goHome = function () {
router.push({ name: 'home' });
}
</script>
<template>
<div>
...
<button @click="goHome">홈으로</button>
</div>
</template>

- router.push로 이동하면서 인자를 전달할 수도 있다.
router.push('/users/eduardo')
router.push({ path: '/users/eduardo' })
router.push({ name: 'user', params: { username: 'eduardo' } })
router.push({ path: '/register', query: { plan: 'private' } })
2. 현재 위치 바꾸기 - router.replace()
- push 메서드와 달리 history stack에 새로운 항목을 push하지 않고 다른 URL로 이동. 즉, 이동 전 URL로 뒤로 가기 불가
- <RouterLink :to="..." replace>는 router.replace(...)와 동일
Navigation Guard
- Vue router를 통해 특정 URL에 접근할 때 다른 URL로 redirect 하거나 취소하여 네비게이션을 보호한다.
-> ex) 인증 정보가 없으면 특정 페이지에 접근하지 못하게 함
1. Globally (전역 가드)
- 애플리케이션 전역에서 동작, index.js에서 정의
router.beforeEach()
: 다른 URL로 이동하기 직전에 실행되는 함수
구조
router.beforeEach((to, from) => {
...
return false
// return { name: 'About' }
})
- to: 이동할 URL 정보가 담긴 route 객체
- from: 현재 URL 정보가 담긴 route 객체
- 선택적 반환(return) 값
1) false: 현재 네비게이션 취소, URL이 변경된 경우(사용자 수동으로 또는 뒤로 버튼) from 경로의 URL로 재설정
2) Route Location: router.push()를 호출하는 것처럼 경로 위치를 전달하여 다른 위치로 redirect
* return이 없다면 'to' URL Route 객체로 이동
활용
- LoginView 컴포넌트 작성 및 라우트 등록
<!-- LoginView.vue -->
<template>
<div>
<h1>Login View</h1>
</div>
</template>
// index.js
{
path: "/login",
name: "login",
component: LoginView,
},
<!-- App.vue -->
<RouterLink :to="{ name: 'login'}">Login</RouterLink>
- Login이 되어있지 않다면 페이지 진입을 막고 Login 페이지로 이동시키기
-> 어떤 RouterLink를 클릭해도 LoginView 컴포넌트만 볼 수 있음
- 로그인이 되어 있지 않고(1), 이동하는 주소 이름이 login이 아니라면(2) login 페이지로 redirect
// index.js
router.beforeEach((to, from) => {
const isAuthenticated = false;
if (!isAuthenticated && to.name != "login") {
console.log("로그인이 필요합니다.");
return { name: "login" };
}
});

2. Per-route (라우터 가드)
- 특정 route에서만 동작, index.js의 각 routes에 정의
route.beforeEnter()
: route에 진입했을 때만 실행되는 함수
-> 매개변수, 쿼리 값이 변경될 때는 실행되지 않고 다른 경로에서 탐색할 때만 실행됨
구조
{
path: "/user/:id",
name: "user",
component: UserView,
beforeEnter: (to, from) => {
...,
return false
}
},
- routes 객체에서 정의
- 함수의 to, from, 선택 반환 인자는 beforeEach와 동일
활용
- 이미 로그인한 상태라면 LoginView 진입을 막고 HomeView로 이동 시키기
// index.js
const isAuthenticated = true;
const router = createRouter({
routes: [
...
{
path: "/login",
name: "login",
component: LoginView,
beforeEnter: (to, from) => {
if (isAuthenticated === true) {
console.log("이미 로그인한 상태입니다");
return { name: "home" };
}
},
},
],
});

3. In-component (컴포넌트 가드)
- 특정 컴포넌트 내에서만 동작, 컴포넌트 Script에 정의
1) onBeforeRouteLeave
: 현재 라우트에서 다른 라우트로 이동하기 전에 실행
-> 사용자가 현재 페이지를 떠나는 동작에 대한 로직 처리
활용
- 사용자가 UserView를 떠날 시 팝업 창 출력하기
// UserView.vue
import { onBeforeRouteLeave } from "vue-router";
onBeforeRouteLeave((to, from) => {
const answer = window.confirm('정말 떠나실 건가요?')
if (answer === false) {
return false
}
});

2) onBeforeRouteUpdate
: 이미 렌더링된 컴포넌트가 같은 라우트 내에서 업데이트 되기 전에 실행
-> 라우트 업데이트 시 추가적인 로직 처리
활용
- UserView 페이지에서 다른 id를 가진 User의 UserView 페이지로 이동
<!-- UserView.vue -->
<button @click="routeUpdate">100번 유저 페이지</button>
// UserView.vue
import { onBeforeRouteUpdate } from "vue-router";
const routeUpdate = function () {
router.push({ name: 'user', params: { id: 100 } })
}
onBeforeRouteUpdate((to, from) => {
userId.value = to.params.id;
})

'Frontend > Vue3' 카테고리의 다른 글
[Vue3] 상태 관리 라이브러리 Pinia (0) | 2024.05.14 |
---|---|
[Vue3] 컴포넌트 간 통신 (props, emit) (0) | 2024.05.07 |
[Vue3] Lifecycle Hooks (0) | 2024.05.06 |
[Vue3] watch (0) | 2024.05.06 |
[Vue3] 리스트 렌더링 (v-for) (0) | 2024.05.06 |