PWA

사용자 인증 - Google 계정으로 로그인

그랜파 개발자 2024. 8. 8. 16:30

47. Google 계정으로 Login

구글 계정으로 로그인은 다음과 같은 시퀀스를 가집니다.

  1. 회원은 ‘Google Login’ 버튼을 누릅니다.
  2. my-auth 앱은 구글 계정으로 구글에 로그인하여 user객체를 받습니다.
  3. 구글에서 받은 user객체의 uid로 my-auth 웹앱에 등록된 계정 정보를 가져옵니다.
  4. my-auth 계정 정보로 웹앱에 로그인 처리를 합니다.
  5. 로그인을 하면 app-bar의 우측에 로그아웃 아이콘이 나타납니다.
  6. 로그인 상태에서 브라우저를 떠나도 다시 사이트에 접속하면 자동 로그인이 됩니다.

UI

 

로그인 후 계정 정보를 읽는 방법이 로그인에서 보았듯이 두 가지 방법이 있습니다.

  1. firestore DB에서 직접 계정 정보를 읽는 방법.
  2. 사이트 접속할 때 이미 전체 회원의 정보를 읽어 리스트고 가지고 있다면 구글 로그인 후에 받은 uid를 이용하여 이미 읽어온 users에서 계정 정보를 찾는 방법.

웹앱은 사이트에 접속을 하면 모든 회원 정보를 읽어 둡니다. 여기에서 로그인한 회원의 정보를 가져오도록 해 봅시다.

ChatGPT에게 물었습니다.

How to find a user with a specific uid in users' uids?

users 에서 user의 uids에 특정 uid를 가진 user를 찾는 방법은?

To find a user with a specific uid in the uids array field of documents in the users collection in Firestore, you can use the array-contains query. This query allows you to filter documents where the array field contains a specific value.
Firestore의 users 컬렉션에 있는 문서의 uids 배열 필드에서 특정 uid를 가진 사용자를 찾으려면 array-contains 쿼리를 사용하면 됩니다. 이 쿼리를 사용하면 배열 필드에 특정 값이 포함된 문서를 필터링할 수 있습니다.

Here’s how you can implement this in JavaScript using Firestore:
Firestore를 사용하여 JavaScript로 이를 구현하는 방법은 다음과 같습니다.

Step-by-Step Implementation

  1. Initialize Firebase: Make sure Firebase is initialized and Firestore is set up.
    Firebase 초기화: Firebase가 초기화되고 Firestore가 설정되었는지 확인하세요.
  2. Write the Query: Use the where method with array-contains to find documents where the uids array contains the specific uid.
    쿼리 작성: array-contains와 함께 where 메소드를 사용하여 uids 배열에 특정 uid가 포함된 문서를 찾습니다
  3. Handle the Query Results: Process the query results to retrieve and display the matching documents.
    쿼리 결과 처리: 쿼리 결과를 처리하여 일치하는 문서를 검색하고 표시합니다.

Example Code

1. Firebase Initialization

First, ensure that your Firebase configuration and initialization are set up correctly:
먼저 Firebase 구성 및 초기화가 올바르게 설정되었는지 확인하세요.

// firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore';

const firebaseConfig = {
  apiKey: 'your-api-key',
  authDomain: 'your-auth-domain',
  projectId: 'your-project-id',
  storageBucket: 'your-storage-bucket',
  messagingSenderId: 'your-messaging-sender-id',
  appId: 'your-app-id'
};

firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

export { db };

2. Firestore Query

Next, write the function to query the users collection and find documents where the uids array contains the specific uid:
다음으로, users 컬렉션을 쿼리하고 uids 배열에 특정 uid가 포함된 문서를 찾는 함수를 작성합니다.

// fetchData.js
import { db } from './firebase';

async function fetchDocumentsWithUid(uid) {
  try {
    const querySnapshot = await db.collection('users').where('uids', 'array-contains', uid).get();

    if (querySnapshot.empty) {
      console.log('No matching documents.');
      return [];
    }

    const documents = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    console.log('Matching documents:', documents);
    return documents;
  } catch (error) {
    console.error('Error fetching documents:', error);
  }
}

