주말간의 삽질
- 파이어베이스 리얼타임 DB 를 이용하려고 함 (웹)
- 테스트 모드로 하기 싫었고 인증 규칙을 사용하려 했는데 죄다 write&read 권한을 풀어놓은 자료들만 있음
- 공식문서가 너무 파편화되어 유저 가입 -> 인증 -> 작성 플로우를 따라가기가 힘들어 헤맴
결론적으로 공식문서를 똑바로 안읽었었다 ㄱ- 미안아 구글해
그래도 상황에 적은 것처럼 파이어베이스 서비스 이용에 있어 인증부터 사용까지 전체적인 플로우 가이드가 많이 없다.
그래서 써봉다
Vue 기반으로 진행했는데 리액트로 해도 동일하다.
진행하려는 절차는 아래와 같다.
- 유저 등록
- 유저 로그인
- DB 접근 요청시 Validation 후 요청 처리
파이어베이스는 다양한 유저 인증 방법을 제공한다. 나는 검증 메일을 선택했고, 다른 방법을 택하더라도 흐름은 동일하다.
절차는 아래와 같다.
입력한 유저 이메일로 인증 메일 전송
-> 메일 내 링크로 이동 (서비스 내 로그인 처리 라우트)
-> *이동하며 받아온 인증 토큰을 담아서 sign in 요청 전송
-> 인증 완료 후 서비스 메인으로 redirect
** 당연히 firebase app
설정 및 실행은 서비스 내에서 완료된 상태여야 한다.
firebase.js
import {
getAuth,
sendSignInLinkToEmail,
isSignInWithEmailLink,
signInWithEmailLink,
} from "firebase/auth";
const auth = getAuth();
const actionCodeSettings = {
url: process.env.VUE_APP_SIGN_IN_ROUTE_DEV,
// 메일 내 링크로 접속했을때 이동할 URL 을 설정한다.
// 로그인 요청을 위한 별도의 라우트를 만들어준다. (${BASE_URL}/login/validate 이런식으로)
// 해당 페이지에서 인증이 끝나면 main 으로 redirect 한다.
handleCodeInApp: true,
};
// 인증 메일 발송.
// localStorage 에 email 을 저장해서 메일 링크로 접속 시 메일을 요청한 user 가 맞는지 이중 검증한다.
export const sendSignInLink = (email) => {
sendSignInLinkToEmail(auth, email, actionCodeSettings)
.then(() => {
localStorage.setItem("signInEMail", email);
})
.catch((error) => {
console.log(error);
});
};
// 메일을 통해 인증 라우트로 들어왔으면, 인증 요청을 보낸다.
// url 쿼리에 인증 토큰이 담겨있어 현재 주소를 인자로 보낸다.
export const signInFirebase = async () => {
const email = localStorage.getItem("signInEMail");
if (!email) return false;
localStorage.clear();
if (isSignInWithEmailLink(auth, window.location.href)) {
const response = await signInWithEmailLink(
auth,
email,
window.location.href
);
return response;
}
};
SignIn.vue
<template>
<div>Check Login ...</div>
</template>
<script>
import { signInFirebase } from "@/firebase";
export default {
// mount 시 로그인 요청을 보내고, 응답이 오면 userId, uid 를 localStorage 에 저장한다.
// 새로고침시 Vuex 가 초기화되어 서비스 내 로그인 상태가 해제되는걸 막아준다.
// Vuex 의 로그인 상태로 true 로 처리해준다.
mounted() {
signInFirebase().then((response) => {
const userId = response.user.auth.currentUser.email;
const uid = response.user.uid;
localStorage.setItem("userId", userId);
localStorage.setItem("uid", uid);
this.toastMessage("Success to Sign In :)", "success");
this.$store.dispatch("signIn", { userId, uid });
this.$router.push("/");
});
},
inject: ["toastMessage"],
};
</script>
App.vue
...
// 새로고침시 localStorage 에 저장된 정보가 있다면 Vuex 로그인 상태를 업데이트한다.
mounted() {
if (localStorage.getItem("userId")) {
const userId = localStorage.getItem("userId");
const uid = localStorage.getItem("uid");
this.$store.dispatch("signIn", { userId, uid });
}
여기까지 오면 firebase app 내 auth 정보가 들어간다.
**SDK 이용해 처리하면 app 내에서 sign-in 상태기 때문에 알아서 인증을 처리해주는데
Realtime DB 규칙 플레이그라운드 예제 보면서 Axios 로 헤더 설정해 날리려고 하니까 세부 설정을 다 맞추지 못해서 주말내내 사방팔방을 들쑤시고 다녔다.
SDK 를 이용하자
임시로 설정한 규칙. 로그인 후 SDK 이용한 요청은 auth 객체를 이용할 수 있으니 필요한 대로 설계해 사용하면 된다.
realtimeDB.js
import { getDatabase, ref, set } from "firebase/database";
export const database = getDatabase(app);
export const writeDB = (DBLocation, obj) => {
/*
* database: firebase database 앱
* DBLocation: 저장할 NoSQL 경로 쿼리 (문자열)
* obj: 저장할 key - value
*/
set(ref(database, DBLocation), obj);
};
로그인까지 다 해놓고 저거 이용 못해서 주말 날린게 화낙만두