firebase 설치
npm i firebase
firebase 설정
import firebase from 'firebase/app'
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,
}
export default firebase.initializeApp(firebaseConfig)
.env파일에 아래와 같은 형태로 저장해야지 create-react-app에서 환경변수로 접근이 가능하다. 이 과정은 단순히 key가 git에 올라가는것만 방지함
REACT_APP_"KEY_NAME"=value
import 절대경로사용
// jsconfig.json { "compilerOptions": { "baseUrl": "src" }, "include": ["src"] }
export const authService = firebase.auth()
try {
if(회원가입) {
await authService.createUserWithEmailAndPassword(email, password);
if(로그인) {
await authService.signInWithEmailAndPassword(email, password);
}
} catch(error){
setError(error.message);
}
에러처리
const [error, setError] = useState(""); /* ... */ {error && <span className="authError">{error}</span>}
Persistence: 사용자들을 어떻게 기억할 것인지 선택
개발자도구 - Application - IndexedDBfirebase.auth.Auth.Persistence.Type
- LOCAL : 브라우저를 닫아도 사용자 정보 기억
- SESSION : 현재 탭에서 사용자 정보 기억
- NONE : 정보 기억x, 새로고침시 로그아웃
새로고침시 로그아웃되는 문제 해결
const [init, setInit] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
authService.onAuthStateChanged((user) => {
if(user){
setIsLoggedIn(true);
}
setInit(true);
});
}, []);
return (
<>
{init ? <AppRouter isLoggedIn={isLoggedIn} /> : "Initializing..."}
</>
)
provider 생성 후 popup
// 구글 provider
const provider = new firebase.auth.GoogleAuthProvider();
// 깃헙 provider
const provider = new firebase.auth.GithubAuthProvider();
await authService.signInWithPopup(provider);
로그아웃 및 리다이렉션
const history = useHistory();
const onLogOutClick = () => {
authService.signOut();
history.push("/");
};
firebase database 설정
import 'firebase/firestore'
export const dbService = firebase.firestore()
Create
await dbService.collection("tweets").add(tweetObj);
Read(Realtime)
await dbService.collection("tweets").onSnapshot((snapshot) => {
const tweetArray = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data()
}));
setTweets(tweetArray);
});
Update
await dbService.doc(`tweets/${tweetObj.id}`).update(tweetObj);
Delete
await dbService.doc(`tweets/${tweetObj.id}`).delete();
사진 업로드
const [attachment, setAttachment] = useState("");
// 파일 선택
const onFileChange = (event) => {
const {target: {files}} = event;
const theFile = files[0];
const reader = new FileReader();
// 이벤트 리스터 추가
reader.onloadend = (finishedEvent) => {
const {currentTarget: {result}} = finishedEvent;
setAttachment(result);
};
// 파일 읽기
reader.readAsDataURL(theFile);
};
// 파일 삭제
const onClearAttachment = () => {
setAttachment("");
};
return(
<>
<input type="file" accept="image/*" onChange={onFileChange} />
{attachment && (
<>
<img src={attachment} />
<button onClick={onClearAttachment}>Clear</button>
</>
)}
</>
)
firebase storage 저장
import 'firebase/storage'
export const storageService = firebase.storage()
// 파일에 대한 reference 생성
const attachmentRef = storageService.ref().child(`${userObj.uid}/${uuidv4()}`);
// 파일 내용 업데이트(reference에 파일 정보 담기)
const response = await attachmentRef.putString(attachment, "data_url");
// 접근가능한 URL 생성
const attachmentUrl = await response.ref.getDownloadURL();
uuidv4: 이미지 이름을 랜덤으로 생성하기 위한 랜덤 식별자 생성 라이브러리
npm i uuid
import { v4 as uuidv4 } from "uuid"; uuidv4() // 랜덤 식별자 생성
firebase storage 삭제
await storageService.refFromURL(tweetObj.attachmentUrl).delete();
firebase에서 내정보 불러오기(쿼리사용)
const getMyTweets = async() => {
const tweets = await dbService
.collection("tweets")
.where("creatorId", "==", userObj.uid)
.orderBy("createdAt")
.get();
console.log(tweets.docs.map((doc)=>doc.data()));
};
firebase는 NoSQL이여서 쿼리 사용시 쿼리에 대한 복합 인덱스를 생성해주어야한다.
user객체 크기 경량화
{
displayName: user.displayName,
uid: user.uid,
updateProfile: (args) => user.updateProfile(args)
}
이유: 변경되는 객체의 크기가 크다면 react의 리렌더링 기능이 동작하지 않을 수 있다.