Vue.js Authentication

강정우·2023년 4월 6일
0

vue.js

목록 보기
34/72
post-thumbnail
post-custom-banner

store modules

  • vuex로 굳이 store module을 왜 만들까?
    • 로그인할 때 요청을 보낼 수 있는 엔드포인트 주소가 있다. 이 컴포넌트 내에서 요청을 발송하면 안되기 때문이다.
    • 또 나중에 토큰이나 사용자 로그인 여부 등의 정보도 결국 Vuex에 저장하기 때문이다.
    • 우리가 현재 작업 중인 로그인 모드는 페이지에 표시할 내용에도 영향을 미치기 때문이다.

module 작성

  • 우선 모듈은 각 회사마다 정해놓은 REST API를 따르거나 하면 된다. 하지만 난 혼자 공부중이기에 firebase REST API를 따를 것이다.

modules/auth/index.js

import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
export default {
    state() {
        return {
            userId: null,
            token: null,
            tokenExpiration:null
        };
    },
    mutations,
    actions,
    getters
}

modules/auth/actions.js

export default {
    async login() {

    },
    async signup(context, payload) {
        const res = await fetch('본인 혹은 社에서 지정한 Sign up URL 작성',{
            method: "POST",
            body:JSON.stringify({
                email: payload.email,
                password: payload.password,
                returnSecureToken:true
            })
        });

        const responseData = await res.json();
        if(!res.ok){
            console.log(responseData)
            const error = new Error(responseData.message || 'Failed to authenticate.')
            throw error;
        }

        console.log(responseData);
        context.commit('setUser',{
            token: responseData.idToken,
            userId: responseData.localId,
            tokenExpiration : responseData.expiresIn
        })
    },
}
  • 통상 http req는 앞서 배운대로 actions부터 작성하는 것이 나머지 코드짜기에도 편하다.

  • 작성은 fetch API 혹은 async, await구문을 토대로 작성하면 된다.

  • await의 결과값을 responseData에 담아서 검토하며 state에 set하는 구문을 작성한다.

여기서 context는 같은 module의 setUser에 접근하여 따로 작업이 필요없었지만
만약 메서드가 아닌 state에 접근할 일이 생긴다면 context.rootGetters.state 값 으로 접근하는 것이 좋다.

modules/auth/mutations.js

export default {
    setUser(state, payload) {
        state.token = payload.token;
        state.userId = payload.userId;
        state.tokenExpiration = payload.tokenExpiration

    },
}
  • 위에서 나온 결과값을 작성할 때 들어갈 속성값들을 정의하는 함수를 작성한다.

  • 그리고 이 값들을 토대로 index.js의 init state(){} 를 설정해준다.

modules/auth/getters.js

export default {
    userId(state) {
        return state.userId;
    }
}

커스텀 컴포넌트에서 사용

...
  methods:{
        async submitForm() {
            this.formIsValid = true
            if (this.email === '' || this.password.length < 6) {
                this.formIsValid = false
                return
            }
            this.isLoading = true
            try {
                if (this.mode === 'login') {
                    // login action should be dispatched
                } else {
                    await this.$store.dispatch('signup', {
                        email: this.email,
                        password: this.password
                    });
                }
            } catch (err) {
                this.error = err.message || 'Failed to authenticate, try later'
            }
            this.isLoading = false
        },
        switchAuthMode() {
            if (this.mode === 'login') {
                this.mode = 'signup'
            } else {
                this.mode = 'login'
            }
        },
        handleError(){
            this.error=null;
        }
...
  • submitForm 내부의 로직이 동기식이기 때문에 submitForm에도 async 키워드를 넣어주었다.
<tamplate>
	<div>
        <base-dialog :show="!!error" title="An error occurred" @close="handleError">
            <p>{{error}}</p>
        </base-dialog>
        <base-dialog :show="isLoading" title="Authentication..." fixed>
            <base-spinner></base-spinner>
        </base-dialog>
        <base-card>
            <form @submit.prevent="submitForm">
    ...
  • <div>로 묶어서 상위 컴포넌트에서 <transition>이 이상없도록 지정하였다.

  • 첫번째 <base-dialog>에선 :show="!!error" 구문을 사용하여 에러 메시지를 동적으로 바인드하였고 이를 해제하기위한 @close 도 구현이 되어있다.

    • !! : 확실한 논리결과를 가지기 위해 사용한다. 예를 들어 정의되지 않은 변수 undefined 값을 가진 내용의 논리 연산 시에도 확실한 true / false를 가지도록 하는게 목적이다.
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글