// Example usage
fetchDocumentsWithUid('specific-uid');

Explanation

  • firebase.js: This file contains the Firebase configuration and initialization code.
    firebase.js: 이 파일에는 Firebase 구성 및 초기화 코드가 포함되어 있습니다.
  • fetchData.js: This file contains the fetchDocumentsWithUid function which:
    fetchData.js: 이 파일에는 다음과 같은 기능을 수행하는 fetchDocumentsWithUid 함수가 포함되어 있습니다.
  • Queries the users collection using where('uids', 'array-contains', uid) to filter documents.
    문서를 필터링하기 위해 where('uids', 'array-contains', uid)를 사용하여 users 컬렉션을 쿼리합니다.
  • Checks if the query result is empty and logs a message if no matching documents are found.
    쿼리 결과가 비어 있는지 확인하고 일치하는 문서가 없으면 메시지를 기록합니다.
  • Maps over the query snapshot to extract document data and logs the matching documents.
    쿼리 스냅샷을 매핑하여 문서 데이터를 추출하고 일치하는 문서를 기록합니다.

Example Usage and Testing

To test the query, you can call the fetchDocumentsWithUid function with a specific uid value and check the console for the results.
쿼리를 테스트하려면 특정 uid 값을 사용하여 fetchDocumentsWithUid 함수를 호출하고 콘솔에서 결과를 확인할 수 있습니다.

fetchDocumentsWithUid('specific-uid');

Inserting Sample Data for Testing

If you need to insert sample data into Firestore for testing, you can use the following function:
테스트를 위해 Firestore에 샘플 데이터를 삽입해야 하는 경우 다음 기능을 사용할 수 있습니다.

// addUser.js
import { db } from './firebase';

async function addUser() {
  try {
    await db.collection('users').add({
      uids: ['specific-uid', 'another-uid'],
      name: 'Test User',
      email: 'test@example.com'
    });
    console.log('User added');
  } catch (error) {
    console.error('Error adding user:', error);
  }
}

// Example usage
addUser();

Full Example for Testing

Here’s a full example that includes both the query and sample data insertion:
다음은 쿼리와 샘플 데이터 삽입을 모두 포함하는 전체 예입니다.

 

firebase.js

// firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore';

const firebaseConfig = {
  apiKey: 'your-api-key',
  authDomain: 'your-auth-domain',
  projectId: 'your-project-id',
  storageBucket: 'your-storage-bucket',
  messagingSenderId: 'your-messaging-sender-id',
  appId: 'your-app-id'
};

firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

export { db };

 

addUser.js

// addUser.js
import { db } from './firebase';

async function addUser() {
  try {
    await db.collection('users').add({
      uids: ['specific-uid', 'another-uid'],
      name: 'Test User',
      email: 'test@example.com'
    });
    console.log('User added');
  } catch (error) {
    console.error('Error adding user:', error);
  }
}

// Example usage
addUser();

 

fetchData.js

// fetchData.js
import { db } from './firebase';

async function fetchDocumentsWithUid(uid) {
  try {
    const querySnapshot = await db.collection('users').where('uids', 'array-contains', uid).get();

    if (querySnapshot.empty) {
      console.log('No matching documents.');
      return [];
    }

    const documents = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    console.log('Matching documents:', documents);
    return documents;
  } catch (error) {
    console.error('Error fetching documents:', error);
  }
}

// Example usage
fetchDocumentsWithUid('specific-uid');

 

This full example sets up Firebase, inserts a sample user with a uids array, and queries the collection to find documents where the uids array contains a specific uid.
이 전체 예시에서는 Firebase를 설정하고, 'uids' 배열로 샘플 사용자를 삽입하고, 컬렉션을 쿼리하여 'uids' 배열에 특정 'uid'가 포함된 문서를 찾습니다.

ChatGPT의 답이 질문 의도와는 다릅니다. 원하는 답이 아닙니다.

다시 질문했습니다.

How to find a user with a specific uid from the users pre-read in the store?

