[Vue.js] 라우팅

cowmin·2025년 7월 1일

1. 뷰 프로젝트 생성

  1. Node.js 설치
    뷰를 사용하기 위한 설치
    노드JS 사용x npm 쓰려고o

  2. 뷰 프로젝트 생성
    npm create vue@latest

  3. 체크
    v router
    v pinia
    v prettier 글씨 정렬

그외
typescript
jsx support 뷰에서 리액트 문법 쓸수있게 해줌
vitest, end to end testing -> tdd
ESLint 문법 교정

  1. vscode 터미널에서 npm install
    (강사님이 뷰 파일 주면 npm install 한번 하기)

  2. 실행
    5.1 개발계에서 실행할때
    npm run dev
    -> package.json 파일에서 "dev": "vite" 실행 이라는 뜻

5.2 nginx같은 웹서버에 배포할때
npm run build

  1. 추가 플러그인 설치
    Vue - Official
    Vue 3 Snippets

2. 뷰 기본 파일 설명

(건드릴 필요 없음)
.vscode 개발 도구
node_modules npm i 해서 설치된 것들 (용량 매우 큼, 공유가 필요할경우 삭제하고 공유)
public 배포할때 사용되는 파일 목록
gitattributes 깃 저장소 자동으로 만들어줌
gitignore 깃에 안올릴 파일 확장자 작성
index.html 기본 html (수정할 일 없음)
package.json 자신의 프로젝트가 의존하는 패키지의 리스트
prettierrc.json Prettier의 설정 파일
package-lock.json 프로젝트에서 설치한 의존성(라이브러리)들의 정확한 버전과 구조를 잠그는 파일
vite.config.js vite 설정파일, url 축약
jsconfig.json 문법 사용

.vue : 컴포넌트
html, css, js으로 이루어져있고 다른 vue파일(componenet)을 html 태그처럼 가져와서 사용할 수 있다.

http://localhost:5173/__dev-tools__ 화면 캡처
관리자 모드

3. 예제 만들기

index.html

<!doctype html>
<html lang="">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>	
    <div id="app"></div>
    // 1
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

main.js

// 2
import './assets/main.css'
import { createApp } from 'vue'
// 3
import App from './App.vue'
const app = createApp(App)
app.mount('#app')

App.vue

<script setup>
// 4
import Header from './components/Header.vue'
// 5
import Footer from './components/Footer.vue'
</script>

<template>
  <Header />
  <!--<Header> </Header> 이렇게 써도됨-->
  <div>App.vue에서 작성</div>
  <Footer />
</template>

<style scoped></style>

conponents/Header.vue

<script setup>
</script>

<template>
Header
</template>

<style scoped></style>

conponents/Footer.vue

<script setup>
</script>

<template>
Footer
</template>

<style scoped></style>

assets/main.css

* {
  margin: 0;
  padding: 0;
}

button {
  border: 0;
  background: transparent;
  cursor: pointer;
  outline: none;
}

ol,
ul,
li {
  list-style: none;
}

a {
  color: black;
  text-decoration: none;
}
  • 삭제해도 되는 것
    assets
    components
    stores
    views
    main.js 에서 // import './assets/main.css'
    index.js 에서
    routes: [], 로 만들기
    // import HomeView from '../views/HomeView.vue'

최종 화면
Header
App.vue에서 작성
Footer


  1. 라우터
    router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    
  ],
})

export default router

SPA(Single Page Application): 단일 HTML 페이지를 기반으로 동작하는 웹 애플리케이션
실제 페이지가 여러개가 x, 하나의 페이지에서 페이지의 내용을 변경해서 여러 페이지처럼 보이게 한 앱

장점: 여러 페이지의 내용을 한 파일에 넣으니 파일 용량이 커서 처음에는 느리지만 다른 필터로 넘어갈때 빠름

index.html
ㄴ main.js

index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
// App.vue 임포트
import App from './App.vue'

// 라우터 폴더 임포트되어있음
import router from './router'

const app = createApp(App)

app.use(createPinia())

// id가 app인 것들 가져옴
app.use(router)
app.mount('#app')

App.vue

<script setup>

</script>

<template>
   <Header />
  <router-view />
  <Footer />
  <!--임포트 안해도 사용할수 있는 이유: main.js에 임포트되어있기때문-->
  <!--<RouterLink> 로 할 경우, 라우터에 매핑된 컴포넌트 부분만 다시 로드됨-->
  <!--<a> 로 해도 가능은 하지만 페이지 전체를 다시 로드해서 오래걸림-->
</template>

<style scoped></style>

router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import User from '../components/User.vue' 
import Product from '../components/Product.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  // URI랑 컴포너트 매핑
  routes: [
    { path: '/user', component: User },
    { path: '/product', component: Product },
  ],
})

