[Vue.js] 토큰 기반 인증(#4. 유저 로그인)

하수도키

·

2020. 10. 28. 23:42

728x90
반응형
SMALL

 

2020/10/31 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증 (#7. 자동 로그인)

2020/10/31 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증 catch 사용 (#6. 에러 처리)

2020/10/30 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증(#5. 유저 로그아웃)

2020/10/28 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증(#4. 유저 로그인)

2020/08/30 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증(#3. 사용자 등록)

2020/07/27 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증(#2. 인증을 위한 프로젝트 구조 살피기)

2020/07/24 - [개발일기/Vue.js] - [Vue.js] 토큰 기반 인증(#1. 인증소개)

[Vue.js] 토큰 기반 인증(#4. 유저 로그인)

개요

  • 로그인 구현
  • LoginUser.vue 생성
  • 라우팅 추가
  • 로그인, 로그아운 UX 추가
  • Vuex 적용

Login 페이지 만들기

  • Register 페이지에서 로그인 시 필요 없는 name 영역만 삭제하면 된다.
   data () {
     return {
       email: '',
       password: ''
     }
   },
   methods: {
     login () {
       this.$store
         .dispatch('login', {
         email: this.email,
         password: this.password
       })
         .then(() => { this.$router.push({ name: 'dashboard' }) })
     }
   }
  • login 메소드는 login Vuex Action에 dispatch하고 유져의 email, password를 payload로 보낸다. 정상적으로 처리되면 dashboard route로 리다이렉트된다.(RgisterUser 컴포넌트에서 했던 것들)
  • 이제 store.js에 가서 Login Action으로 작성하자.

Vuex: login action 생성

  • login Action도 reigster Action이 작동하는 방법과 비슷하다.
  • Axios Post 요청이 필요하고 이번엔 서버의 /login endpoint에 요청한다.
  • LoginUser 컴포넌트에 payload를 credentials로 보낸다.
login ({ commit }, credentials) {
  return axios
    .post('//localhost:3000/login', credentials)
    .then(({ data }) => {
    commit('SET_USER_DATA', data)
  })
}
  • 서버가 응답하면 data를 받고 SET_USER_DATA에 data를 payload로 넘기고 commit한다.

서버 로그인 로직

  • 서버 /login으로 POST하면 db폴더에 있는 user.json 파일을 읽고 서버로 같이 보내진 credentials(email,password)과 비교한다.
  • 만약 일치하면 JWT token을 생성하고 생성한 토큰과 응답 데이터(response data)를 반환한다.
  • login Action이 SET_USER_DATA mutaion에 커밋하면서 아래와 같이 3단계가 이루어진다.
    • VuexState에 userData 저장
    • localStorage에 userData 복사본 저장
    • Axios Header userData.token 추가
  • axios header에 JWT token을 가지고 있으므로 dashboard 경로(route)로 리다이렉트 될때 개인 자료(private event data)에 접근할 수 있어야 한다.
  • 이제 LoginUser를 라우트 설정하자

라우터에 LoginUser 추가하기

  • router.js에 routes 배열에 추가한다.
/src/router.js
import LoginUser from './views/LoginUser.vue'
  ...
  routes: [
    ...
    {
      path: '/login',
      name: 'login',
      component: LoginUser
    }
  ]

테스트

  • localhost:8080:/login에 가서 user.json 저장되어있는 email, password를 입력해라.
  • (이 백엔드 서버는 연습용이라 등록수가 1명이다.)
  • 로그인 버튼 클릭하고 성공적으로 dashboard로 리다이렉트면 private data가 보여진다.

Home에 라우터 링크 연결

  • 현재까지 URL에 /login, /register로 직업 접속했다.
  • Home에서 Login, Register 링크를 생성한다.
  • 그리고 Login, Register 페이지에서는 각각 Login에서는 Register 링크, Register에서는 Login 링크를 생성한다.(로그인 유무에 따른 처리)
//Home.vue
<div>
  To use this app you'll need to
  <router-link to="/login">
    Login
  </router-link>
  or
  <router-link to="/register">
    Register
  </router-link>
</div>

// LoginUser.vue
<form>
  ...
  <button type="submit" name="button">
    Login
  </button>

  <router-link to="/register">
    Don't have an account? Register.
  </router-link>
</form>

// Register.vue
<form>
  ...
  <button type="submit" name="button">
    Login
  </button>

  <router-link to="/login">
    Already have an account? Login.
  </router-link>
</form>

로그인 버튼 추가

  • 상단 GNB 영역에 로그인 버튼 추가하기
/src/components/AppNav.vue
<router-link to="/login" class="button">
  Login
</router-link>
  • 사용자가 로그인했을때 다시 로그인하거나, 등록하라는 메시지를 보지 말아야 한다.
  • 로그인 한 상태인데 login, register 버튼이 보이지 말아야 한다.
  • Vuex State를 사용해보자.

로그인 상태일때 Login, Register 보여주지 않기

  • 유저가 로그인한 상태이며 로그인하라는 메시지를 보이지 않게 해야 한다. Vuex State를 이용해 Router-links를 숨겨보자.
  • this.$store.state.user 표현식을 이용해 템플릿을 수정해보자.
<template>
  ...
  <template v-if="!this.$store.state.user">
    <div>
      To use this app you'll need to
      <router-link to="/login">
        Login
      </router-link>
      or
      <router-link to="/register">
        Register
      </router-link>
    </div>
  </template>
  ...
</template>
  • 잘 작동하지만 이상적인 방식이 아니다. 템플릿 가독성이 좋길 원한다. Vuex를 잘 모르는 사람(디자이너)가 있을 수 있다.
  • 앱이 커질수록 Store를 모듈로 분해하거나 아이템의 이름을 변경하거나 여러가지 이슈들이 있을 수 있다. 이때마다 v-if문을 수정하기는 힘들다.
  • 그래서 좋은 방법은 유저가 로그인 했는지 확인하는 getter를 제공하는 것이다. 어떠한 컴포넌트에서 접근 가능한!!
// store.js
...
getters: {
  loggedIn (state) {
    return !!state.user
  }
}
  • true이면 로그인 한 상태, false이면 로그아웃상태(null)
  • 이제 이 getters를 어떠한 컴포넌트에서든 접근가능하게 만들자.
  • src안에 vuex폴더를 만들고 store.js를 여기다 이동시키고, helpers.js를 생성하자.
  • helpers.js에 Vuex의 mapGetters를 import 한다.
import { mapGetters } from 'vuex'

export const authComputed = {
  ...mapGetters(['loggedIn'])
}
  • store.js에 있는 getters의 loggedIn 를 mapGetters를 이용해 authComputed로 내보낸다.(export)
  • 이제 vuex helper를 import하면 어디서든 사용이 가능하다.
  • Home에다 추가해보자.
src/views/Home.vue
<script>
  import { authComputed } from '../vuex/helpers.js'

export default {
  computed: {
    ...authComputed
  }
}
</script>
  • Home 컴포넌트에서 loggedIn getter를 포함한 authComputed를 자유롭게 사용할 수 있다.
  • <template v-if="!this.$store.state.user"> 대신에 loggedIn로 사용할 수 있다.
src/views/Home.vue
<template>
  ...
  <div v-if="!loggedIn">
    To use this app you'll need to
    <router-link to="/login">
      Login
    </router-link>
    or
    <router-link to="/register">
      Register
    </router-link>
  </div>
  ...
</template>
  • AppNav에도 적용 하자.
src/components/AppNav.vue
<template>
  <div id="nav">
    ...
    <router-link v-if="!loggedIn" to="/login" class="button">
      Login
    </router-link>
  </div>
</template>

<script>
  import { authComputed } from '../vuex/helpers.js'
  export default {
    computed: {
      ...authComputed
    }
  }
</script>

정리

  • 로그인 하는 법을 알아봤고, 로그인 유무에 따른 UX를 살펴봤다.(Vuex의 getter를 활용했다.)
  • 다음 포스팅은 로그아웃에 대해 알아보겠다. :)

소스코드

#4 소스코드

728x90
반응형
LIST