๐ŸŽพ vue-tennis | SSR Migration(Nuxt + Firebase) | 2. Firebase Usage

SSR Migration(Nuxt + Firebase) Series
1. Set Environment
2. Firebase Usage ๐Ÿ‘ˆ๐Ÿป



๐Ÿ”ฅ firestore usage


REF : https://firebase.nuxtjs.org/guide/usage

  • pages > index.vue ๋‚ด์šฉ ์ถ”๊ฐ€
<script>
export default {
  async mounted() {
    console.log('mounted')
    const db = await this.$fire.firestore
    // const users = this.$fire.firestore.collection('users').doc(uid).get()
    console.log('here', db)
  },
}
</script>
  • console

์ฃผ์˜ ์‚ฌํ•ญ
1. this.$firestore (x) โ‡’ this.$fire.firestore (o)
*๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฆ„(ํ•„์ž์˜ ํ™˜๊ฒฝ => "@nuxtjs/firebase": "^7.6.1")
2. nuxt.config.js > firebase > services โ‡’ firestore: true ํ™•์ธ



๐Ÿ‘จ๐Ÿปโ€๐Ÿš’ functions usage

REF : ๋กœ์ปฌ์—์„œ ํ•จ์ˆ˜ ์‹คํ–‰
https://firebase.google.com/docs/functions/local-emulator
REF : ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์ ํŠธ์— Firebase ์ถ”๊ฐ€
https://firebase.google.com/docs/web/setup
REF : Functions
https://firebase.google.com/docs/functions/manage-functions?hl=ko

1. ์„ ํ–‰

$ npm install -g firebase-tools : firebase-tools ์„ค์น˜
$ firebase login : firebase์— ๋กœ๊ทธ์ธ

2. firebase ์ดˆ๊ธฐํ™”

$ firebase init : functions๋งŒ ์„ ํƒํ•œ ํ›„ ์„ค์น˜
(ํ”„๋กœ์ ํŠธ ๋‚ด์— functions ํด๋”๊ฐ€ ์ƒ์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ)

3. nuxt.config.js ๋‚ด์šฉ ์ˆ˜์ •

  firebase: {
    config: {
      ...
    },
    services: {
      ...
      functions: {
        location: 'asia-northeast3', // firebase project ์„ค์ •์— ๋”ฐ๋ฆ„
        // Cloud Functions ์œ„์น˜
        // https://firebase.google.com/docs/functions/locations
      },

4. firebase admin SDK ์„ค์ •

local์—์„œ myFirebaseProject๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋จ
๊ทธ๋งŒํผ ๋ฆฌ์Šคํฌ๊ฐ€ ํฌ๊ธฐ ๋•Œ๋ฌธ์— key ๊ด€๋ฆฌ์— ์‹ ๊ฒฝ์จ์•ผ ํ•จ

1. firebase > myProject > ํ”„๋กœ์ ํŠธ ์„ค์ • > ์„œ๋น„์Šค ๊ณ„์ • > firebase admin SDK ๊ตฌ์„ฑ ์Šค๋‹ˆํŽซ ํ™•์ธ

2. ํ•˜๋‹จ์˜ ์ƒˆ ๋น„๊ณต๊ฐœ ํ‚ค ์ƒ์„ฑ์„ ํ†ตํ•ด์„œ ํ‚ค ํŒŒ์ผ์„ ๋‹ค์šด๋ฐ›์€ ํ›„ myProject > functions ๊ฒฝ๋กœ๋กœ ์ด๋™

(key ํŒŒ์ผ๋ช…์„ ์•Œ๋งž๊ฒŒ ์ˆ˜์ •ํ•จ / ํ•„์ž์˜ ๊ฒฝ์šฐ vue-tennis-key.json)

3. firebase console ๋‚ด firebase admin SDK ๊ตฌ์„ฑ ์Šค๋‹ˆํŽซ์„ ๋ณต์‚ฌํ•˜์—ฌ

myProject > functions > index.js์— ๋ถ™์—ฌ๋„ฃ์Œ

const functions = require('firebase-functions')
var admin = require('firebase-admin')
var serviceAccount = require('./vue-tennis-key.json')

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'myDatabaseURL',
})

const db = admin.database()
const fdb = admin.firestore()

4. gitignore ๋“ฑ๋ก (์ค‘์š”โ—๏ธโ—๏ธ)

  • root > functions > .gitignore
    root > .gitignore๊ณผ ๊ตฌ๋ถ„๋จ์— ์ฃผ์˜ ๐Ÿšจ
node_modules
vue-tennis-key.json
.env

5. ์ƒˆ๋กœ์šด ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜(function) ์ž‘์„ฑ

: root > functions > index.js ๋‚ด์šฉ ์ˆ˜์ •

exports.createUser = functions.auth.user().onCreate(async (user) => {
  console.log('firebase funtions : createUser')
  const { uid, email, displayName, photoURL } = user
  const time = new Date()
  const userInfo = {
    email,
    displayName,
    photoURL,
    nickName: displayName,
    sex: '',
    birth: '',
    location: '',
  }
  await fdb.collection('users').doc(uid).set(userInfo) // set user at Firestore
  userInfo.createdAt = time.getTime()
  db.ref('users').child(uid).set(userInfo) // set user at RealTime Database
})

