Vue Router URL 컴포넌트 매핑 방법

Vue 라우터, 라우트 차이

Vue 라우터

URL 경로에 따라 화면에 렌더링할 컴포넌트를 매핑하는 라우팅 라이브러리 객체입니다.
앱에 전역 등록되어 다른 페이지 이동, URL 추적, 히스토리 관리를 수행합니다.

Vue 라우트

현재 URL 경로, 동적 파라미터, 쿼리, 컴포넌트 정보 등을 담는 객체입니다.


Vue 프로젝트 라우터 적용 방법

Vue 라우터 라이브러리 설치

npm install vue-router

프로젝트 경로에서 위 명령어를 통해 Vue Router를 설치할 수 있습니다.

라우트 설정 (URL, 페이지 컴포넌트 매핑)

import { createRouter, createWebHistory } from 'vue-router';

import View컴포넌트명1 from '@/views/View컴포넌트명1.vue';
import View컴포넌트명2 from '@/views/View컴포넌트명2.vue';
import View컴포넌트명3 from '@/views/View컴포넌트명3.vue';
import View컴포넌트명4 from '@/views/View컴포넌트명4.vue';
import 상위컴포넌트명 from '@/views/상위컴포넌트명.vue';
import 중첩컴포넌트명0 from '@/views/중첩컴포넌트명0.vue';
import 중첩컴포넌트명1 from '@/views/중첩컴포넌트명1.vue';
import 중첩컴포넌트명2 from '@/views/중첩컴포넌트명2.vue';
import 에러페이지컴포넌트명 from '@/views/에러페이지컴포넌트명.vue';

const routes = [
  {
    path: '/',
    name: '경로별칭' // 필수값 X
    component: View컴포넌트명1
  },
  {
    path: '/URL경로',
    component: View컴포넌트명2
  },
  {
    path: '/URL경로/하위경로',
    component: View컴포넌트명3
  },
  {
    path: '/URL경로/:id', // 동적 세그먼트를 통한 동적 라우팅 (여러 URL을 하나의 컴포넌트에 매핑)
    component: View컴포넌트명4
  },
  { // Vue 중첩 라우트 설정 예시
    path: '/nested',
    component: 상위컴포넌트명, // /nested~ 접근 시 상위 RouterView에 렌더링
    children: [
      {
        path: '', // 상대경로
        component: 중첩컴포넌트명0, // /nested 접근 시 상위 RouterView 내부 RouterView에 렌더링
      },
      {
        path: 'one',
        component: 중첩컴포넌트명1, // /nested/one 접근 시 상위 RouterView 내부 RouterView에 렌더링
      },
      {
        path: 'two',
        component: 중첩컴포넌트명2,
      }
    ]
  },
  {
    path: '/:pathMatch(.*)*', // 정규표현식으로 위 경로 외 모든 URL은 Vue 에러페이지 라우팅
    name: 'NotFound',
    component: 에러페이지컴포넌트명
  },
]

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // 기본값 : '/'
  routes, // 키와 값이 같으므로 단축 표현 사용
});

export default router;

src/router 폴더에 index.js 파일 생성 후, 위와 같이 라우터 객체를 생성하고 내보내면 됩니다.
createWebHistory 함수 파라미터 경로를 기준으로 라우터가 URL 히스토리를 관리합니다.

라우트 시 props 전달 방법

const routes = [
  {
    path: '/경로/:id',
    component: 컴포넌트명,
    props: true // route.params.id를 컴포넌트에 props로 전달
    또는
    props: route => {
      id: parseInt(route.params.id),
    }
  },
  {
    path: '/경로',
    component: 컴포넌트명,
    props: route => ({ 객체명: route.query, }) // URL 뒤 쿼리스트링 객체를 컴포넌트에 props로 전달
  },
]

페이지 컴포넌트에 props를 전달해서, 컴포넌트가 직접 route 객체를 사용하여 의존하지 않도록 합니다.

<script setup>
const id = defineProps({
  id: Number,
});

const props = defineProps(['객체명']);
</script>

위와 같이, 컴포넌트에서 전달 받은 props를 사용할 수 있습니다.

router 생성 시 History 옵션 종류

