Vue

Vue_5 (Vuex 인증 모듈 및 App.vue 사용)

99duuk 2024. 9. 4. 17:26

로그인 정보를 전역적으로 관리하기 위해 Vuex store를 사용,

App.vue에서 이를 초기화하고 관리

 

=> 애플리케이션 전체에서 일관된 로그인 상태를 유지 가능

 

// store/modules/auth.js
import api from '@/api' // API 호출을 위한 가상의 모듈

export default {
  namespaced: true,
  state: {
    user: null,
    token: null
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user
    },
    SET_TOKEN(state, token) {
      state.token = token
    }
  },
  actions: {
    async login({ commit }, credentials) {
      try {
        const { user, token } = await api.login(credentials)
        commit('SET_USER', user)
        commit('SET_TOKEN', token)
        localStorage.setItem('token', token) // 토큰을 로컬 스토리지에 저장
        return user
      } catch (error) {
        console.error('Login failed:', error)
        throw error
      }
    },
    logout({ commit }) {
      commit('SET_USER', null)
      commit('SET_TOKEN', null)
      localStorage.removeItem('token')
    },
    async checkAuth({ commit, state }) {
      if (state.user) return state.user
      const token = localStorage.getItem('token')
      if (!token) return null
      try {
        const user = await api.getUserInfo(token)
        commit('SET_USER', user)
        commit('SET_TOKEN', token)
        return user
      } catch (error) {
        console.error('Auth check failed:', error)
        localStorage.removeItem('token')
        return null
      }
    }
  },
  getters: {
    isAuthenticated: state => !!state.user,
    currentUser: state => state.user
  }
}

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './modules/auth'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    auth
  }
})

// App.vue
<template>
  <div id="app">
    <!-- 앱 컨텐츠 -->
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  async created() {
    // 앱 시작 시 인증 상태 확인
    try {
      await this.$store.dispatch('auth/checkAuth')
    } catch (error) {
      console.error('Initial auth check failed:', error)
    }
  }
}
</script>

 

  1. store/modules/auth.js에서 인증 관련 상태, 뮤테이션, 액션, 게터를 정의:
    • login 액션: 사용자 로그인 처리
    • logout 액션: 로그아웃 처리
    • checkAuth 액션: 저장된 토큰을 사용해 인증 상태 확인
  2. store/index.js에서 auth 모듈을 Vuex store에 등록.
  3. App.vue에서:
    • created 훅에서 checkAuth 액션을 디스패치하여 앱 시작 시 인증 상태를 확인.
    • 이를 통해 페이지 새로고침 시에도 로그인 상태를 유지할 수 있음.

요러면 애플리케이션의 어느 컴포넌트에서든 다음과 같이 인증 관련 기능을 사용 가능함

 

// 로그인
this.$store.dispatch('auth/login', { username, password })

// 로그아웃
this.$store.dispatch('auth/logout')

// 현재 사용자 정보 가져오기
const user = this.$store.getters['auth/currentUser']

// 인증 상태 확인
const isLoggedIn = this.$store.getters['auth/isAuthenticated']

 

 

 

 


// store/modules/auth.js
export default {
  state: {
    user: null,
    loginAttempts: 0,
    isLocked: false
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user;
    },
    INCREMENT_LOGIN_ATTEMPTS(state) {
      state.loginAttempts++;
    },
    RESET_LOGIN_ATTEMPTS(state) {
      state.loginAttempts = 0;
    },
    SET_LOCKED(state, isLocked) {
      state.isLocked = isLocked;
    }
  },
  actions: {
    async login({ commit, state }, credentials) {
      if (state.isLocked) {
        throw new Error('계정이 잠겼습니다. 나중에 다시 시도해주세요.');
      }
      try {
        // API 호출로 로그인 시도
        const user = await api.login(credentials);
        commit('SET_USER', user);
        commit('RESET_LOGIN_ATTEMPTS');
        router.push('/'); // 메인 페이지로 이동
      } catch (error) {
        commit('INCREMENT_LOGIN_ATTEMPTS');
        if (state.loginAttempts >= 5) {
          commit('SET_LOCKED', true);
          setTimeout(() => commit('SET_LOCKED', false), 30 * 60 * 1000); // 30분 후 잠금 해제
        }
        throw error;
      }
    },
    logout({ commit }) {
      commit('SET_USER', null);
      router.push('/login');
    },
    checkAuth({ commit, state }) {
      // 토큰 검증 등의 로직
      if (/* 토큰이 유효하지 않으면 */) {
        commit('SET_USER', null);
        router.push('/login');
      }
    }
  },
  getters: {
    isLoggedIn: state => !!state.user,
    remainingAttempts: state => 5 - state.loginAttempts
  }
};

// App.vue
export default {
  name: 'App',
  created() {
    this.$store.dispatch('auth/checkAuth');
  },
  watch: {
    '$route'(to) {
      // 라우트 변경 시마다 인증 상태 확인
      if (to.meta.requiresAuth && !this.$store.getters['auth/isLoggedIn']) {
        this.$router.push('/login');
      }
    }
  }
};

// router/index.js
const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Home,
      meta: { requiresAuth: true }
    },
    {
      path: '/login',
      component: Login
    }
    // 기타 라우트...
  ]
});

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !store.getters['auth/isLoggedIn']) {
    next('/login');
  } else {
    next();
  }
});

이런 식으로도 가능하다.

 

Store(auth.js)에서 

로그인 상태, 로그인 시도 횟수, 계정 잠금 상태 등을 관리하고, 

로그인, 로그아웃, 인증 상태 확인 등의 액션을 정의하고, 

로그인 시도 횟수 제한과 계정 잠금 로직을 구현하면

 

App.vue에서

created 훅에서 인증 상태를 확인하고

라우트 변경 시마다 인증이 필요한 페이지에 대한 접근을 제어할 수 있다

 

라우터에서는

각 라우트에 인증 필요 여부를 메타 데이터로 지정한 뒤,

전역 네비게이션 가드를 사용해 인증이 필요한 페이지에 대한 접근을 제어한다. 

 

 

이런 구조를 통해 

- 사이트 접근 시 자동 로그인 상태 확인,

- 로그인/로그아웃 처리

- 인증이 필요한 페이지에 대한 접근 제어

- 로그인 페이지로의 리다이렉션

- 로그인 성공 시 메인 페이지로 이동

- 로그인 시도 횟수 제한 및 계정 잠금 

과 같은 기능을 구현할 수 있다. 

 

'Vue' 카테고리의 다른 글

Vue_7 생애주기 훅  (0) 2024.09.05
Vue_6 디렉티브  (0) 2024.09.05
Vue_4 (v-if vs v-show)  (1) 2024.09.04
Vue_3 (Vue Query)  (0) 2024.09.04
Vue_2  (2) 2024.09.04