store에 미리 읽어 둔 users에서 특정 uid를 가진 user를 찾는 방법은?

To find a user with a specific uid from a list of users pre-read into a Vuex store, you can follow these steps:
Vuex 스토어를 미리 읽은 사용자 목록에서 특정 uid를 가진 사용자를 찾으려면 다음 단계를 따르세요.

  1. Initialize Vuex Store: Create a Vuex store with a state to hold the list of users.
    Vuex 스토어 초기화: 사용자 목록을 보관할 상태가 있는 Vuex 스토어를 생성합니다.
  2. Load Users into the Store: Populate the state with user data from Firestore.
    스토어에 사용자 로드: Firestore의 사용자 데이터로 상태를 채웁니다.
  3. Create a Getter: Write a getter to find a user by uid.
    Getter 만들기: uid로 사용자를 찾는 getter를 작성합니다.
  4. Use the Getter in a Component: Access the getter from your Vue component to find and display the user.
    구성 요소에서 Getter 사용: Vue 구성 요소에서 getter에 액세스하여 사용자를 찾고 표시합니다.

Step-by-Step Implementation

1. Initialize Vuex Store

First, set up your Vuex store to include state, actions, mutations, and getters.
먼저 상태, 작업, 돌연변이 및 getter를 포함하도록 Vuex 스토어를 설정하세요.

 

store.js

// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import { db } from './firebase'; // Ensure you have your firebase.js with Firestore setup

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    users: []
  },
  mutations: {
    setUsers(state, users) {
      state.users = users;
    }
  },
  actions: {
    async loadUsers({ commit }) {
      const users = [];
      try {
        const querySnapshot = await db.collection('users').get();
        querySnapshot.forEach(doc => {
          users.push({ id: doc.id, ...doc.data() });
        });
        commit('setUsers', users);
      } catch (error) {
        console.error('Error loading users:', error);
      }
    }
  },
  getters: {
    getUserByUid: (state) => (uid) => {
      return state.users.find(user => user.uids && user.uids.includes(uid));
    }
  }
});

2. Load Users into the Store

Call the loadUsers action to fetch and populate the user data into the store when your application initializes.
애플리케이션이 초기화될 때 loadUsers 작업을 호출하여 사용자 데이터를 가져와서 스토어에 채웁니다.

 

main.js

// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';

Vue.config.productionTip = false;

new Vue({
  store,
  render: h => h(App),
  created() {
    this.$store.dispatch('loadUsers');
  }
}).$mount('#app');

3. Use the Getter in a Component

Access the getter from your Vue component to find a user by uid.
Vue 구성 요소에서 getter에 액세스하여 uid로 사용자를 찾습니다.

 

UserProfile.vue

// UserProfile.vue
<template>
  <div v-if="user">
    <h1>{{ user.name }}</h1>
    <p>Email: {{ user.email }}</p>
    <p>UIDs: {{ user.uids.join(', ') }}</p>
  </div>
  <div v-else>
    <p>No user found with the specified UID.</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex';

export default {
  props: {
    uid: {
      type: String,
      required: true
    }
  },
  computed: {
    ...mapGetters(['getUserByUid']),
    user() {
      return this.getUserByUid(this.uid);
    }
  }
};
</script>

Example Usage

You can use the UserProfile component in another component or directly in your App.vue:
다른 구성 요소에서 UserProfile 구성 요소를 사용하거나 App.vue에서 직접 사용할 수 있습니다.

 

App.vue

<!-- App.vue -->
<template>
  <div id="app">
    <UserProfile uid="specific-uid" />
  </div>
</template>

<script>
import UserProfile from './components/UserProfile.vue';

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

Explanation

1. Vuex Store:

  • State: Holds the list of users.
    State: 사용자 목록을 보유합니다.
  • Mutations: setUsers mutation to update the user list.
    Mutations: 사용자 목록을 업데이트하기 위한 setUsers 변형입니다.
  • Actions: loadUsers action to fetch users from Firestore.
    Actions: Firestore에서 사용자를 가져오는 loadUsers 작업입니다.
  • Getters: getUserByUid getter to find a user by uid.
    Getters: uid로 사용자를 찾는 getUserByUid getter입니다.