History 모드 createWebHistory() 함수에 넘긴 문자열 파라미터가 URL 베이스 경로로 붙습니다.

히스토리 모드로 배포 시, 웹 서버에 설정이 필요합니다.
요청된 URL 경로에 실제 HTML 파일이 없어서 404 오류를 반환하기 때문입니다.
모든 경로를 index.html로 리다이렉트 설정하면 404 오류를 방지할 수 있습니다.
Hash 모드 createWebHashHistory() 페이지 이동 시 URL에 #이 붙습니다.
검색엔진 최적화 (SEO) 에 불리한 방식입니다.
Memory 모드 createMemoryHistory() URL을 사용하지 않고 메모리 상에서만 라우팅 상태를 유지합니다.
테스트 또는 서버 사이드 렌더링 (SSR) 환경에서 사용됩니다.

Vue 라우터 사용 설정

import router from '@/router';

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

main.js 파일에 router import 후 라우터 객체 인스턴스를 Vue 앱에 등록하면 적용됩니다.
이제 ‘http://localhost:포트/URL경로’로 접근하면 매핑된 컴포넌트가 렌더링 됩니다.


Vue 라우터 사용법

RouterView 렌더링 방법

<template>
  <main>
    <div class="container">
      <RouterView></RouterView>
    </div>
  </main>
</template>

특정 컴포넌트 안에 RouterView 내장 컴포넌트를 위치시키면,
현재 URL 경로에 매핑된 컴포넌트가 RouterView 내부에 렌더링됩니다.

HTML에서 페이지 이동 방법

<template>
  <nav>
    <RouterLink to="/">Home</RouterLink>
    <RouterLink to="/URL경로">페이지명</RouterLink>
    
    <RouterLink to="/URL경로">
      <button>버튼명</button>
    </RouterLink>

    // 신규 히스토리 남기지 않고 현재 기록 대체하여 이동 (이전 페이지 뒤로가기 방지)
    <RouterLink :to="{name: '경로별칭', replace: true}">페이지명</RouterLink> // 객체 바인딩 (v-bind)
  </nav>
</template>

일반 a 태그 대신 RouterLink 커스텀 컴포넌트를 사용하면,
전체 페이지 리로딩 없이 SPA 방식으로 URL에 매핑된 페이지 컴포넌트를 렌더링할 수 있습니다.

RouterLink 활성화 시 클래스 지정

<template>
  <nav>
    <RouterLink active-class="active클래스명" to="/">Home</RouterLink>
    <RouterLink active-class="active클래스명" to="/URL경로">페이지명</RouterLink>
  </nav>
</template>

RouterLink는 기본적으로 a 태그로 렌더링됩니다.
위와 같이 RouterLink에 active-class를 지정하면, a태그가 클릭되어 활성화 시 클래스를 부여합니다.
Vue 3 이상은 active-class가 지원되지 않고, 활성화된 링크에 자동으로 붙는 router-link-active, router-link-exact-active 클래스에 스타일을 지정합니다.

Javascript에서 페이지 이동 방법

router.push()

<template>
  <button @click="$router.push('/경로')">버튼명</button>
  또는
  <button @click="goOrderPage()">버튼명</button>
</template>
<script setup>
import { useRouter } from 'vue-router';

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

const goOrderPage = (id) => {
  router.push(`/경로/${id}`);
}
또는
const goOrderPage = () => {
  const id = route.params.id;
  router.push({
    name: '경로별칭',
    params: {
      id: id, // 동적 세그먼트에 따라 다른 URL로 이동
    }
  });
}
또는
const goOrderPage = () => {
  router.push({
    path: '/경로',
    query: { 파라미터명: '값' } // 페이지 이동 시 쿼리스트링 파라미터 지정
  });
}
</script>

Options API의 this.$router는 Composition API의 useRouter() 훅과 같은 기능을 합니다.
router.push()는 전체 페이지 리로딩 없이 SPA 방식으로 페이지를 이동할 수 있습니다.

router.replace()

const router = useRouter();

router.push({ path: '경로', replace: true });
또는
router.replace({ path: '/경로' });