export default router
<script setup></script>

<template>
  <div>유저 페이지입니다.</div>
</template>

<style scoped></style>
<script setup></script>

<template>
  <div>상품 페이지입니다.</div>
</template>

<style scoped></style>

화면
사용자 페이지상품 페이지
상품 페이지입니다.
푸터입니다.

약속
component파일 이름은 대문자로
routerview를 띄울 페이지는 views 폴더에 넣는다


routerview
routerlink

특정페이지 안에서 특정 기능을 사용할때만 움직임
->
컴포넌트 안에 또 다른 컴포넌트 만들겠다

/product/list
/product/detail

-> 이런식으로 하면 index.js에 import가 많이 생김
따라서 routes 안에 함수를 만들어서 import 시키자

메인에서 사람들이 많이 클릭하는 기능 (로그인) 은 먼저 임포트 시키고
아닌 기능들은 함수로 임포트 시키자

전: 첫 페이지에서 라우터뷰로 같이 적용되어있는 페이지의 데이터 다 다운받음
import { createRouter, createWebHistory } from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import Product from '../views/Product.vue'
import ProductList from '../views/ProductList.vue'
import ProductDetail from '../views/ProductDetail.vue'

routes: [
{ path: '/', component: Main },
{ path: '/login', component: Login },
// 컴포넌트 안에 또 다른 컴포넌트 만들겠다
{
path: '/product',
component: Product,
children: [
{ path: 'list', component: ProductList },
{ path: 'detail', component: ProductDetail },
],
},
],
})

후: 해당 페이지의 데이터만 다운받음 (정답은 없다)
레이지 로딩

routes:
[ { path: '/', component: Main },
{ path: '/login', component: Login },
// 컴포넌트 안에 또 다른 컴포넌트 만들겠다
{
path: '/product',
component: () => import('../views/Product.vue'),
children: [
{ path: 'list', component: () => import('../views/ProductList.vue') },
{ path: 'detail', component: () => import('../views/ProductDetail.vue') },
],
},
],
})


개발자 도구 vue에서 구조보면됨

헷갈리는 부분
routerview
routerlink
위치


어떤 페이지는 로그인한 사람만 볼수있음

// 네비게이션 가드
// 라우터 페이지로 이동하기전에 무조건 한번 실행
router.beforeEach((to, from) => {
console.log(from, '에서', to, '로 이동하기 전에 실행')

// 유저페이지 못가게 막기
if (to.fullPath == '/user') {
return false
} else {
return true
}
})

보통은 if (to.fullPath == '/user') 이렇게 경로를 쓰지 않고
로그인 여부를 넣어서 접근을 제한함

// 네비게이션 가드
// 라우터 페이지로 이동하기전에 무조건 한번 실행
router.beforeEach((to, from, next) => {
// 로그인하지 않은 유저가 상품상세페이지로 접근할경우, 로그인 페이지로 넘기기
if (to.fullPath == '/user') {
next('/login')
}
next()
})

    { path: "/a", component: () => import("../views/A.vue"), meta: { requiresAuth: false } },
    { path: "/b", component: () => import("../views/B.vue"), meta: { requiresAuth: true } },
    { path: "/c", component: () => import("../views/C.vue"), meta: { requiresAuth: true } },
    
const checkLogin = () => {
  return true;
}

router.beforeEach((to, from, next) => {


  if (to.meta.requiresAuth) {
    next("/login")
  } else {
    next()
  }
}) 

  1. Named Views:
여러 개의 <router-view>에 각각 이름을 지정하여, 서로 다른 컴포넌트를 동시에 렌더링할 수 있습니다.
예를 들어, 헤더, 푸터, 본문 영역에 각각 다른 컴포넌트를 표시할 수 있습니다.
<router-view name="header">, <router-view name="content">, <router-view name="footer"> 와 같이 <router-view>에 name 속성을 부여하고, 라우트 설정에서 해당 이름에 해당하는 컴포넌트를 지정합니다. 

이름으로 이동시키기

라우터 index.js
전: 경로의 이름을 바꿀때마다 링크를 심어놓은 파일을 다 수정해야함
routes: [
{
path: '/product',
component: () => import('../views/Product.vue'),
children: [
{ path: 'list', component: () => import('../views/ProductList.vue') },
{ path: 'detail', component: () => import('../views/ProductDetail.vue') },
],
})

상품 상세페이지

후 :
인덱스.js 파일에서만 이름 수정하면 전체 적용됨

{ name: "detail", path: 'detail', component: () => import('../views/ProductDetail.vue') },

상품 상세페이지

페이지 전체 내용 : views 폴더
짜잘하게 있는 기능들: components 폴더

components 안에서도 큰 기능 별로 나누어 보관
ex) dashboard, base

0개의 댓글