2. Main App:

  • Dispatches the loadUsers action on creation to populate the store with user data.
    생성 시 loadUsers 작업을 전달하여 저장소를 사용자 데이터로 채웁니다.

3. UserProfile Component:

  • Receives a uid as a prop.
    'uid'를 prop으로 받습니다.
  • Uses the getUserByUid getter to find the user with the specified uid.
    getUserByUid getter를 사용하여 지정된 uid를 가진 사용자를 찾습니다.
  • Displays user information if found, otherwise shows a message indicating no user was found.
    사용자가 발견되면 정보를 표시하고, 그렇지 않으면 사용자를 찾지 못했다는 메시지를 표시합니다.
  • This setup ensures that user data is efficiently managed in the Vuex store and can be easily accessed and filtered by components.
    이 설정을 사용하면 Vuex 저장소에서 사용자 데이터가 효율적으로 관리되고 구성 요소별로 쉽게 액세스하고 필터링할 수 있습니다.

쓸만한 답을 받았습니다. 그런데 우리는 getUserByUid getter를 actions에서 호출해야 합니다.

ChatGPT에게 물었습니다.

How to call getter's function in store actions?

store actions에서 getter의 함수를 호출하는 방법은?

To call a getter's function inside a Vuex store action, you can use the getters argument provided to the action function. This allows you to access any of the defined getters directly from within the action.
Vuex 스토어 액션 내에서 getter 함수를 호출하려면 액션 함수에 제공된 getters 인수를 사용할 수 있습니다. 이를 통해 액션 내에서 직접 정의된 getter에 액세스할 수 있습니다.

Here’s how you can do it:
방법은 다음과 같습니다.

  1. Define the Getter: Ensure that the getter is defined in your store. Getter 정의: getter가 상점에 정의되어 있는지 확인하십시오.
  2. Access the Getter in an Action: Use the getters argument in the action to call the getter.
    액션에서 Getter에 액세스: 액션에서 getters 인수를 사용하여 getter를 호출합니다.

Step-by-Step Implementation

1. Define the Vuex Store with Getter and Action

First, define your Vuex store with the necessary state, getters, and actions. 먼저 필요한 상태, getter 및 작업을 사용하여 Vuex store를 정의합니다.

 

store.js

// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import { db } from './firebase'; // Ensure you have your firebase.js with Firestore setup

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    users: []
  },
  mutations: {
    setUsers(state, users) {
      state.users = users;
    },
    addUser(state, user) {
      state.users.push(user);
    }
  },
  actions: {
    async loadUsers({ commit }) {
      const users = [];
      try {
        const querySnapshot = await db.collection('users').get();
        querySnapshot.forEach(doc => {
          users.push({ id: doc.id, ...doc.data() });
        });
        commit('setUsers', users);
      } catch (error) {
        console.error('Error loading users:', error);
      }
    },
    async addUser({ commit, getters }, user) {
      try {
        const existingUser = getters.getUserByUid(user.uid);
        if (!existingUser) {
          await db.collection('users').add(user);
          commit('addUser', user);
        } else {
          console.log('User already exists');
        }
      } catch (error) {
        console.error('Error adding user:', error);
      }
    }
  },
  getters: {
    getUserByUid: (state) => (uid) => {
      return state.users.find(user => user.uids && user.uids.includes(uid));
    }
  }
});

2. Using the Getter in an Action

In the addUser action, you can see how the getter getUserByUid is used to check if the user already exists before adding a new user to Firestore and committing the mutation to update the state.
addUser 작업에서는 Firestore에 새 사용자를 추가하고 상태를 업데이트하기 위해 변형을 커밋하기 전에 getter getUserByUid를 사용하여 사용자가 이미 존재하는지 확인하는 방법을 확인할 수 있습니다.

Example Usage

Here’s how you might call the addUser action from a Vue component:
Vue 구성 요소에서 addUser 작업을 호출하는 방법은 다음과 같습니다.

 

AddUser.vue