router.replace는 브라우저 히스토리 스택에 새 기록을 추가하지 않고, 현재 기록을 대체하며 페이지 이동합니다.
로그인 후 페이지 이동 시 사용하면, 뒤로가기 눌렀을 때 다시 로그인 페이지로 안 가도록 할 수 있습니다.

라우트 정보 접근 방법

<template>
  <p>{{ $route }}</p>
</template>
<script setup>
import { useRoute } from 'vue-router';

const route = useRoute();

console.log(route.path); // 현재 URL 경로 객체
console.log(route.name); // 라우트에 설정된 페이지 이름 (없으면 undefined)
console.log(route.params); // URL로 받은 동적 세그먼트 파라미터 객체
console.log(route.query); // URL로 받은 쿼리스트링 파라미터 객체
console.log(route.query.파라미터키); // 특정 쿼리 파라미터 값 추출
console.log(route.hash); // URL로 받은 해시태그 파라미터 객체
</script>

Options API의 this.$route는 Composition API의 useRoute() 훅과 같은 기능을 합니다.
현재 활성화된 URL 경로, URL 파라미터 등 라우트 정보를 확인할 수 있습니다.


Vue Router 네비게이션 가드

사용자가 특정 라우트로 이동하려면 조건 검사를 통과해야 하는 기능입니다.
미로그인 시 /mypage 등 보호된 페이지 접근을 막고 로그인 페이지로 리다이렉트 할 수 있습니다.

전역가드 등록 방법

// 라우터 인스턴스 생성
const router = createRouter({
  history: createWebHistory(),
  routes,
})

// 전역 가드 등록
router.beforeEach((to, from) => {
  // to : 이동할 페이지 라우트 정보 객체
  // from : 이동하기 전 페이지 라우트 정보 객체
  
  // 로그인 여부 확인
  const isLoggedIn = false;

  if (to.meta.requiresAuth && !isLoggedIn) {
    // 로그인 필요 페이지인데 로그인 안 한 경우, 로그인 페이지로 리다이렉트
    return { name: '로그인페이지라우트별칭' } 또는 '/로그인경로';
    또는
    // 현재 라우팅(네비게이션) 취소. 페이지 이동 불가
    return false;
  }

  // 현재 라우팅 허용. 페이지 이동
  return true;
})

export default router;

router/index.js 하단에 beforeEach를 사용하여 모든 페이지에 전역 가드를 등록할 수 있습니다.

라우트 가드 등록 방법

const routes = [
  {
    path: '/경로',
    component: 컴포넌트명,
    beforeEnter: (to, from) => {
      // 쿼리스트링이 있다면, 제거 후 이동
      if (Object.keys(to.query).length > 0) {
        return { path: to.path, query: {} };
      }
    }
  }
]

라우트 객체를 통해, 특정 라우트 진입 시에만 라우트 가드를 설정할 수 있습니다.

컴포넌트 내 가드 등록 방법

Options API 라우트 가드 사용 예시

const 컴포넌트명 = {
  template: '<div>내용</div>',
  beforeRouteEnter(to, from) {
    // 네비게이션 이동 후, 컴포넌트 생성 전 실행되는 가드 (this 사용 불가)
  },
  beforeRouteUpdate(to, from) {
    // 현재 컴포넌트를 렌더링하는 경로가 변경되면 호출되는 가드
  },
  beforeRouteLeave(to, from) {
    // 현재 라우트를 떠나기 전 실행되는 가드
  }
}

Options API를 사용하여 컴포넌트 렌더링 시 가드를 구현할 수 있습니다.

Composition API 라우트 가드 사용 예시

<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';

onBeforeRouteUpdate((to, from) => {
  // 현재 컴포넌트를 렌더링하는 경로가 변경되면 호출되는 가드
});

onBeforeRouteLeave((to, from) => {
  // 현재 라우트를 떠나기 전 실행되는 가드
  const answer = window.confirm('정말 나가시겠습니까?');
  return answer;
});
</script>
<script>
export default {
  beforeRouteEnter() {
    // 네비게이션 이동 후, 컴포넌트 생성 전 실행되는 가드 (this 사용 불가)
  },
};
</script>

Composition API를 사용하여 컴포넌트 렌더링 시 가드를 구현할 수 있습니다.
beforeRouteEnter는 Options API에서만 지원합니다.