지식보부상님의 공부 일지

Vue[10-1] vue-router를 이용한 라우팅 본문

KB IT's Your Life/Vue

Vue[10-1] vue-router를 이용한 라우팅

지식보부상님 2025. 3. 28. 16:30

[1] vue-router란
◈ SPA(단일 페이지 애플리케이션: Single Page Application)

- 하나의 페이지 안에서 사용자 경험 제공하는 애플리케이션

- 여러 화면 하나 페이지 안에서 제공 => 화면 별도로 로딩 x

- 화면마다 고유 식별자(URI) 기반으로 화면 렌더링 => vue-router 라이브러리 이용

 

[2] vue-router의 기본 사용법

◈ createRouter()

- router 객체 생성

- URI 경로에 따라 각각 다른 화면 렌더링 되도록 이를 처리할 컴포넌트 매핑함

- src/router/index.js

import {createRouter, createWebHistory } from 'vue-router'
...
const router = createRouter({
	history: createRouter(),
	routes:[
		{ path:'/', component:Home },
		{ path:'/about', components:About },
		{ path:'/members', components:Members },
		{ path:'/videos', components:Videos },
	]
})
export default router;

- history 속성: 라이터가 사용할 라우팅 모드 지정

- routes 속성: 요청 경로에 따라 어떤 컴포넌트 렌더링할지 결정

 

◈ router 객체의 등록

- router 객체를 사용하기 위해선  Vue 인스턴스에 등록 필요함

- src/main.js

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

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

 

◈ <RouterView>

- 각 경로별 컴포넌트를 랜더링할 위치 지정

- src/App.vue

<template>
<div>
  <header />
  <RouterView />
</div>
</template>

 

◈ <RouterLink to="경로">

- 화면 전환을 위한 링크 생성ㅇ

- <RouterLink to="URI 경로">링크 텍스트</RouterLink>

- <RouterLink :to="변수">링크 텍스트</RouterLink> : URI 경로를 변수에 저장했을 때 사용하는 방식 (v-bind 이용해야)

 

[3] router객체와 currentRoute 객체

◈ 컴포넌트에서 router 객체 접근하기

라우터 객체: const router = useRouter()

매칭된 라우트(currentRoute): const currentRoute = useRoute() (관례상 변수명 currentRoute)

- currentRoute 객체 주요 속성

구분 설명
fullPath 전체 요청 경로, 쿼리 문자열까지 포함  ex) /about?a=18&b=2
matched VueRouter 객체의 routes 배열의 라우트 중 매칭된 라우트
params URI 경로에 동적으로 전달된 파라미터 정보
path 요청 URI 경로
query 쿼리 문자열 ?a=1&b=2로 요청됐으면 CurrentRoute.query는 {a:1, b:2} 와 같은 객체
redirectedFrom 다른 경로에서 리디렉트된 경우 리디렉트시킨 URI 경로 정보 포함

 

[ 예제 ]

더보기
더보기
더보기
더보기

◈ src/router/index.js

import { createRouter, createWebHistory } from 'vue-router';
import HomePage from '@/pages/HomePage.vue';

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomePage,
    },
    // lazy
    {
      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('../pages/AboutPage.vue'),
    },
    {
      path: '/dynamic/:mood',
      name: 'dynamic',
      component: () => import('@/pages/DynamicPage.vue'),
    },
    {
      path: '/userinfo/:username',
      name: 'userinfo',
      component: () => import('@/pages/UserInfo.vue'),
    },
    {
      path: '/:pathMatch(.*)*',
      name: 'notfound',
      component: () => import('@/pages/NotFound.vue'),
    },
  ],
});

export default router;

- 처음엔 'home' route만 로딩되고, 후에 URI가 요청되면 뒷 route 로딩 (lazy)

 

◈ src/main.js

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

const app = createApp(App);

app.use(router);

app.mount('#app');

 

◈ src/pages/AboutPage.vue

<script setup></script>

<template>
  <div>
    <h1>라우트를 한 장의 사진으로 표현하면?</h1>
    <p>침교동과 쭈펄</p>
    <img
      alt="침교동과 쭈펄"
    />
  </div>
</template>

 

◈ src/pages/HomePage.vue

<script setup></script>

<template>
  <div>
    <h1>Vue Router의 세계에 오신 것을 환영합니다.</h1>
    <p>침교동을 아시나요?</p>
    <img
      alt="침교동"
    />
  </div>
</template>

 

◈ src/pages/DynamicPage.vue

<template>
  <div>
    <h1>오늘의 기분은? {{ msg }}</h1>
    <img :src="imgSrc" :alt="msg" />
  </div>
</template>

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

const currentRoute = useRoute();
const mood = computed(() => currentRoute.params.mood);
const msg = computed(() =>
  mood.value === 'happy' ? '행복합니다!:)' : '신납니다!:D'
);

