본문 바로가기

Frontend/Vue3

[Vue3] Vue Router로 페이지 이동하기

728x90
반응형

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;
})

728x90
반응형

'Frontend > Vue3' 카테고리의 다른 글