![[Frotend] Firebase 공부](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FmFAzv%2FbtsMKx5bULW%2FAAAAAAAAAAAAAAAAAAAAABeqHynhtpci6Irff6N90m3Lw1T7eR4X2pEPWGdbyYsc%2Fimg.jpg%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1756652399%26allow_ip%3D%26allow_referer%3D%26signature%3DMZiuidt6KvS8OHb10b6bTMv0xco%253D)
Firebase 공부
Firebase란?
- Firebase: 실시간 데이터베이스, 인증, 스토리지, 분석 등 다양한 기능을 제공하는 모바일 및 웹앱 개발 플랫폼
- 2011년 스타트업에서 시작 (실시간 채팅 기능) >> 2014년 구글이 인수 (백엔드 서버리스)
- 백엔드 서버 구축하고 관리 X. Google Cloud Platform을 이용해 빠르고 효율적인 개발
- 특히 실시간 기능 서비스, 클라이언트 사이드 집중, 초기 프로토타입 개발에 유용
Firebase 주요 기능
1. Authentication: 간편한 다중 플랫폼 로그인
- 이메일 인증, 소셜 미디어 계정 인증, 전화번호 인증방식 제공
- 보안 강화, 사용자 인증 과정 안정하게 처리
2. Firestore: NoSQL 데이터베이스
- Firebase에서 제공하는 NoSQL 형식의 클라우드 데이터베이스
- 실시간 데이터 동기화 지원 (ex. 실시간 채팅)
3. Storage: 사진 및 동영상 저장
- 사용자 파일 저장 및 공유, 강력한 보안
4. Hosting: 웹앱 호스팅
- 정적 및 동적 콘텐츠 모두 호스팅 가능, 웹 앱 간단 배포
Firebase 장•단점
1. 장점
- 백엔드 서버 없이 개발: 개발 시간 절약, 클라이언트에 집중해서 개발 가능
- 실시간 데이터베이스: 사용자 데이터 실시간 공유, 실시간 채팅 등의 기능 쉽게 개발
- Google 플랫폼 통합: Google Cloud Platform 서비스 쉽게 이용 및 분석 가능
2. 단점
- 쿼리 제한: NoSQL 데이터 베이스의 간단한 쿼리만 사용 가능
- 비용: 확장성이 중요한 경우 비용이 빠르게 증가할 수 있음
- 마이그레이션 어려움: 타 백엔드 서비스로 전환하는 경우 추가적인 작업 필요
Firebase 설정 방법
1. Firebase 공식 사이트 이동
https://firebase.google.com/?hl=ko
Firebase | Google's Mobile and Web App Development Platform
개발자가 사용자가 좋아할 만한 앱과 게임을 빌드하도록 지원하는 Google의 모바일 및 웹 앱 개발 플랫폼인 Firebase에 대해 알아보세요.
firebase.google.com
2. 프로젝트 생성
3. Firebase 앱 설정
- 생선된 Firebase 프로젝트 페이지에서, "웹"을 선택하고 앱의 별칭을 입력
- Firebase SDK를 추가하는 과정에서, FIrebase가 제공하는 구성 객체를 복사
3. React 프로젝트에 Firebase 설치
yarn add firebase
4. React 앱에서 Firebase 초기화
- SDK 복사 붙여넣기
- API key는 env로 이동
// ex) firebaseApp.ts
// firebaseApp.ts
import { initializeApp } from "firebase/app";
const {
REACT_APP_API_KEY,
REACT_APP_AUTH_DOMAIN,
REACT_APP_PROJECT_ID,
REACT_APP_STORAGE_BUCKET,
REACT_APP_MESSAGING_SENDER_ID,
REACT_APP_APP_ID,
} = process.env;
const firebaseConfig = {
apiKey: REACT_APP_API_KEY,
authDomain: REACT_APP_AUTH_DOMAIN,
projectId: REACT_APP_PROJECT_ID,
storageBucket: REACT_APP_STORAGE_BUCKET,
messagingSenderId: REACT_APP_MESSAGING_SENDER_ID,
appId: REACT_APP_APP_ID,
};
const firebase = initializeApp(firebaseConfig);
export default firebase;
5. React 앱에서 Firebase 사용
import 'firebase/auth';
import 'firebase/firestore';
const auth = firebase.auth();
const db = firebase.firestore();
Firebase 초기 세팅 - 끝 -
Firebase Auth란?
- Firebase Authenticaiton: 쉽게 사용자 인증을 구현할 수 있도록 돕는 Firebase 서비스
기능
- 이메일과 비밀번호 인증, 소셜 미디어 인증, 전화번호 인증
- 인증 정보 안전하게 저장
- 인정 정보 변경시 실시간으로 앱에 업데이트
- 인증 이메일 전송, 비밀번호 재설정 이메일 전송 등의 기능
장점
1. 편의성
- 복잡한 인증 과정을 Firebase가 대신 처리
- 클라이언트 사이드 개발에만 집중
2. 소셜 미디어 계정 인증
- OAuth 2.0과 OpenID Connect 지원
- 각종 소셜 미디어 계정 이용한 인증 쉽게 구현
3. 보안
- 사용자의 비밀번호 안전하게 암호화
- HTTPS 이용해 데이터 전송 보안
Firebase Auth는 언제 사용하는게 좋을까?
- 로그인 시스템
- 사용자 프로필 시스템
Firebase Auth 세팅 방법
1. Firebase 프로젝트 생성 & Firebase SDK 앱 추가 (앞서 설명)
2. Firebase 초기화 (앞서 설명)
3. Authentication 서비스 불러오기
- Authentication 탭 클릭 -> 시작하기
로그인 방법 탭에서
기본적인 이메일/비밀번호 클릭 -> 저장
회원가입 성공한 사용자들의 정보는 사용자탭에 저장된다.
템플릿 탭에서는
이메일을 보낸다고하면 이메일 템플릿을 변경할 수도 있고, 비밀번호 재설정, 이메일 주소 변경등 여러가지 설정 가능함
❗️ 개발자 문서
https://firebase.google.com/docs/auth/web/start?hl=ko
웹사이트에서 Firebase 인증 시작하기 | Firebase Authentication
4월 9~11일, Cloud Next에서 Firebase가 돌아옵니다. 지금 등록하기 의견 보내기 웹사이트에서 Firebase 인증 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
firebase.google.com
실제로 세팅 해보자
- 기존 코드
// firebaseApp.ts
import { initializeApp } from "firebase/app";
const {
REACT_APP_API_KEY,
REACT_APP_AUTH_DOMAIN,
REACT_APP_PROJECT_ID,
REACT_APP_STORAGE_BUCKET,
REACT_APP_MESSAGING_SENDER_ID,
REACT_APP_APP_ID,
} = process.env;
const firebaseConfig = {
apiKey: REACT_APP_API_KEY,
authDomain: REACT_APP_AUTH_DOMAIN,
projectId: REACT_APP_PROJECT_ID,
storageBucket: REACT_APP_STORAGE_BUCKET,
messagingSenderId: REACT_APP_MESSAGING_SENDER_ID,
appId: REACT_APP_APP_ID,
};
const firebase = initializeApp(firebaseConfig);
export default firebase;
import할때마다 초기화해주는 방식은 비효율적이기 때문에
- app을 지역변수로 선언해주고 try catch문으로 할당해주는 방식으로 진행
import { FirebaseApp, getApp, initializeApp } from "firebase/app";
import "firebase/auth";
let app: FirebaseApp;
/ ... /
try {
app = getApp("app");
} catch (error) {
app = initializeApp(firebaseConfig, "app");
}
export default app;
getAuth
- firebase 사용자가 현재 로그인되었는지 확인
getAuth를 콘솔에 찍어보면 currentUser가 있는데 null이면 로그인 안한거임
onAuthStateChanged
- Firebase Authentication 서비스에서 제공하는 메서드
- 인증 상태가 변경될 때마다 호출되는 리스너 설정 (로그인, 로그아웃) => 사용자가 로그인 or 로그아웃 할 때 마다 실시간으로 호출 됨 (로그인 상태일 때는 사용자 정보를, 아니라면 null 리턴함)
// 코드 예시 - 로그인 상태에 따른 조건처리
export default function App() {
const auth = getAuth(app);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(
!!auth?.currentUser
);
const [init, setInit] = useState<boolean>(false);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
user ? setIsAuthenticated(true) : setIsAuthenticated(false);
setInit(true);
});
}, [auth]);
return (
{init ? <Router isAuthenticated={isAuthenticated} /> : <Loader />}
);
}
createUserWithEmailAndPassword
신규 사용자를 생성할 때는 createUserWithEmailAndPassword 메서드 호출
// 예시 코드
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const auth = getAuth(app);
await createUserWithEmailAndPassword(auth, email, password);
toast.success("회원가입에 성공했습니다!");
navigate("/");
} catch (error: any) {
console.log(error);
toast.error(error?.code);
}
};
signInWithEmailAndPassword
반대로 로그인할때는 signInWithEmailAndPassword 메서드 호출
// 예시 코드
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const auth = getAuth(app);
await signInWithEmailAndPassword(auth, email, password);
toast.success("로그인에 성공했습니다.");
navigate("/");
} catch (error: any) {
toast.error(error?.code);
console.log(error);
}
};
signOut
- signOut 메서드 가지고 오면 간단하게 작성가능
// 예시 코드
const onSignOut = async () => {
try {
const auth = getAuth(app);
await signOut(auth);
toast.success("로그아웃 되었습니다.");
} catch (error: any) {
console.log(error);
toast.error(error?.code);
}
};
<div onClick={onSignOut}>
로그아웃
</div>
Firestore란?
Firestore: Firebase에서 제공하는 NoSQL 형식의 클라우드 데이터베이스
- 애플리케이션 개발을 하다보면 데이터를 저장하고 불러오는 일이 매우 중요한데, Cloud Firestore는 이러한 일을 쉽게 도와줌
- Firestore는 실시간 데이터 동기화를 지원하며, 웹, 안드로이드, iOS에서 데이터를 저장하고 동기화할 수 있음
- 데이터는 문서(document)와 컬렉션(collection)의 형태로 저장되고, 효율적인 쿼리 작성하게 함
- 오프라인 지원 제공
Firestore 장점
1. 실시간 데이터 동기화
- 실시간 채팅 및 데이터 분석 등 실시간 기능 애플리케이션 개발
2. 구조화된 데이터
- 문서 / 컬렉션 형태로 데이터 저장 / 구조화된 데이터 쉽게 저장하고 불러올 수 있음
3. 보안
- 사용자 기반의 보안규칙 설정 가능
Firestore 사용 예시
1. 실시간 채팅 앱
2. 다양한 데이터 저장 및 불러올 수 있음 - ex) 게임 점수, 사용자 설정, 텍스트, 이미지
3. 사용자별 데이터 접근 권한 쿼리 - ex) 사용자 인증 정보와 함께 사용됨
Firestore 사용 방법
1. Firebase 프로젝트 생성 & Firebase SDK 앱 추가 (앞서 설명)
2. Firebase 인스턴스 가져오기
3. Firestore 세팅하기
- Cloud Firestore -> 데이터베이스 만들기 클릭
- 위치는 서울
- 프로덕션 누르면 데이터가 비공개라 사용할 수 없기 때문에 나중에 배포할때 변경
- 만들기
4. firebaseApp.ts 세팅
- getFirestore
import { FirebaseApp, getApp, initializeApp } from "firebase/app";
import "firebase/auth";
import { getFirestore } from "firebase/firestore";
const {
REACT_APP_API_KEY,
REACT_APP_AUTH_DOMAIN,
REACT_APP_PROJECT_ID,
REACT_APP_STORAGE_BUCKET,
REACT_APP_MESSAGING_SENDER_ID,
REACT_APP_APP_ID,
} = process.env;
const firebaseConfig = {
apiKey: REACT_APP_API_KEY,
authDomain: REACT_APP_AUTH_DOMAIN,
projectId: REACT_APP_PROJECT_ID,
storageBucket: REACT_APP_STORAGE_BUCKET,
messagingSenderId: REACT_APP_MESSAGING_SENDER_ID,
appId: REACT_APP_APP_ID,
};
let app: FirebaseApp;
try {
app = getApp("app");
} catch (error) {
app = initializeApp(firebaseConfig, "app");
}
export const db = getFirestore(app);
export default app;
setDoc()
- 단일 문서 생성 or 덮어쓰기
// 코드 예시
import { doc, setDoc } from "firebase/firestore";
// Add a new document in collection "cities"
await setDoc(doc(db, "cities", "LA"), {
name: "Los Angeles",
state: "CA",
country: "USA"
});
addDoc()
- 문서마다 id 값을 따로 넣지 않으려면 (자동 id 생성)
공식문서 내용
문서에 유의미한 ID가 없는 경우 Cloud Firestore에서 ID를 자동으로 생성할 수 있습니다.
다음과 같은 언어별 add() 메서드를 호출할 수 있습니다.
// 코드 예시
import { collection, addDoc } from "firebase/firestore";
await addDoc(collection(db, "posts"), {
title,
summary,
content,
createdAt: new Date()?.toLocaleDateString("ko", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
email: user?.email,
uid: user?.uid,
category,
});
toast?.success("게시글을 생성했습니다.");
navigate("/");
getDocs()
- 컬렉션의 모든 문서 가져오기
ex) 게시글 리스트
// 코드 예시
const getPosts = async () => {
const datas = await getDocs(collection(db, "posts"));
datas.forEach((doc) => {
const dataObj = { ...doc.data(), id: doc.id };
setPosts((prev) => [...prev, dataObj])
})
}
getDoc()
- 문서 가져오기
ex) 단일 데이터 가져오기
// 코드 예시
const getPost = async (id: string) => {
if (id) {
const docRef = doc(db, "posts", id);
const docSnap = await getDoc(docRef);
setPost({ id: docSnap.id, ...(docSnap.data() as PostProps) });
}
};
// 공식 문서 코드 예시
import { doc, getDoc } from "firebase/firestore";
const docRef = doc(db, "cities", "SF");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
} else {
// docSnap.data() will be undefined in this case
console.log("No such document!");
}
updateDoc()
- 문서 업데이트
ex) 게시글 수정
// 코드 예시
const postRef = doc(db, "posts", post.id);
await updateDoc(postRef, {
title,
summary,
content,
updatedAt: new Date()?.toLocaleDateString("ko", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}), // firebase는 no sql 이므로 동적으로 데이터 추가해도 상관없음
category,
});
toast?.success("게시글을 수정했습니다.");
navigate(`/posts/${post.id}`);
deleteDoc()
- 문서 삭제
ex) 게시글 삭제
// 코드 예시
const handleDelete = async () => {
const confirm = window.confirm("해당 게시글을 삭제하시겠습니까?");
if (confirm && post && post.id) {
await deleteDoc(doc(db, "posts", post.id));
toast.success("게시글을 삭제하였습니다.");
navigate("/");
}
};
❗️ Firestore에서 쿼리를 사용하려면 색인을 꼭 만들어줘야함
orderBy()
- 쿼리 정렬
// 코드 예시 (query, where, orderBy 사용해서 탭 별로 필터링해 불러오기)
const getPosts = async () => {
setPosts([]);
let postsRef = collection(db, "posts");
let postsQuery = query(postsRef, orderBy("orderBy","asc"))
const datas = await getDocs(postsQuery);
datas?.forEach((doc) => {
const dataObj = { ...doc.data(), id: doc.id };
setPosts((prev) => [...prev, dataObj as PostProps]);
});
};
const getPosts = async () => {
setPosts([]);
let postsRef = collection(db, "posts");
let postsQuery;
if (activeTab === "my" && user) {
// 나의 글만 필터링
postsQuery = query(
postsRef,
where("uid", "==", user.uid),
orderBy("createdAt", "asc")
);
} else if (activeTab === "all") {
// 모든 글 보여주기
postsQuery = query(postsRef, orderBy("createdAt", "asc"));
} else {
// 카테고리 글 보여주기
postsQuery = query(
postsRef,
where("category", "==", activeTab),
orderBy("createdAt", "asc")
);
}
const datas = await getDocs(postsQuery);
datas?.forEach((doc) => {
const dataObj = { ...doc.data(), id: doc.id };
setPosts((prev) => [...prev, dataObj as PostProps]);
});
};
arrayUnion()
- 배열 요소 업데이트
// 코드 예시 (posts 컬렉션 내부 필드에 배열 형태로 넣어주기 위함)
const commmentObj = {
content: comment,
uid: user.uid,
email: user.email,
createdAt: new Date().toLocaleDateString("ko", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
};
await updateDoc(postRef, {
comments: arrayUnion(commmentObj),
updatedAt: new Date().toLocaleDateString("ko", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
});
arrayRemove()
- 배열 요소 삭제
// 코드 예시 (댓글 삭제 기능 구현)
const handleDeleteComment = async (data: CommentsInterface) => {
const confirm = window.confirm("해당 댓글을 삭제하시겠습니까?");
if (confirm && post.id) {
const postRef = doc(db, "posts", post.id);
await updateDoc(postRef, {
comments: arrayRemove(data), // 지우려고 하는 필드에 arrayRemove() 사용하면 됨
});
toast.success("댓글을 삭제했습니다.");
// 문서 업데이트
await getPost(post.id);
}
};
Firebase 보안 작업
1. Firebase Authorization 승인된 도메인 설정
- 프로젝트를 연결하고자 한다면 승인된 도메인에 추가해줘야함
2. Firestore의 기본 보안규칙(rules) 변경
- 아래 문서 보면서 수정
https://firebase.google.com/docs/rules/get-started?hl=ko&authuser=0
Firebase 보안 규칙 시작하기 | Firebase Security Rules
4월 9~11일, Cloud Next에서 Firebase가 돌아옵니다. 지금 등록하기 의견 보내기 Firebase 보안 규칙 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Firebase
firebase.google.com
// 예시 - 로그인 사용자만 데이터 접근 허용
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null
}
}
}
3. API key 보안 작업
- 클라우드 구글 콘솔 이동
https://console.cloud.google.com/apis/credentials
Google 클라우드 플랫폼
로그인 Google 클라우드 플랫폼으로 이동
accounts.google.com
1) 블로그 프로젝트 생성, 선택
2) 사용자 인증 정보 탭 -> 주의가 나와있는 Browser key 클릭
- 애플리케이션 제한사항 설정 (웹 사이트 클릭, 승인된 URL 추가 - localhost주소, firebase 도메인(authentication 승인된 도메인 부분에 나와있음),배포한 도메인 주소)
- 저장 (이제 해당 도메인에서만 API 키를 제한할 수 있음)
Firebase CLI란?
Firebase CLI (Command Line Interface)
- Firebase 프로젝트를 관리하고 다양한 Firebase 기능을 로컬에서 사용할 수 있게 해줌
- Firebase 프로젝트 설정, 데이터베이스, Cloud Function, 호스팅 등 관리
https://firebase.google.com/docs/cli?hl=ko
Firebase CLI 참조 | Firebase 문서
firebase.google.com
Firebase CLI 설치 방법
1. node.js, npm은 이미 설치했으니까 pass
2. npm install -g firebase-tools
3. firebase login -> Y -> 로그인 화면 나오면 로그인
4. firebase projects:list - 로그인된 계정의 firebase 프로젝트를 모두 리스트업 할 수 있음
이제 이 CLI를 통해 배포를 하거나 호스팅과 같은 여러 설정들을 작업할 수 있음
배포하기
1. 프로젝트 초기화
- firebase init hosting
- Command line에 아래와 같이 입력
1) Use an existing project
2) 프로젝트 이름
3) What do you want to use as your public directory? -> build 입력
4) Configure as a single-page app (rewrite all urls to /index.html) -> yes
5) Set up automatic builds and deploys with GitHub -> No
2. 사이트 배포
- yarn build (빌드 후 배포)
- firebase deploy --only hosting
- 배포된 url 확인 (ex) https://XXX-XXX-XXX.web.app)
3. Google console 및 Firebase 보안 적용
- Firebase Auth > setting > 승인된 도메인 추가
- Google Console > API > 보안 URL 추가
프론트엔드 공부일지 입니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!