import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage'; // import
const firebaseConfig = {
...
};
export const firebase = initializeApp(firebaseConfig);
export const auth = getAuth();
export const db = getFirestore(firebase);
export const storage = getStorage(firebase); // storage ์์ฑ
์น์์ Cloud Storage ์์ํ๊ธฐ - Firebase
uploadString()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ base64 , base64url ๋๋ data_url ์ธ์ฝ๋ฉ ๋ฌธ์์ด์ Cloud Storage์ ์
๋ก๋ํ ์ ์๋ค.getDownloadURL()
๋ฉ์๋๋ก ํ์ผ์ ๋ค์ด๋ก๋ํด์ผ ํ๋ค.import { ref, uploadString, getDownloadURL } from 'firebase/storage';
import { storage } from 'fbase';
import { v4 as uuidv4 } from 'uuid';
const [attachment, setAttachment] = useState(null); // ์ด๋ฏธ์ง url
...
const onSubmit = async (e) => {
e.preventDefault();
// ํ์ผ ์ฐธ์กฐ ์์ฑ
const fileRef = ref(storage, `${userObj.email}/${uuidv4()}`); // ์ ์ ์ด๋ฉ์ผ๊ณผ uuid๋ก ๊ฒฝ๋ก ์์ฑ
// ํ์ผ ์
๋ก๋
const response = await uploadString(fileRef, attachment, 'data_url');
// ํ์ผ ๋ค์ด๋ก๋
const fileUrl = await getDownloadURL(ref(storage, fileRef));
// ํธ์ ๊ฐ์ฒด
const tweetObj = {
text: tweet,
createdAt: Date.now(),
creatorId: userObj.uid,
fileUrl,
};
// ์๋ฒ์ ์
๋ก๋
try {
const docRef = await addDoc(collection(db, 'Tweets'), tweetObj);
console.log('Document written with ID: ', docRef.id);
} catch (error) {
console.error('Error adding document: ', error);
}
setTweet('');
setAttachment(null);
};
// File input ํธ๋ค๋ฌ
const onFileChange = (e) => {
const {
target: { files },
} = e;
const file = files[0];
const reader = new FileReader(); // reader ์์ฑ
// reader์ onLoadEnd ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ถ๊ฐ
reader.onloadend = (finishedEvent) => {
// ๋ก๋ฉ ์๋ฃ๋๋ฉด ์คํ๋๋ ์ฝ๋
const {
currentTarget: { result },
} = finishedEvent;
setAttachment(result);
};
reader.readAsDataURL(file);
};
const onClearAttachment = () => setAttachment(null);
...
์ฐธ์กฐ ๋ง๋ค๊ธฐ - Firebase
๋ฌธ์์ด์์ ์
๋ก๋ - Firebase
URL์ ํตํด ๋ฐ์ดํฐ ๋ค์ด๋ก๋ - Firebase
Firebase ์ฝ์์ Storage์์ ์ ์ ์ด๋ฉ์ผ์ ์ด๋ฆ์ผ๋ก ์์ฑ๋ ํด๋ ์์ ์ด๋ฏธ์ง๊ฐ ์
๋ก๋ ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
Cloud Firestore์๋ fileUrl ์์ฑ์ ์ด๋ฏธ์ง์ ๊ฒฝ๋ก๊ฐ ์
๋ ฅ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
...
<h4>{tweetObj.text}</h4>
{tweetObj.fileUrl && <img src={tweetObj.fileUrl} width='50px' />}
{isCreator && (
<>
<button onClick={onDeleteClick}>Delete</button>
<button onClick={toggleEditing}>Edit</button>
</>
)}
...
ํธ์์ ์ญ์ ํ์ ๋ ํธ์๋ง ์ญ์ ํ๋ ๊ฒ์ด ์๋ Storage์ ์ ์ฅํ ์ด๋ฏธ์ง ํ์ผ๊น์ง ์ญ์ ํด์ผ ํ๋ค.
์ด๋ฏธ์ง๋ฅผ ์ญ์ ํ๋ ค๋ฉด ์ด๋ฏธ์ง๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ ๊ฒฝ๋ก๋ฅผ ์์์ผ ํ๋ค.
import { storage } from 'fbase';
import { ref, deleteObject } from 'firebase/storage';
...
const onDeleteClick = async () => {
const ok = window.confirm('์ด ํธ์์ ์ญ์ ํ์๊ฒ ์ต๋๊น?');
if (ok) {
try {
await deleteDoc(newTweetRef); // db์์ ํธ์ ์ญ์
if (tweetObj.fileUrl) {
const desertRef = ref(storage, tweetObj.fileUrl); // ์ญ์ ํ ์ด๋ฏธ์ง์ ref
await deleteObject(desertRef); // storage์์ ์ด๋ฏธ์ง ํ์ผ ์ญ์
}
} catch (err) {
window.alert('ํธ์์ ์ญ์ ํ๋ ๋ฐ ์คํจํ์ต๋๋ค.');
}
}
};
...