PWA

사용자 인증 - 프로젝트

그랜파 개발자 2024. 8. 3. 03:42

42. 계정 만들기, 로그인 - 개발 1

 

배운 내용으로 계정 등록, 로그인 기능을 개발합니다.

1. 프로젝트 설정

vue create my-auth

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, PWA, Router, Vuex
? Choose a version of Vue.js that you want to start the project with 2.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N) n

2. vuetify 설치

cd my-auth

vue add vuetify

? Choose a preset: (Use arrow keys)
Vuetify 2 - Configure Vue CLI (advanced)
> Vuetify 2 - Vue CLI (recommended)
Vuetify 2 - Prototype (rapid development)
Vuetify 3 - Vite (preview)
Vuetify 3 - Vue CLI (preview)

3. Firebase 설정

npm install firebase

4. Firebase 초기화:

5. Vuex 스토어 모듈

store/index.js 

6. router, App.vue, Home.vue, Abount.vue

ChatGPT가 알려준 Vuetify Component 예제에서 가져 왔습니다.

 

src/router/index.js 

 

src/App.vue 

 

src/views/Home.vue 

 

src/views/About.vue 

7. 실행

8. Source

store/index.js

// src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
import { db, auth, googleProvider } from '@/firebase';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null,
    users: [],
    isLoading: false,
    error: null
  },
  mutations: {
    setUser(state, user) {
      state.user = user;
    },
    setUsers(state, users) {
      state.users = users;
      state.isLoading = false;
    },
    setError(state, error) {
      state.error = error;
      state.isLoading = false;
    },
    setLoading(state, isLoading) {
      state.isLoading = isLoading;
    }
  },
  actions: {
    async fetchUsers({ commit }) {
      commit('setLoading', true);
      try {
        const usersSnapshot = await db.collection('users').get();
        const users = usersSnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
        commit('setUsers', users);
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async addUser({ dispatch }, user) {
      try {
        await db.collection('users').add(user);
        dispatch('fetchUsers');
      } catch (error) {
        console.error('Error adding user:', error);
      }
    },
    async deleteUser({ dispatch }, userId) {
      try {
        await db.collection('users').doc(userId).delete();
        dispatch('fetchUsers');
      } catch (error) {
        console.error('Error deleting user:', error);
      }
    },
    async updateUser({ dispatch }, { userId, user }) {
      try {
        await db.collection('users').doc(userId).update(user);
        dispatch('fetchUsers');
      } catch (error) {
        console.error('Error updating user:', error);
      }
    },
    async login({ commit }, { email, password }) {
      try {
        const { user } = await auth.signInWithEmailAndPassword(email, password);
        commit('setUser', user);
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async register({ commit }, { email, password }) {
      try {
        const { user } = await auth.createUserWithEmailAndPassword(email, password);
        commit('setUser', user);
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async googleLogin({ commit }) {
      try {
        const { user } = await auth.signInWithPopup(googleProvider);
        commit('setUser', user);
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async logout({ commit }) {
      await auth.signOut();
      commit('setUser', null);
    },
    setUser({ commit }, user) {
      commit('setUser', user);
    }
  },
  getters: {
    user: state => state.user,
    users: state => state.users,
    isLoading: state => state.isLoading,
    error: state => state.error
  }
});

 

src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';
import About from '@/views/About.vue';

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
});

export default router;

 

src/App.vue

<template>
  <v-app>
    <v-navigation-drawer app>
      <v-list>
        <v-list-item link>
          <router-link to="/">Home</router-link>
        </v-list-item>
        <v-list-item link>
          <router-link to="/login">Login</router-link>
        </v-list-item>
        <v-list-item link>
          <router-link to="/about">About</router-link>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>

    <v-app-bar app>
      <v-toolbar-title>My Vuetify App</v-toolbar-title>
    </v-app-bar>

    <v-main>
      <router-view></router-view>
    </v-main>
  </v-app>
</template>

<script>
export default {
  name: 'App'
};
</script>

 

src/views/Home.vue

<template>
  <v-container>
    <h1>Home Page</h1>
    <v-btn color="primary">Primary Button</v-btn>
  </v-container>
</template>

<script>
export default {
  name: 'Home'
};
</script>

 

src/views/About.vue

Copy<template>
  <v-container>
    <h1>About Page</h1>
    <v-card>
      <v-card-title>About Vuetify</v-card-title>
      <v-card-text>
        Vuetify는 Vue.js 애플리케이션을 위한 Material Design 컴포넌트 프레임워크입니다.
      </v-card-text>
    </v-card>
  </v-container>
</template>

<script>
export default {
  name: 'About'
};
</script>