// AddUser.vue
<template>
  <div>
    <v-form @submit.prevent="handleSubmit">
      <v-text-field v-model="name" label="Name" required></v-text-field>
      <v-text-field v-model="email" label="Email" required></v-text-field>
      <v-text-field v-model="uid" label="UID" required></v-text-field>
      <v-btn type="submit">Add User</v-btn>
    </v-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: '',
      email: '',
      uid: ''
    };
  },
  methods: {
    handleSubmit() {
      const newUser = {
        name: this.name,
        email: this.email,
        uids: [this.uid]
      };
      this.$store.dispatch('addUser', newUser);
    }
  }
};
</script>

Explanation

1. Vuex Store:

  • State: Holds the list of users.
    State: 사용자 목록을 보유합니다.
  • Mutations: setUsers to update the user list and addUser to add a new user.
    Mutations: 사용자 목록을 업데이트하는 setUsers 및 새 사용자를 추가하는 addUser.
  • Actions:
    • loadUsers to fetch and populate users from Firestore.
      loadUsers는 Firestore에서 사용자를 가져와 채웁니다.
    • addUser to add a new user if they don’t already exist (checked using the getter).
      새로운 사용자가 아직 존재하지 않는 경우 addUser를 사용하여 추가합니다(getter를 사용하여 확인).
  • Getters: getUserByUid to find a user by uid.
    Getters: getUserByUid는 uid로 사용자를 찾습니다.

2. AddUser Component:

  • Provides a form to input user details.
    사용자 세부정보를 입력하는 양식을 제공합니다.
  • Calls the addUser action with the new user data when the form is submitted.
    양식이 제출되면 새 사용자 데이터로 addUser 작업을 호출합니다.

By using getters within actions, you can ensure that your actions can perform more complex logic that depends on the current state of the store, providing a more powerful and flexible way to manage your application's state.
액션 내에서 getter를 사용하면 액션이 저장소의 현재 상태에 따라 더 복잡한 논리를 수행할 수 있도록 보장하여 애플리케이션 상태를 관리하는 더 강력하고 유연한 방법을 제공할 수 있습니다.

ChatGPT가 시키는 대로 했습니다.

src/views/Login.vue

 

src/store/index.js 

Source Code

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
import { auth } from '@/firebase';

Vue.config.productionTip = false

new Vue({
  router,
  store,
  vuetify,
  render: h => h(App),
  created() {
    // Set up Firebase auth state change listener
    const { dispatch } = this.$store;

    dispatch('fetchUsers');

    auth.onAuthStateChanged(user => {
      // 우리는 우리의 웹앱에 저장된 계정 정보를 사용한다.
      // user.uid로 웹앱의 firestore DB에서 계정 정보를 가져온다. 
      if(user != null) {
        dispatch('fetchUserWithUid', {uid: user.uid});
      }
    });
  }
}).$mount('#app')

 

src/views/Login.vue

<!-- src/views/Login.vue -->
<template>
  <v-container>
    <v-row>
      <v-col cols="12" class="text-center my-5">
        <h3>로그인</h3>
      </v-col>      
    </v-row>
    <v-row>
      <v-col class="text-center" cols="10" offset="1" sm="8" offset-sm="2">   
        <v-form @submit.prevent="loginUser">
          <v-text-field v-model="email" label="이메일" type="email" required></v-text-field>
          <v-text-field v-model="password" label="비밀번호" type="password" required></v-text-field>
          <v-btn type="submit" color="primary">Login</v-btn>
          <v-alert v-if="error" type="error" dismissible>{{ error }}</v-alert>
        </v-form>
      </v-col>
    </v-row>
    <v-row>
      <v-col class="text-center" cols="10" offset="1" sm="8" offset-sm="2">  
        <v-btn color="red" @click="googleLogin" dark>
          <v-icon left>mdi-google</v-icon>
          Sign in with Google
        </v-btn>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import { mapActions, mapGetters } from 'vuex';

export default {
  name: 'Login',
  data() {
    return {
      email: '',
      password: ''
    };
  },
  computed: {
    ...mapGetters(['error'])
  },
  methods: {
    ...mapActions(['login']),
    ...mapActions(['googleLogin']),
    async loginUser() {
      await this.login({ email: this.email, password: this.password });
    }
  }
};
</script>

 

