Home ERROR-Vue3-router에서-네비게이션-가드-설정하는-방법
Post
Cancel

ERROR-Vue3-router에서-네비게이션-가드-설정하는-방법

네비게이션 가드 공식문서

네비게이션 가드란 특정 페이지를 보호하기 위해 사용하는 방법으로서 URL의 접근을 제한하는 것을 의미한다.


😥 문제 상황

  • 로그인을 하지 않은 유저: 개인 정보 수정, 회원 탈퇴 페이지에 접근을 못한다.

  • 로그인을 한 유저: 로그인, 회원가입 페이지에 접근을 못한다.


회원 관리에 관한 페이지를 개발한 후, 로그인 여부에 따라 페이지에 접근할 수 있는 것을 제한하려 했다. 그러나 로그인 여부 자체를 인식하지 못했다.


1) 로그인 유저인지 확인을 못하나..?

로그인유저 확인 로직

  • 로그인 했을 때, 유저의 access토큰과 refresh토큰을 로컬 스토리지와 vuex에 저장한다.
  • 브라우저를 재 시작 했을 때, 로컬 스토리지에 토큰 정보가 있으면 이를 vuex에 저장한다.
  • vuex에 토큰이 저장되어 있을 경우 해당 유저는 로그인 유저로 간주한다.


image-20220729230058080

vuex를 확인해보면, 로그인 여부는 잘 확인하고 있는 것을 알 수 있었다.


2) Router 코드가 문젠가..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// src/router.ts 

import { computed } from "vue";
import { useStore } from "vuex"
const store = useStore()


// Navigation Guard 설정: 오류를 해결하기 위해 임의로 any타입을 사용했다. 
router.beforeEach((to: any, from, next) => {
  // 로그인 여부 확인
  const isLoggedIn = computed(() => store.getters["personalInfo/isLoggedIn"]);

  // 로그인이 필요한 페이지
  const authPages = ["TheSignOutView", "TheChangeUserView", "TheChangePwView"];

  // 로그인이 되어있지 않을 때만 가능한 페이지
  const notAuthPages = ["TheSignupView", "TheLoginView"];

  // 1. 현재 이동하고자 하는 페이지가 로그인이 필요한지 확인
  const isAuthRequired = authPages.includes(to.name);
  const isNotAuthRequired = notAuthPages.includes(to.name);

  // 2. 로그인이 필요한 페이지인데 로그인이 되어있지 않다면 로그인 페이지(/login)로 이동
  if (isAuthRequired && !isLoggedIn.value) {
    next({ name: "TheLoginView" });

    // 3. 로그인이 되어있는데 /login, /signup 페이지로 이동한다면 메인 페이지(/)로 이동
  } else if (isNotAuthRequired && isLoggedIn.value) {
    next({ name: "TheHomeView" });

    // 4.  원래 이동 페이지
  } else {
    next();
  }
});

router.ts에 네비게이션 가드로 작성한 코드가 로직적인 문제가 있는지 확인해 보았다.

  1. 현재 유저가 로그인 유저인지 확인한다.
  2. 유저의 로그인 상태에 따라 접근할 수 있는 페이지와 접근할 수 없는 페이지를 나눈다.
  3. 현재 이동하고자 하는 페이지가 어떤 페이지 인지 확인한다.
    • 현재 이동하고자 하는 페이지가 어디에 속해있는지 includes함수를 통해 확인
  4. 1~3에서 확인한 유저의 로그인 여부이동하고자 하는 페이지의 종류에 따라 이동되는 분기가 나뉜다.
    • 권한이 없는 페이지에 이동하려고 할 시, 지정된 페이지로 이동
    • 권한이 있는 페이지에 이동하려고 할 시, 원래 이동하려고 하는 페이지로 이동


로직은 큰 문제가 없는 것 같은데.. 🤔


🤸‍♂️ 해결 방법

위의 코드에서 문제가 되는 부분은 다음과 같다.


1
2
3
4
// src/router.ts 

const isLoggedIn = computed(() => store.getters["personalInfo/isLoggedIn"]);
console.log(isLoggedIn)

console에 찍어보니 undefined가 출력 되어 로그인 여부를 확인할 수 없는 것이다. 분명 store에는 값이 잘 저장되어 있는데 왜 값을 못 가져오는 걸까.

기존에 컴포넌트에서 store를 접근할 때는 useStore라는 메서드를 통해 접근할 수 있기 때문에 외부 ts파일도 이렇게 접근이 가능할 것이라고 생각했었다. 그러나 같은 코드로 접근하면 안된다.


1
2
3
4
5
6
7
8
9
// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

const app = createApp(App);
app.use(store).use(router);
app.mount("#app");
  • vue는 이렇게 main.ts에서 store가 연동되어 있기 때문에 {useStore}메서드로 접근을 할 수 있다. (추측..)
  • 그래서 vue파일이 아닌 외부 파일에서 접근을 하기 위해서는 직접 store에 접근해서 store를 가져와야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// src/store/index.ts

import { createStore } from "vuex";
import { account, AccountState } from "../store/accounts/account";
import { signup, SignupState } from "../store/accounts/signup";
import { password, PasswordState } from "../store/accounts/password";
import { personalInfo, PersonalInfoState} from "../store/accounts/personalInfo";


// 모듈의 state를 공유한다.
export interface RootState {
  account: AccountState;
  signup: SignupState;
  personalInfo: PersonalInfoState;
  password: PasswordState;
}

// store를 생성한다.
export default createStore({
  modules: {
    account,
    signup,
    personalInfo,
    password,
  },
});

  • store를 createStore를 통해 export하고 있기 때문에 createStore로 vuex의 store에 접근하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { computed } from "vue";
import createStore from "../src/store/index";

// 스토어 정의
const store = createStore;

// Navigation Guard 설정: 오류를 해결하기 위해 임의로 any타입을 사용했다. 
router.beforeEach((to: any, from, next) => {
  const isLoggedIn = computed(() => store.getters["personalInfo/isLoggedIn"]);

  const authPages = ["TheSignOutView", "TheChangeUserView", "TheChangePwView"];
  const notAuthPages = ["TheSignupView", "TheLoginView"];

  const isAuthRequired = authPages.includes(to.name);
  const isNotAuthRequired = notAuthPages.includes(to.name);

  if (isAuthRequired && !isLoggedIn.value) {
    next({ name: "TheLoginView" });
    console.log("로그인 하지 않은 유저는 돌아가시오")
  } else if (isNotAuthRequired && isLoggedIn.value) {
    next({ name: "TheHomeView" });
  } else {
    next();
  }
});

문제 없이 잘 작동 하는 것을 확인할 수 있다 😀


image-20220731120805602


This post is licensed under CC BY 4.0 by the author.