FrameWorks/Vue

VueRouter의 Route Matching Grammar 파헤치기

ABCD 2024. 6. 21.

parameter에 커스텀 정규식 사용

parameter에 커스텀 정규식을 이용하여 사용할 수 있습니다.
숫자만 표시하게 한다던지, 뒤에 추가로 붙는 URL을 허용해야하는 경우에 사용할 수 있죠.

다음은 일반적인 route를 사용하는 방법입니다.

const route = [
    { path: '/order/:orderId'},
    { path: '/product/:productName'},
]

하지만 정적섹션 /order or /product를 사용하고 싶지 않을 수 있습니다.
만약 :orderId에서는 숫자만, :productName에는 무엇이든 가능하다면 정규식으로 해당 문제를 해결 할 수 있습니다.

const route = [
    // /:orderId -> 숫자만 매치됨
    { path: '/:orderId(\\d+)' },
    // /:productName -> 무엇이든 매치됨
    { path: '/:productName' },
]


정규식 표현법

  • \d : 숫자와 매치 ([0-9]와 동일한 표현)
  • \D : 숫자가 아닌 것과 매치 ([^0-9]와 동일한 표현)
  • \s : whitespace 문자와 매치 ([ \t\n\r\f\v]와 동일한 표현)
    • 맨 앞의 빈 칸은 공백문자(space)를 의미
  • \S : whitespace 문자가 아닌 것과 매치 ([^\t\n\r\f\v]와 동일한 표현)
  • \w : 문자 + 숫자(alphanumeric)와 매치 ([a-zA-Z0-9_]와 동일한 표현)
  • \W : 문자 + 숫자(alphanumeric)가 아닌 문자와 매치 ([^a-zA-Z0-9_]와 동일한 표현)
  • {m} : 반드시 m번 반복
  • {m, n} : 반드시 m~n번 반복
  • {m,}, {,n} : 반드시 m회 이상 반복, n회 이하 반복

반복가능한 파라미터

/first/second/third처럼 여러 섹션이 있는 라우트를 매칭해야 하는 경우 사용합니다.
parameter에 *(의미: 0개 이상) or +(의미: 1개 이상) 를 사용하여 정의하게 됩니다.

다음 예시를 보도록 하겠습니다.

const routes = [
    // 다음 항목들이 매치됨 /, /one, /one/two, /one/two/three, 등
    { path: '/:route*' },
    // 다음 항목들이 매치됨 /one, /one/two, /one/two/three, 등
    { path: '/:route+' },
]

 

위와 같이 전달하게 되면 parameter가 문자열이 아닌 배열리 제공되며, route를 상용할 때 배열을 전달해 주어야 합니다.

// { path: '/:route*', name: 'router' }
// 탐색한 route '/'
router.resolve({ name: 'router', params: { route: [] } }).href
// 탐색한 route '/a/b'
router.resolve({ name: 'router', params: { route: ['a', 'b'] } }).href

// { path: '/:route+', name: 'router' }
// +를 사용하여 1개이상의 parameter가 존재해야 하는데 공백이라 에러가 발생함
router.resolve({ name: 'router', params: { route: [] } }).href

 

사용방법을 알아보겠습니다.

<nav>  
    <router-link to="/">홈으로 가자</router-link> | <router-link to="/Note">노트로 가자</router-link> |  
    <router-link to="/router/라우터/테스트/중입니다.">라우터 공부하러 가자</router-link> |  
    <router-link :to="router.resolve({ name: 'router', params: { route: ['resolve', '사용한', '배열parameter'] } }).path">라우터 공부하러 가자2</router-link>
</nav>
<script setup>  
import { useRoute } from 'vue-router';  

const route = useRoute();  

console.log(route.params);  
</script>  

<template>  
    <h1>라우터 공부방</h1>  
    <div v-for="item in route.params.route">  
        <span>{{ item }}</span>  
    </div>  
</template>  

<style scoped></style>

 

각각 /router path에 도달한 화면의 결과는 다음과 같을 것입니다.

<div id="app" data-v-app="">
    <h1>라우터 공부방</h1>
    <div>
        <span>라우터</span>
    </div>
    <div>
        <span>테스트</span>
    </div>
    <div>
        <span>중입니다.</span>
    </div>
</div>
<div id="app" data-v-app="">
    <h1>라우터 공부방</h1>
    <div>
        <span>resolve</span>
    </div>
    <div>
        <span>사용한</span>
    </div>
    <div>
        <span>배열parameter</span>
    </div>
</div>

 

괄호를 사용하여 앞서 사용한 커스텀 정규식과 결합도 가능합니다.

const routes = [
    // 숫자에만 매칭
    // 매치됨 /1, /1/2, 등
    { path: '/:route(\\d+)+' },
    // 매치됨 /, /1, /1/2, 등
    { path: '/:route(\\d+)*' },
]

민감하고 엄격한 route options

기본적으로 route는 대소문자를 구분하지 않습니다.
후행 슬래시의 존재 유무에 따라 동작이 다르게 동작하지도 않습니다.
/user/123//user/123이 같은 동작을 하는 것이 그 예입니다.

우리는 다음 속성을 부여해 다음 문제를 해결할 수 있습니다.

  • strict : 후행 /구분 여부
  • sensitive : 대소문자 구분 여부
import Main from '@/Main.vue'
import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [  
    { path: '/', name: 'Main', component: Main },  
    { path: '/:id/:pwd', name: 'MainParam', component: Main },  
    { path: '/Note', name: 'Note', component: () => import('@/components/Note.vue') },
    // 대소문자를 구분하게 sensitive를 설정
    { path: '/router/:route*', name: 'router', sensitive: true, component: () => import('@/components/RouterStudy.vue') },  
]  

const router = createRouter({  
    history: createWebHashHistory('/'),
    // 후행 '/'를 구분하도록 설정  
    strict: true,
    routes,  
})  

export default router

선택적 parameter

우리는 javascript에서 사용하는 ?를 이용하여 nullable하게 사용하는 방법을 알고 있습니다. java에서는 Optional을 이용하는거와 비슷한 방법이죠.
위에서 사용해본 *경우는 반복적으로 사용해 여러개의 parameter를 배열의 형태로 받아오는 방법을 사용해 보았습니다.

하지만, 우리는 0개 or 1개의 데이터 중에 선택하고 싶은 경우가 발생 할 수 있습니다.
그럴 경우 우리는 ?를 사용하여 이 문제를 해결할 수 있습니다.
?를 사용하게 되면 *처럼 배열이아닌 문자열을 제공받을 수 있습니다.

예시를 보여드리겠습니다.

const routes = [
    // 매치 가능한 것: /users, /users/james
    { path: '/users/:userId?' },
    // 매치 가능한 것: /users/, users/42
    { path: '/users/:userId(\\d+)?' },
]

 

이해가 되셨나요?
첫번째 route정보는 문자열을 받던지 안받던지를 설정한 것입니다.
두번째 route정보는 userId에 올 수 있는 데이터는 숫자로 한정을 지은 것이죠.

728x90
반응형

댓글

💲 추천 글