exports.deleteUser = functions.auth.user().onDelete(async (user) => {
  console.log('firebase funtions : deleteUser')
  const { uid } = user
  await db.ref('users').child(uid).remove()
  await fdb.collection('users').doc(uid).delete()
})

6. ํ•จ์ˆ˜ ๋ฐฐํฌ(deploy function)

: $ firebase deploy --only functions:createUser
: $ firebase deploy --only functions:deleteUser

7. ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ์ž‘๋™ ํ™•์ธ

: firebase > myProject > Functions > ๋กœ๊ทธ

  • ์œ„์—์„œ ์ž‘์„ฑํ•œ function์—์„œ console๋กœ ์ฐ์€ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ
  • ์—ฌ๊ธฐ์„œ ์˜ˆ์‹œ๋กœ ์ž‘์„ฑํ•œ createUser ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ,
    auth์—์„œ user๊ฐ€ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ํŠธ๋ฆฌ๊ฑฐ๋กœ ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—,
    ์•„๋ž˜ auth usage ํŒŒํŠธ์—์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•จ.
    ๋”ฐ๋ผ์„œ auth usage ํŒŒํŠธ๋ฅผ ์ž‘์„ฑํ•œ ํ›„์— 7. ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ์ž‘๋™ ํ™•์ธ ๋‚ด์šฉ์„ ํ™•์ธ ๋ฐ”๋žŒ



๐Ÿš’ auth usage

1. nuxt.config.js ๋‚ด์šฉ ์ˆ˜์ •

: ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ๊ฒฝ์šฐ, Auth State๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค onAuthStateChangedAction์ด ์‹คํ–‰๋จ.

  firebase: {
    config: {
      ...
    },
    services: {
      ...
      auth: {
        initialize: {
          onAuthStateChangedAction: 'onAuthStateChanged',
        },
        ssr: true,
        disableEmulatorWarnings: false,
      },
    }
  }

2. pages > mypage.vue ๋‚ด์šฉ ์ˆ˜์ •

<template>
  <v-container>
    <v-card>
      <v-card-text>
        <v-btn @click="login" :loading="isProcessing">login</v-btn>
        <v-btn @click="logout" :loading="isProcessing">logout</v-btn>
      </v-card-text>
    </v-card>
  </v-container>
</template>

<script>
export default {
  data() {
    return {
      isProcessing: false,
    }
  },
  methods: {
    async login() {
      if (this.isProcessing) return
      this.isProcessing = true
      const provider = new this.$fireModule.auth.GoogleAuthProvider()
      try {
        const snapshot = await this.$fire.auth.signInWithPopup(provider)
      } catch (err) {
        alert('๋กœ๊ทธ์ธ ์‹คํŒจ', err)
        console.log(err)
      } finally {
        this.isProcessing = false
      }
    },

    async logout() {
      if (this.isProcessing) return
      this.isProcessing = true
      try {
        await this.$fire.auth.signOut()
        console.log('๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต')
      } catch (err) {
        alert('๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ.', err)
        console.log(err)
      } finally {
        this.isProcessing = false
      }
    },
  },
}
</script>
  • http://localhost:3000/mypage

3. Vuex(store)

store > state.js

export default () => ({
  user: null,
  fireUser: null,
})

store > mutations.js

mutations์—์„œ state.user = payload์™€ ๊ฐ™์ด ์ง์ ‘ ํ• ๋‹น์„ ํ•˜๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ ๐Ÿšจ

import initialState from './state'

export default {
  RESET_STORE: (state) => {
    Object.assign(state, initialState())
  },

  SET_FIRE_USER: (state, fireUser) => {
    const { uid, email, displayName, photoURL } = fireUser
    state.fireUser = { uid, email, displayName, photoURL }
  },
  
  SET_USER: (state, user) => {
    if (user) {
      const {
        email,
        displayName,
        photoURL,
        nickName,
        sex,
        birth,
        location,
      } = user
      state.user = {
        email,
        displayName,
        photoURL,
        nickName,
        sex,
        birth,
        location,
      }
    } else {
      state.user = null
    }
  },
}

store > actions.js

export default {
  async onAuthStateChanged({ commit }, { authUser }) {
    let unsubscribe = null
    if (!authUser) {
      if (unsubscribe) unsubscribe()
      return
    }
    commit('SET_FIRE_USER', authUser)

    const subscribe = (authUser) => {
      const ref = this.$fire.firestore.collection('users').doc(authUser.uid)
      unsubscribe = ref.onSnapshot((doc) => {
        if (doc.exists) commit('SET_USER', doc.data())
      }, console.error)
    }
    subscribe(authUser)
  },
}


๐Ÿงฏ๐Ÿง‘๐Ÿปโ€๐Ÿš’๐Ÿ‘ฉ๐Ÿปโ€๐Ÿš’๐Ÿ•ฏ



REF : nuxt-firebase-demo

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