vue + jpa project (14) - vuex설정 및 로그인 화면 생성 본문

프로그램/Vue.js

vue + jpa project (14) - vuex설정 및 로그인 화면 생성

반응형

로그인 처리 부분을 이 장에서 부터 시작한다.

일단 프론트 단에서 로그인 화면을 생성한다.

나중에 설명을 추가로 하겠지만 스프링 시큐리티를 쓰면서 기본 제공하는 login 페이지를 이용할 수 있지만

제약사항이 있어서 별도 로그인 페이지를 만들어서 진행하는 것으로 한다.

 

진행에 앞서 로그인 처리를 위해서 상태를 저장하는 vuex패키지를 설치를 해야한다.

vue 프로젝트 폴더로 가서 아래 명령어를 실행하여 설치한다. 

이장에서는 vuex를 사용하지는 않지만 미리 작업을 해두는 것이다.

npm install vuex

vuex 패키지의 처리 루틴은 구글링으로 찾아서 확인해보면 알수가 있어서 여기서는 생략한다.

 

src 폴더 아래에 vuex 폴더를 만들고 mutation_types.js, mutation.js, getters.js 파일을 각각 추가하고 

아래와 같이 추가한다. (참고로 mutation이 setter의 개념이다)

// src/vuex/mutation_types.js
export const USER_ID = 'USER_ID'
export const ERROR_STATE = 'ERROR_STATE'
export const IS_AUTH = 'IS_AUTH'
// src/vuex/mutation.js
import * as types from './mutation_types.js'

export default {
    [types.USER_ID] (state, userId) {
        state.userId = userId
    },
    [types.ERROR_STATE] (state, errorState) {
        state.errorState = errorState
    },
    [types.IS_AUTH] (state, isAuth) {
        state.isAuth = isAuth
    }
}
// src/vuex/getters.js
export default {
  getUserId: state => state.userId,
  getErrorState: state => state.errorState,
  getIsAuth: state => state.isAuth,
  loggedIn(state) {
    return !!state.user
  }
}

 

그리고 api 처리를 위해서 src/service/common/ 폴더를 만들고 loginAPI.js 를 아래와 같이 만든다.

일단 DB 와 연동이 안된 상태여서 return 값에 무조건 data를 임시로 집어넣었다.

const getUserInfo = (userId, userPw)=> {

  const reqData = {
    'user_id': userId,
    'user_pw': userPw
  }

  return {
    'data' : {
      'user_id' : reqData.user_id,
      'access_token' : 'user_token1',
      'refresh_token' : 'user_token2',
      'user_role' : 'ADM',
    }
  }
}

export default {

  async doLogin(userId, userPw) {
    
    try {
      const getUserInfoPromise = getUserInfo(userId, userPw)
      const [userInfoResponse] = await Promise.all([getUserInfoPromise])
      if (userInfoResponse.data.length === 0) {
        return 'notFound'
      } else {
        localStorage.setItem('access_token', userInfoResponse.data.access_token)
        localStorage.setItem('refresh_token', userInfoResponse.data.refresh_token)
        localStorage.setItem('user_role', userInfoResponse.data.user_role)
        return userInfoResponse
      }
    } catch(err) {
      console.log(err)
    }
  }
}

vuex 폴더 아래에 actions.js 파일을 생성하고 아래와 같이 추가한다.

import {USER_ID, ERROR_STATE, IS_AUTH} from './mutation_types.js'
import loginAPI from '@/service/common/loginAPI.js'

let setUserId = ({commit}, data) => {
  commit(USER_ID, data)
}

let setErrorState = ({commit}, data) => {
  commit(ERROR_STATE, data)
}

let setIsAuth = ({commit}, data) => {
  commit(IS_AUTH, data)
}

let processResponse = (store, loginResponse) => {
  switch (loginResponse) {
    case 'notFound':
      setErrorState(store, 'Wrong ID or Password')
      setIsAuth(store, false)
      break
    default:
      setUserId(store, loginResponse.user_id)
      setErrorState(store, '')
      setIsAuth(store, true)
      break
  }
}

