firebase 사용해서 게시판 CRUD기능을 만들어보자.
firebase는 벡엔드 기능을 클라우드 서비스 형태로 제공하기 때문에 백엔드없이 어플리케이션을 만들 때 사용하면 유용하다.
firebase가 버전 업데이트를 하면서 문법 등에 많은 변화가 생겼다.
firebase 프로젝트 생성 후 Firebase를 초기화하여 사용하려는 제품의 SDK를 사용하기
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
appId: process.env.REACT_APP_APP_ID,
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
REACT_APP_API_KEY = abcdedf...
REACT_APP_AUTH_DOMAIN = abcdedf...
REACT_APP_PROJECT_ID = abcdedf...
REACT_APP_STORAGE_BUCKET = abcdedf...
REACT_APP_MESSAGIN_ID = abcdedf...
REACT_APP_APP_ID = abcdedf...
환경변수는 노출되면 보안상 위험하기때문에 env파일을 활용해야 한다.
addDoc
메소드를 사용하여 구현한다.
addDoc(' 키를 통해 가져온 DB ' , ' payload ')
import { db } from '../../lib/fbase';
import { addDoc, collection } from 'firebase/firestore';
const handleSubmit = useCallback(
async e => {
e.preventDefault();
try {
const res = await addDoc(collection(db, 'board'), boardContent);
console.log(res);
} catch (e) {
console.log(e, 'error');
}
},
[boardContent, viewContent],
);
read는 query, getDocs 메소드가 있다. query에는 여러 조건을 넣을 수 있는데 공식문서에서 참조가능하다.
import { getDocs, collection } from 'firebase/firestore';
import { db } from '../../lib/fbase';
//전체 데이터 배열 가져오기
<리스트 페이지>
useEffect(() => {
const fetchData = async () => {
const snapshot = await getDocs(collection(db, 'board'));
const listArr = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}));
setViewContents(listArr);
};
fetchData().catch(e => console.log(e));
}, []);
//특정 데이터만 가져오기 - firebase에서 생성된 id로 url id 만들어주고, params로 id get
<상세 페이지>
import { doc, getDoc } from 'firebase/firestore';
import { db } from '../../lib/fbase';
...
const { id } = useParams();
useEffect(() => {
(async function fetchData() {
const detailRef = doc(db, 'board', id);
const res = await getDoc(detailRef);
setData(res.data());
})();
}, []);
그대로 db에서 받아온 데이터를 바인딩하면 html태그가 그대로 적용되어 출력되는 현상이 발생한다. html이 적용된 데이터를 html로 변환해서 사용해야하는데 이때 dangerouslySetInnerHTML
를 사용한다.
리액트에서는 보안적인 문제로 html형태로 글을 출력하는 기능을 제공하지 않기 때문에 dangerouslySetInnerHTML를 사용해서 대신 요청하여 태그를 적용시킨다.
//사용법
<main dangerouslySetInnerHTML={{ __html: data.content }} />
updateDoc 메소드 사용하여 구현한다.
import { addDoc, collection, doc, updateDoc } from 'firebase/firestore';
const handleSubmit = useCallback(
async e => {
e.preventDefault();
// 최초 등록 일 경우
if (!editingMode) {
try {
await addDoc(collection(db, 'board'), boardContent);
navigate('/');
} catch (e) {
console.log(e);
}
} else {
// 수정 일 경우
try {
const detailRef = doc(db, 'board', id);
await updateDoc(detailRef, { title: boardContent.title, content: boardContent.content });
navigate('/');
} catch (e) {
console.log(e);
}
}
},
[boardContent],
);
deleteDoc 메소드 사용
import { doc, deleteDoc } from "firebase/firestore";
const deletePost = async () => {
const detailRef = doc(db, 'board', id);
await deleteDoc(detailRef);
};