const imgSrc = computed(() =>
  mood.value === 'happy'
);
</script>

<style lang="scss" scoped></style>

 

◈ src/pages/UserInfo.vue

<template>
  <div v-if="user">
    <h1>{{ user.name }}의 프로필</h1>
    <div>
      <img :src="user.avatar" :alt="user.name" class="avatar" />
      <div>
        <p>ID : {{ user.id }}</p>
        <p>이메일 : {{ user.email }}</p>
        <p>전화번호 : {{ user.phone }}</p>
        <p>가입일 : {{ user.joinDate }}</p>
        <p>직업 : {{ user.occupation }}</p>
      </div>
    </div>
    <div>
      <h2>자기소개</h2>
      <p>{{ user.bio }}</p>
    </div>
  </div>

  <div v-else>
    <h1>{{ username }}은 존재하지 않습니다.</h1>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';

const usersData = [
  {
    id: '1',
    name: '김철수',
    email: 'cheolsu.kim@example.com',
    phone: '010-1234-5678',
    joinDate: '2022-01-15',
    occupation: '소프트웨어 개발자',
    bio: '안녕하세요! 저는 프론트엔드 개발을 전문으로 하는 개발자입니다. Vue와 React를 주로 사용하며, 사용자 경험을 향상시키는 UI/UX에 관심이 많습니다.',
  },
  {
    id: '2',
    name: '이영희',
    email: 'younghee.lee@example.com',
    phone: '010-2345-6789',
    joinDate: '2022-03-22',
    occupation: '그래픽 디자이너',
    bio: '창의적인 디자인을 만드는 것에 열정을 가진 그래픽 디자이너입니다. 다양한 브랜드의 아이덴티티와 UI 디자인 프로젝트를 진행해왔으며, 사용자 중심 디자인을 지향합니다.',
  },
  {
    id: '3',
    name: '박민준',
    email: 'minjun.park@example.com',
    phone: '010-3456-7890',
    joinDate: '2022-06-10',
    occupation: '마케팅 매니저',
    bio: '디지털 마케팅 전략을 수립하고 실행하는 마케팅 매니저입니다. 데이터 분석을 통한 인사이트 도출과 효과적인 커뮤니케이션 전략 개발에 강점이 있습니다.',
  },
  {
    id: '4',
    name: '정수미',
    email: 'sumi.jung@example.com',
    phone: '010-4567-8901',
    joinDate: '2022-09-05',
    occupation: '제품 매니저',
    bio: '사용자의 니즈를 파악하고 이를 제품에 반영하는 제품 매니저입니다. 다양한 이해관계자와 협업하여 성공적인 제품을 출시한 경험이 있습니다.',
  },
];

const currentRoute = useRoute();
const username = computed(() => currentRoute.params.username);
console.log(username.value);
const user = computed(() => {
  if (username.value === 'user1') {
    return usersData[0];
  } else if (username.value === 'user2') {
    return usersData[1];
  } else if (username.value === 'user3') {
    return usersData[2];
  } else if (username.value === 'user4') {
    return usersData[3];
  }
});
</script>

<style scoped></style>

 

◈ src/pages/NotFound.vue

<script setup></script>

<template>
  <div>
    <h1>404 Not Found</h1>
    <img
      alt="침교동"
    />
  </div>
</template>

 

◈ src/App.vue

<script setup>
import { RouterLink, RouterView, useRouter } from 'vue-router';

const router = useRouter();
</script>

<template>
  <header>
    <nav>
      <RouterLink to="/">Home</RouterLink>
      /
      <RouterLink to="/about">About</RouterLink>
      /
      <RouterLink to="/dynamic/happy">happy</RouterLink>
      /
      <RouterLink to="/dynamic/excited">Excited</RouterLink>
    </nav>
    <div>
      <button @click="router.push('/')">Home</button>
      <button @click="router.push('/about')">About</button>
      <button @click="router.back()">뒤로</button>
      <button @click="router.forward()">앞으로</button>
      <button @click="router.go(-2)">뒤뒤로</button>
    </div>
  </header>
  <RouterLink to="/userinfo/user1">User1</RouterLink>/
  <RouterLink to="/userinfo/user2">User2</RouterLink>/
  <RouterLink to="/userinfo/user3">User3</RouterLink>/
  <RouterLink to="/userinfo/user4">User4</RouterLink>/
  <RouterLink to="/userinfo/user5">User5</RouterLink>
  <RouterView />
</template>

<style scoped></style>

 

 

'KB IT's Your Life > Vue' 카테고리의 다른 글

Dolt Node.js [03] 파일 관리하기  (1) 2025.04.23
Vue [10-2] vue-router를 이용한 라우팅  (2) 2025.04.23
Vue [09] Composition API  (0) 2025.03.27
Vue [08] 컴포넌트 심화  (1) 2025.03.27
Vue [07-2] TodoList 예제 리팩토링  (0) 2025.03.27