export default {
  async login (store, {user_id, user_pw}) {
    
    let loginResponse = await loginAPI.doLogin(user_id, user_pw)
    processResponse(store, loginResponse)
    return store.getters.getIsAuth
  }
}

 

위 파일들을 하나로 합쳐서 사용 가능하도록  vuex 폴더에 store.js 파일을 만들고 아래와 같이 추가한다.

// src/vuex/store.js
import {createStore} from "vuex";
import getters from "./getters.js";
import mutations from "./mutations.js";
import actions from "./actions.js";

export default createStore({
  state: {
    user: null,
    isLogin: false,
  },
  mutations,
  getters,
  actions
});

그리고 다시 store.js를 main.js에 최종 아래와 같이 추가한다.

import './assets/board.css' 

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/router.js'
import axios from 'axios' // router 아래에 위치 해야함
import store from './vuex/store.js'

const app = createApp(App)
app.config.globalProperties.$axios = axios;  //전역변수로 설정 컴포넌트에서 this.$axios 호출할 수 있음
app.config.globalProperties.$serverUrl = '//localhost:8081' //api server
app.config.globalProperties.$store = store  // 전역변수로 $store 사용등록

app
  .use(router)
  .use(store)     //store 등록
  .mount('#app')

포함되는 순서를 본다면  mutation_types -> mutation으로 우선되고  loginAPI -> action -> (getter, mutations, action) 을 

합쳐서 store로 포함이 된다. 그리고 최종적으로 main.js 에 store 가 포함되고 App에 등록한다.


이제 로그인 화면을 만들어보자

views 폴더 아래 common 폴더에 Login.vue 파일을 생성한다.

<template>
  <div>
    <div>
      <h2>로그인</h2>
      <div id="loginForm">
        <form @submit.prevent="fnLogin">
          <p>
            <input class="w3-input" name="uid" placeholder="Enter your ID" v-model="user_id"><br>
          </p>
          <p>
            <input name="password" class="w3-input" placeholder="Enter your password" v-model="user_pw" type="password">
          </p>
          <p>
            <button type="submit" class="w3-button w3-green w3-round">Login</button>
          </p>
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import {mapActions, mapGetters} from 'vuex'   //vuex 추가

export default {
  data() {
    return {
      user_id: '',
      user_pw: ''
    }
  },
  methods: {
    ...mapActions(['login']),     //vuex/actions에 있는 login 함수

    async fnLogin() {       //async 함수로 변경
      if (this.user_id === '') {
        alert('ID를 입력하세요.')
        return
      }

      if (this.user_pw === '') {
        alert('비밀번호를 입력하세요.')
        return
      }

      //로그인 API 호출 
      try {
        let loginResult = await this.login({user_id: this.user_id, user_pw: this.user_pw})
        if (loginResult) alert('로그인 결과 : ' + loginResult)
      } catch (err) {
        if (err.message.indexOf('Network Error') > -1) {
          alert('서버에 접속할 수 없습니다. 상태를 확인해주세요.')
        } else {
          alert('로그인 정보를 확인할 수 없습니다.')
        }
      }
    }
  },
  computed: {
    ...mapGetters({
      errorState: 'getErrorState'
    })
  }
}
</script>

 

그리고 board.css 파일에 아래 스타일을 추가한다.

/* board.css */
... 중략
#loginForm {
    width: 500px;
    margin: auto;
}

그리고  router폴더 아래에 home.js 를 아래와 같이 수정한다.

import Home from '@/views/common/Home.vue'
import Login from '@/views/common/Login.vue'


export const HomeRouters = [
  {
    path: '/',
    name: 'Home',
    component : Home,
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
]

 

여기까지하고 일단 화면에서 로그인을 클릭하면 아래와 같이 로그인창이 뜨고 일단 로그인을 시도하면

로그인 결과 true 가 alert 창으로 뜬다.

다음 장에서는 로그인 처리를 위한 백엔드 쪽을 진행하겠다.

반응형

프로그램/Vue.js Related Articles

MORE

Comments