vue.js/vue.js 2

124. cookies에 Login정보 저장 | store actions 으로 코드 리팩토링

DEV-Front 2023. 2. 19. 00:26
반응형

단순히 자바스크립트에 로그인정보 저장해두는게 아니라 브라우저 저장소를 이용해서 토큰값을 저장하기

쿠키에 정의된 함수를 사용 document.cookie

 

1. cookies.js

function saveAuthToCookie(value) {
  document.cookie = `til_auth=${value}`;
}

function saveUserToCookie(value) {
  document.cookie = `til_user=${value}`;
}

function getAuthFromCookie() {
  return document.cookie.replace(
    /(?:(?:^|.*;\s*)til_auth\s*=\s*([^;]*).*$)|^.*$/,
    '$1',
  );
}

function getUserFromCookie() {
  return document.cookie.replace(
    /(?:(?:^|.*;\s*)til_user\s*=\s*([^;]*).*$)|^.*$/,
    '$1',
  );
}

function deleteCookie(value) {
  document.cookie = `${value}=; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
}

export {
  saveAuthToCookie,
  saveUserToCookie,
  getAuthFromCookie,
  getUserFromCookie,
  deleteCookie,
};

2. LoginFrom.vue

- import { saveAuthToCookie, saveUserToCookie } from '@/utils/cookies';

- 쿠키에 토큰과 유저이름 저장
   saveAuthToCookie(data.token);

   saveUserToCookie(data.user.username);

<template>
  <div class="contents">
    <div class="form-wrapper form-wrapper-sm">
      <form @submit.prevent="submitForm" class="form">
        <div>
          <label for="username">id:</label>
          <input id="username" type="text" v-model="username" />
          <p class="validation-text">
            <span class="warning" v-if="!isUsernameValid && username">
              Please enter an email address
            </span>
          </p>
        </div>
        <div>
          <label for="password">pw:</label>
          <input id="password" type="text" v-model="password" />
        </div>
        <button
          :disabled="!isUsernameValid || !password"
          type="submit"
          class="btn"
        >
          로그인
        </button>
      </form>
      <p class="log">{{ logMessage }}</p>
    </div>
  </div>
</template>

<script>
import { loginUser } from '@/api/index';
import { validateEmail } from '@/utils/validation';
import { saveAuthToCookie, saveUserToCookie } from '@/utils/cookies';

export default {
  data() {
    return {
      // form values
      username: '',
      password: '',
      // log
      logMessage: '',
    };
  },
  computed: {
    isUsernameValid() {
      return validateEmail(this.username);
    },
  },
  methods: {
    async submitForm() {
      try {
        // 비즈니스 로직
        const userData = {
          username: this.username,
          password: this.password,
        };
        const { data } = await loginUser(userData);
        console.log(data.token);
        this.$store.commit('setToken', data.token);
        this.$store.commit('setUsername', data.user.username);

        // 쿠키에 토큰과 유저이름 저장
        saveAuthToCookie(data.token);
        saveUserToCookie(data.user.username);

        this.$router.push('/main');
      } catch (error) {
        // 에러 핸들링할 코드
        console.log(error.response.data);
        this.logMessage = error.response.data;
      } finally {
        this.initForm();
      }
    },
    initForm() {
      this.username = '';
      this.password = '';
    },
  },
};
</script>

<style>
.btn {
  color: white;
}
</style>

3. 로그인시 정보가 개발자도구 → 애플리케이션 → 쿠키에 저장된걸 확인 가능


4. store | index.js

- 쿠키 import 받기

  import { getAuthFromCookie, getUserFromCookie } from '@/utils/cookie';

-  아래 함수를 통해 쿠키 값이 있으면 쿠키 값을 쓰고 없으면 빈 문자열 처리
   username: getUserFromCookie() || '',
   token: getAuthFromCookie() || '',

import Vue from 'vue';
import Vuex from 'vuex';
import { getAuthFromCookie, getUserFromCookie } from '@/utils/cookie';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    // 아래 함수를 통해 쿠키 값이 있으면 쿠키 값을 쓰고 없으면 빈 문자열 처리
    username: getUserFromCookie() || '',
    token: getAuthFromCookie() || '',
  },
  getters: {
    isLogin(state) {
      return state.username !== '';
    },
  },
  mutations: {
    setUsername(state, username) {
      state.username = username;
    },
    clearUsername(state) {
      state.username = '';
    },
    setToken(state, token) {
      state.token = token;
    },
  },
});

저장된 쿠키값으로 인해 새로고침해도 잘 보이는 화면 확인


코드 리팩토링

1. store | index.js 에 actions 추가

import Vue from 'vue';
import Vuex from 'vuex';
import {
  getAuthFromCookie,
  getUserFromCookie,
  saveAuthToCookie,
  saveUserToCookie,
} from '@/utils/cookies';
import { loginUser } from '@/api/index';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    // 아래 함수를 통해 쿠키 값이 있으면 쿠키 값을 쓰고 없으면 빈 문자열 처리
    username: getUserFromCookie() || '',
    token: getAuthFromCookie() || '',
  },
  getters: {
    isLogin(state) {
      return state.username !== '';
    },
  },
  mutations: {
    setUsername(state, username) {
      state.username = username;
    },
    clearUsername(state) {
      state.username = '';
    },
    setToken(state, token) {
      state.token = token;
    },
  },
  actions: {
    async LOGIN({ commit }, userData) {
      const { data } = await loginUser(userData);
      console.log(data.token);
      commit('setToken', data.token);
      commit('setUsername', data.user.username);

      // 쿠키에 토큰과 유저이름 저장
      saveAuthToCookie(data.token);
      saveUserToCookie(data.user.username);

      // reture 안넣어도 프로미스가 반환되지만 data를 언제쓸지 모르니 data 반환
      return data;
    },
  },
});

2. loginForm에 store actions 으로 코드 리팩토링

- 컴포넌트에서 비지니스 로직 분리

- 앞에 await가 붙어야함. 비동기처리가 끝나고 라우터 처리 해야하기 때문에
-  await this.$store.dispatch('LOGIN', userData);

<template>
  <div class="contents">
    <div class="form-wrapper form-wrapper-sm">
      <form @submit.prevent="submitForm" class="form">
        <div>
          <label for="username">id:</label>
          <input id="username" type="text" v-model="username" />
          <p class="validation-text">
            <span class="warning" v-if="!isUsernameValid && username">
              Please enter an email address
            </span>
          </p>
        </div>
        <div>
          <label for="password">pw:</label>
          <input id="password" type="text" v-model="password" />
        </div>
        <button
          :disabled="!isUsernameValid || !password"
          type="submit"
          class="btn"
        >
          로그인
        </button>
      </form>
      <p class="log">{{ logMessage }}</p>
    </div>
  </div>
</template>

<script>
import { validateEmail } from '@/utils/validation';

export default {
  data() {
    return {
      // form values
      username: '',
      password: '',
      // log
      logMessage: '',
    };
  },
  computed: {
    isUsernameValid() {
      return validateEmail(this.username);
    },
  },
  methods: {
    async submitForm() {
      try {
        // 비즈니스 로직
        const userData = {
          username: this.username,
          password: this.password,
        };

        // store actions 으로 코드 리팩토링
        // 컴포넌트에서 비지니스 로직 분리
        // 앞에 await가 붙어야함. 비동기처리가 끝나고 라우터 처리 해야하기 때문에
        await this.$store.dispatch('LOGIN', userData);
        this.$router.push('/main');
      } catch (error) {
        // 에러 핸들링할 코드
        console.log(error.response.data);
        this.logMessage = error.response.data;
      } finally {
        this.initForm();
      }
    },
    initForm() {
      this.username = '';
      this.password = '';
    },
  },
};
</script>

<style>
.btn {
  color: white;
}
</style>
반응형