컴퓨터 프로그래밍/Vue.js

[Vue.js] Install Router, Routing, URL Parameter

한33 2025. 2. 5. 18:58

✔️ Project setting

1. router 설치

npm install vue-router@4

2. router.js 설정

router.js

import { createWebHistory, createRouter } from "vue-router";
import List from "./components/List.vue";

const routes = [
  {
    path: "/list",
    component: List.vue,
  }
];

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

export default router;

 

상단 import 로 List Component 가져오고

path route 설정 한다음에 component 에 등록시키면 된다.

 

3. main.js 설정

main.js

import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import router from './router.js'

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

 

 

main.js 에서 import 로 만든 router.js 파일 가져오고 use() 안에 작명 이름 넣어줘서 사용한다고 알리면 된다.

 

4. App.vue 에서 호출

<router-view :blog="blogs" ></router-view>

 

router-view 태그를 통해 원하는 route 로 접근 시 어디에 해당 Component 를 띄울 것인지를 지정한다.

 

반복문은 쓸 수 없으며 props 로 데이터를 전달할 때는 동일하게 위 코드처럼 전달할 수 있다.

5. router-link

<a class="nav-link" href="#">  <router-link to="/list">List</router-link>

 

router-link to ="/route" 를 통해 해당 route 로 이동할 수 있는 링크를 만들 수 있다.

 

6. styling

보통 router-view 나 router-link 태그에 직접 class 를 넣어 스타일링을 해주지 않고 그 위에를 div 로 묶어서 class 를 지정한다.


✔️ URL Parameter 를 이용한 상세페이지 기능

router.js

  {
    path: "/detail/:id(\\d+)",
    component: Detail
  }

detail 뒤에 :id 를 붙여서 URL Parameter 를 받도록 한다.

 

List.vue

<template>
  <div>
    <h3 class="mt-4">블로그 목록</h3>
    <ul>
      <li v-for="(blog, i) in blogs" :key="i">
        <router-link :to="`/detail/${blog.number`">{{ blog.title }}</router-link>
      </li>
    </ul>
  </div>
</template>

 

List Component 에서 title 리스트가 나오게 반복문을 사용했고, 안에 router-link 를 /detail/${i} 로 만들어서 해당 게시물로 상세페이지 링크가 이동되게끔 설정했다.


✔️ 불필요한 Component 에 props 제거

App.vue

<router-view :blogs="blogs" ></router-view>

 

기존 방식에서 Main,vue, List.vue, Detail.vue 이 세 Component 다 동일한 router-view 를 통해 호출되다 보니까 불필요하게 blogs 데이터가 전달되었다.

 

그래서 꼭 필요한 Component 에만 전달되도록 수정하고자 했다.

 

router.js

import blogs from "./assets/blog.js"

const routes = [
  {
    path: "/list",
    component: List,
    props: { blogs: blogs }
  },

 

router.js 파일 상단에 data 파일을 import 해주고,

props 를 이 곳에서 걸어줬다.

  {
    path: "/detail/:id(\\d+)",
    component: Detail,
    props: (route) => {
        const blogPost = blogs.find(blog => blog.number === parseInt(route.params.id));
        return { blogPost }; 
      }
  }

 

또한 Detail 에다가 한 번에 props 를 추가해 데이터를 넣어주지 않고, Detail 에는 해당 id 값만 blogs 데이터에서 찾아서 객체로 게시물 하나만 전달하게 했다.

 

Detail.vue

<template>
    <div>
        <h3 class="mt-4">상세페이지</h3>
        <h5>{{blogPost.title}}</h5>
        <p>{{blogPost.date}}</p>
        <div>{{blogPost.content}}</div>
    </div>
</template>

<script>
export default {
    name: 'Detail',
    props: {
        blogPost: Object
    }
}
</script>

<style></style>

 

받아온 props 데이터를 선언해주고 위에서 사용해줬다.


✔️ props 방식과 import 방식의 차이

🚀 props 방식의 장점

재사용 가능 → Detail.vue는 어떤 데이터든 받을 수 있음 (blogData가 바뀌어도 문제 없음)
유지보수 쉬움 → 부모에서 데이터가 변경되면 자동 반영
유닛 테스트 가능 → 다른 데이터로 쉽게 테스트 가능

❌ import 방식의 단점

🚫 재사용 어려움 → Detail.vue는 blogData에 강하게 결합되어 있어 다른 프로젝트에서 사용하기 어려움
🚫 데이터 변경 어려움 → 부모(App.vue)에서 데이터를 바꿔도 Detail.vue는 그대로 (따로 수정해야 함)
🚫 유닛 테스트 어려움 → 데이터를 변경해서 테스트하기 어려움