[Vue 3] Store(Pinia) 사용하기

우롱차·2023년 3월 13일
0

Vue.js

목록 보기
6/6
  • [Vue 3] Router 사용하기에 store를 추가하여 navigation guard를 구현하고자 한다.
  • userStore에 user 정보가 있으면 로그인한 사용자로 판단하여 /로, user 정보가 없으면 로그인하지 않은 사용자이므로 /login으로 이동하도록 구현한다.

1. user-store.js 파일 생성

📎 src/stores/user-store.js

import { defineStore } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    username: null,
  }),
  getters: {
    isLoggedIn: (state) => {
      return state.username != null;
    },
  },
  actions: {},
});
  • username이 존재하면 로그인 된 상태, username이 존재하지 않으면 로그인이 되지 않은 상태로 판단한다.

2. navigation guard 설정

📎 src/router/index.js

import { route } from "quasar/wrappers";
import {
  createRouter,
  createMemoryHistory,
  createWebHistory,
  createWebHashHistory,
} from "vue-router";
import { useUserStore } from "src/stores/user-store";
import routes from "./routes";

export default route(function (/* { store, ssrContext } */) {
  const createHistory = process.env.SERVER
    ? createMemoryHistory
    : process.env.VUE_ROUTER_MODE === "history"
    ? createWebHistory
    : createWebHashHistory;

  const Router = createRouter({
    scrollBehavior: () => ({ left: 0, top: 0 }),
    routes,

    history: createHistory(process.env.VUE_ROUTER_BASE),
  });

  // 추가한 부분
  const userStore = useUserStore();

  Router.beforeEach((to, from, next) => { // 페이지를 이동하기 전에 호출되는 함수
    if (to.fullPath !== "/login" && !userStore.isLoggedIn) {
      // /login으로 가고 있지 않고 로그인되어 있지 않으면 /login으로 redirect
      // 로그인하지 않은 상태에서 /를 요청하는 경우 (프로젝트가 처음 실행될 때)
      next("/login");
    } else if (to.fullPath == "/login" && userStore.isLoggedIn) {
      // /login으로 가고 있고 로그인되어 있으면 /으로 redirect
      // 로그인한 상태에서 /login을 요청하는 경우
      next("/");
    } else {
      next();
    }
  });

  return Router;
});
  • to.fullPath를 체크하는 이유는 무한 리디렉션을 방지하기 위함이다.

    • to.fullPath를 체크하지 않고 userStore의 상태만 체크한다면, 로그인하지 않은 상태에서는 /login으로의 무한 리디렉션이, 로그인한 상태에서는 /으로의 무한 리디렉션이 발생한다.

3. RouteLayout.vue 수정

📎 src/layouts/RouteLayout.vue

<template>
  <q-layout>
    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>
  • path에 따라 <router-view> 태그의 위치에 routes.js 파일에서 설정한 component가 위치한다.

📎 src/router/routes.js

const routes = [
  {
    path: "/",
    component: () => import("layouts/RouteLayout.vue"),
    children: [
      {
        path: "",
        component: () => import("pages/HomePage.vue"),
      },
      {
        path: "login",
        component: () => import("pages/LoginPage.vue"),
      },
    ],
  },

  {
    path: "/:catchAll(.*)*",
    component: () => import("pages/ErrorNotFound.vue"),
  },
];

export default routes;
  • path가 /인 경우 RouteLayout.vue 위에 HomePage.vue를 component로 위치
  • path가 /login인 경우 RouteLayout.vue 위에 LoginPage.vue를 component로 위치

4. HomePage.vue, LoginPage.vue 수정

📎 src/pages/LoginPage.vue

<template>
  <q-page>
  	<router-link to="/">Home</router-link><q-space /> Login Page<q-space />
    <q-btn @click="login">Login</q-btn>
  </q-page>
</template>

<script setup>
import { useUserStore } from "src/stores/user-store";
import { useRouter } from "vue-router";

const userStore = useUserStore();
const router = useRouter();

const login = () => {
  userStore.username = "test";
  if (userStore.isLoggedIn) { // pinia에서는 getter를 필드처럼 사용 가능하다.
    // 로그인 성공 시 페이지 이동
    router.push("/");
  }
};
</script>
  • 실행 화면

    • 로그인 버튼을 클릭하면 /으로 이동한다.

    • 로그인 버튼을 누르지 않은 상황에서는 Home 페이지로 가는 버튼을 눌러도 이동하지 않는다.

📎 src/pages/HomePage.vue

<template>
  <q-page>
    <router-link to="/login">Login</router-link><q-space /> Home Page<q-space />
    {{ username }}님 안녕하세요.<q-space />
    <q-btn @click="logout">Logout</q-btn>
  </q-page>
</template>

<script setup>
import { useUserStore } from "src/stores/user-store";
import { useRouter } from "vue-router";

const userStore = useUserStore();
const username = userStore.username;
const router = useRouter();

const logout = () => {
  userStore.username = null;
  if (!userStore.isLoggedIn) {
    // 로그아웃 성공 시 페이지 이동
    router.push("/login");
  }
};
</script>
  • 실행 화면

    • 로그아웃 버튼을 클릭하면 /login으로 이동한다.

    • 로그아웃 버튼을 누르지 않은 상황에서는 Login 페이지로 가는 버튼을 눌러도 이동하지 않는다.

profile
아직 따끈따끈합니다🍵

0개의 댓글