src/store/index.js

// src/store/index.js

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

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() }));
        console.log(users);
        commit('setUsers', users);
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async addUser({ dispatch, commit }, user) {
      try {
        await db.collection('users').add(user)
        .then(newUser => {

          // 로그인 설정
          user.id = newUser.id;
          console.log('addUser :', user);
          commit('setUser', 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, dispatch }, { email, password }) {
      try {
        const { user } = await auth.signInWithEmailAndPassword(email, password);;
        // 웹앱의 계정 정보를 가져와 로그인 설정을 한다.
        dispatch('fetchUserWithUid', {uid: user.uid});       
        router.push("/");   // home으로
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async fetchUserWithUid({ commit }, {uid}) {
      //console.log(uid);
      try {
        const querySnapshot = await db.collection('users').where('uids', 'array-contains', uid).get();
        //const user = querySnapshot.docs.map(doc => doc.data());
        const user = querySnapshot.docs. map(doc => ({ id: doc.id, ...doc.data() }));
        //console.log('Matching user:', user[0]);
        // 로그인 설정을 한다.
        commit('setUser', user[0]);
      } catch (error) {
        console.error('Error fetching user:', error);
      }            
    },
    async register({ commit, dispatch }, { email, password, name }) {
      try {
        const { user } = await auth.createUserWithEmailAndPassword(email, password, name);
        // 웹앱에 계정을 만든다.
        const newUser = {
          email: email,
          name: name,
          uids: [user.uid]
        };
        // newUser 객체가 추가됨
        // dispatch('addUser', { user: newUser });
        // newUser 계정 정보가 추가됨
        dispatch('addUser', newUser);

        router.push("/");   // home으로        
      } catch (error) {
        console.log(error);
        commit('setError', error.message);
      }
    },
    async addUidToUser({ state }, newUid) {      
      //console.log('user.id:', state.user.id);
      if (state.user) {
        try {
          await db.collection('users').doc(state.user.id).update({
            uids: firebase.firestore.FieldValue.arrayUnion(newUid)
          });
          // Update the local state if neededa
          state.user.uids = [...(state.user.uids || []), newUid];
        } catch (error) {
          console.error('Error adding UID to user:', error);
        }
      }
    },
    async addGoogleUid({ commit, dispatch }) {
      try {
        const { user } = await auth.signInWithPopup(googleProvider);
        try {
          //console.log("1", user.id);
          dispatch('addUidToUser', user.uid);
        } catch (error) {
          commit('setError','Error adding google uid');
        }
      } catch (error) {
        commit('setError', error.message);
      }
    },
    async googleLogin({ commit, getters }) {
      try {
        // 구글 계정에 로그인
        const { user } = await auth.signInWithPopup(googleProvider);
        try {
          // 구글계정의 uid로 웹앱 계정의 정보를 가져옴.
          // 웹앱 계정은 사이트에 접속할 때 전체 회원 정보를 로드하였으므로 
          // 이미 로드된 회원 리스트에서 구글 계정 uid를 가진 myUser를 가져온다.
          const myUser = getters.getUserByUid(user.uid);
          if (myUser) {
            commit('setUser', myUser);
            router.push("/");   // home으로
          } else {
            console.log('등록된 회원이 아닙니다.');
            // 이경우 회원 가입 페이지로 이동 필요
          }
        } catch (error) {
          console.error('Error adding user:', error);
        }
      } 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,
    getUserByUid: (state) => (uid) => {
      return state.users.find(user => user.uids && user.uids.includes(uid));
    }
  }
});



'PWA' 카테고리의 다른 글

사용자 인증 - 소스코드  (0) 2024.08.10
사용자 인증 - 회원 접근 페이지  (0) 2024.08.09
사용자 인증 - Google 계정 연결  (0) 2024.08.07
사용자 인증 - 자동 로그인  (0) 2024.08.06
사용자 인증 - 로그인  (0) 2024.08.05