113. Exporting Services
npm create vue@latest
여기서는 Firebase 구성을 리팩토링하고 서비스를 내보내는 방법을 다룰 것입니다.
이미 Firebase의 인증 서비스를 사용하고 있지만, 이 서비스는 사용자의 이메일과 비밀번호 외에 추가 정보를 저장하지 않습니다.
사용자의 나이, 국가, 이름과 같은 정보를 저장하려면 Firebase의 다른 서비스인 Firestore를 사용해야 합니다.
Firestore는 Firebase의 공식 데이터베이스 서비스입니다.
Firebase SDK는 Firestore API와 상호작용하기 위한 모듈을 포함하고 있습니다.
데이터베이스와 상호작용하는 함수들은 패키지를 가져오는 것으로 활성화할 수 있습니다.
Firebase 파일을 열어 인증 패키지뿐만 아니라 Firestore 패키지도 가져와야 합니다.
중요한 것은 Firestore 패키지를 가져와야 하며, 구버전 데이터베이스 서비스인 실시간 데이터베이스용 데이터베이스 패키지를 가져오면 안됩니다.
Firebase 객체는 패키지를 변수에 할당하지 않고도 확장됩니다.
코드를 리팩토링하기 위해, 등록 양식 컴포넌트로 전환하고, 등록 함수에서 Firebase의 인증 서비스에 접근하기 위해 firebase.auth()
함수를 반복적으로 호출하는 대신, 서비스에 대한 참조를 생성합니다.
Firestore에 대해서도 마찬가지입니다.
Firebase 파일로 돌아가서 인증 및 Firestore 서비스에 대해 참조를 생성하고 내보냅니다.
이렇게 하면 어떤 컴포넌트도 서비스에 접근하기 위해 참조를 직접 생성할 필요가 없습니다.
마지막으로, 기본 객체 대신 명명된 내보내기를 사용하고, 등록 양식 컴포넌트의 가져오기 문을 업데이트하여 리팩토링을 완료합니다.
이렇게 하면 코드가 더 읽기 쉬워집니다.
다음엔 사용자 정보를 저장하는 방법을 계속 다룰 예정입니다.
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore'
const firebaseConfig = {
apiKey: 'AIzaSyA4X8qu0cS5CeKS9sExbwWgTP4mW9crP84',
authDomain: 'vue-guide-2.firebaseapp.com',
projectId: 'vue-guide-2',
storageBucket: 'vue-guide-2.appspot.com',
// messagingSenderId: '475228612189',
appId: '1:475228612189:web:ff548967df307e9a110fb4'
}
initializeApp(firebaseConfig)
const auth = getAuth()
const db = getFirestore()
export { auth, db }
<script setup lang="ts">
import { ref } from 'vue'
import { createUserWithEmailAndPassword } from 'firebase/auth'
import { auth } from '@/includes/firebase'
const schema = ref({
name: 'required|min:3|max:100|alpha_spaces',
email: 'required|min:3|max:100|email',
age: 'required|min_value:18|max_value:100',
password: 'required|min:9|max:100|excluded:password', // password 단어를 입력하면 유효성 검사를 통과할 수 없다.
confirm_password: 'passwords_mismatch:@password', // 비밀번호 입력할 때, 비밀번호 재확인차 입력하는 필드 // 위의 password 부분과 일치하는지 확인함
country: 'required|country_excluded:Antarctica',
tos: 'required'
})
const userData = ref({
country: 'USA'
})
const reg_in_submission = ref(false)
const reg_show_alert = ref(false)
const reg_alert_variant = ref('bg-blue-500')
const reg_alert_msg = ref('Please wait! Your acount is being created.')
const register = async (values: {
age: number
confirm_password: string
country: string
email: string
name: string
password: string
tos: number
}) => {
// VeeForm 안에 VeeField의 모든 유효성 검사를 통과해야지 values 값이 들어온다.
// ex.
// {
// age: 31
// confirm_password: "asdf"
// country: "Germany"
// email: "sdf@sdf.com"
// name: "sfdf"
// password: "asdf"
// tos: "1"
// }
reg_show_alert.value = true
reg_in_submission.value = true
reg_alert_variant.value = 'bg-blue-500'
reg_alert_msg.value = 'Please wait! Your account is being created.'
let userCred
try {
userCred = await createUserWithEmailAndPassword(auth, values.email, values.password)
} catch (error) {
reg_in_submission.value = false
reg_alert_variant.value = 'bg-red-500'
reg_alert_msg.value = 'An unexpected error occured. Please try again later.'
return
}
reg_alert_variant.value = 'bg-green-500'
reg_alert_msg.value = 'Success! Your account has been created.'
console.log(userCred)
}
</script>
<template>
<!-- Registration Form -->
<div
class="text-white text-center font-bold p-4 rounded mb-4"
v-if="reg_show_alert"
:class="reg_alert_variant"
>
{{ reg_alert_msg }}
</div>
<VeeForm :validation-schema="schema" @submit="register" :initial-values="userData">
<!-- Name -->
<div class="mb-3">
<label class="inline-block mb-2">Name</label>
<VeeField
type="text"
name="name"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
placeholder="Enter Name"
/>
<ErrorMessage class="text-red-600" name="name" />
</div>
<!-- Email -->
<div class="mb-3">
<label class="inline-block mb-2">Email</label>
<VeeField
type="email"
name="email"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
placeholder="Enter Email"
/>
<ErrorMessage class="text-red-600" name="email" />
</div>
<!-- Age -->
<div class="mb-3">
<label class="inline-block mb-2">Age</label>
<VeeField
type="number"
name="age"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
/>
<ErrorMessage class="text-red-600" name="age" />
</div>
<!-- Password -->
<div class="mb-3">
<label class="inline-block mb-2">Password</label>
<VeeField name="password" :bails="false" #default="{ field, errors }">
<input
type="password"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
placeholder="password"
v-bind="field"
/>
<div class="text-red-600" v-for="error in errors" :key="error">
{{ error }}
</div>
</VeeField>
</div>
<!-- Confirm Password -->
<div class="mb-3">
<label class="inline-block mb-2">Confirm Password</label>
<VeeField
type="password"
name="confirm_password"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
placeholder="Confirm Password"
/>
<ErrorMessage class="text-red-600" name="confirm_password" />
</div>
<!-- Country -->
<div class="mb-3">
<label class="inline-block mb-2">Country</label>
<VeeField
as="select"
name="country"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
>
<option value="USA">USA</option>
<option value="Mexico">Mexico</option>
<option value="Germany">Germany</option>
<option value="Antarctica">Antarctica</option>
</VeeField>
<ErrorMessage class="text-red-600" name="country" />
</div>
<!-- TOS -->
<div class="mb-3 pl-6">
<VeeField
type="checkbox"
name="tos"
value="1"
class="w-4 h-4 float-left -ml-6 mt-1 rounded"
/>
<label class="inline-block">Accept terms of service</label>
<ErrorMessage class="text-red-600 block" name="tos" />
</div>
<button
type="submit"
class="block w-full bg-purple-600 text-white py-1.5 px-3 rounded transition hover:bg-purple-700"
:disabled="reg_in_submission"
>
Submit
</button>
</VeeForm>
</template>
<style scoped></style>