๐Ÿ”ฅ Firestore Database CRUD

์ง€์€ยท2023๋…„ 2์›” 1์ผ
0

๐Ÿš‚ ํ† ์ด ํ”„๋กœ์ ํŠธ

๋ชฉ๋ก ๋ณด๊ธฐ
4/10
post-thumbnail

1. ํ”„๋กœ์ ํŠธ์— Cloud Firestore ์ถ”๊ฐ€


2. Firestore ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งŒ๋“ค๊ธฐ

๐Ÿ“‚ fbase.js

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore'; // import

const firebaseConfig = {
  ...
};

export const firebase = initializeApp(firebaseConfig);
export const auth = getAuth();
export const db = getFirestore(firebase); // db ์ƒ์„ฑ

Cloud Firestore ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งŒ๋“ค๊ธฐ - Firebase


3. ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ

๐Ÿ“‚ Home.js

import { collection, addDoc } from 'firebase/firestore';
import { db } from 'fbase';

const Home = () => {
	const [tweet, setTweet] = useState('');

	// input ํ•ธ๋“ค๋Ÿฌ
	const onChange = (e) => {
		const { target: { value } } = e;
		setTweet(value); // setTweet(e.target.value);
	};

	// ํŠธ์œ— ์ถ”๊ฐ€
	const onSubmit = async (e) => {
		e.preventDefault();
		try {
			const docRef = await addDoc(collection(db, 'Tweets'), {
				text: tweet,
				createdAt: Date.now(),
			});
			console.log('Document written with ID: ', docRef.id);
		} catch (error) {
			console.error('Error adding document: ', error);
		}

		setTweet('');
	};

	return (
		<>
			Home
			<form onSubmit={onSubmit}>
				<input value={tweet} onChange={onChange} type='text' placeholder="What's happening?" maxLength={120} />
				<input type='submit' value='Tweet' />
			</form>
		</>
	);
};

๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ - Firebase

์ด์ œ ํŠธ์œ—์„ ์ž‘์„ฑํ•˜๋ฉด Firebase ์ฝ˜์†”์—์„œ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


4. ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ

๐Ÿ“‚ Home.js

import { db } from 'fbase';
import { collection, getDocs } from 'firebase/firestore';

const Home = ({ userObj }) => {
	const [tweets, setTweets] = useState([]);

	useEffect(() => {
		getTweets();
	}, []);

	// ํŠธ์œ— ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	const getTweets = async () => {
		const querySnapshot = await getDocs(collection(db, 'Tweets'));
		querySnapshot.forEach((doc) => {
			const tweetObject = {
				...doc.data(),          // {createdAt : ..., text: ...}
				id: doc.id,             // id ์ถ”๊ฐ€
				creatorId: userObj.uid, // ์ž‘์„ฑ์ž id ์ถ”๊ฐ€
			};
			setTweets((prev) => [tweetObject, ...prev]); // ์ƒˆ๋กœ์šด ํŠธ์œ— ๋งจ ์•ž์— ์ถ”๊ฐ€
		});
	};

	return (
		<>
			Home
			<div>
				{tweets.map((tweet) => {
					return (
						<div key={tweet.id}>
							<h4>{tweet.text}</h4>
						</div>
					);
				})}
			</div>
		</>
	);
};

์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฌธ์„œ ๊ฐ€์ ธ์˜ค๊ธฐ - Firebase


5. ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ ๋ฐ›๊ธฐ

// ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ
useEffect(() => {
	const q = query(collection(db, 'Tweets'), orderBy('createdAt', 'desc'));
	const unsubscribe = onSnapshot(q, (querySnapshot) => {
		const newArr = querySnapshot.docs.map((doc) => {
			return {
				...doc.data(),
				id: doc.id,
                creatorId: userObj.uid,
			};
		});
		setTweets(newArr);
	});
}, []);

์ปฌ๋ ‰์…˜์˜ ์—ฌ๋Ÿฌ ๋ฌธ์„œ ๋“ฃ๊ธฐ

3๋ฒˆ์—์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์œ„์ฒ˜๋Ÿผ ๋ฐ”๊ฟ”์ฃผ๋ฉด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—…๋ฐ์ดํŠธ๊ฐ€ ์ƒ๊ธธ ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š์•„๋„ ๋ฐ”๋กœ ํ™”๋ฉด์— ๋ Œ๋”๋ง๋œ๋‹ค.


6. ๋ฐ์ดํ„ฐ ์‚ญ์ œํ•˜๊ธฐ

deleteDoc ํ•จ์ˆ˜์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, collection๋ช…, ์‚ญ์ œํ•˜๋ ค๋Š” document๋ช…์„ ํ•จ๊ป˜ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ“‚ Tweet.js

import { doc, deleteDoc } from 'firebase/firestore';
import { db } from 'fbase';

const Tweet = ({ tweetObj, isCreator }) => {
	// ํŠธ์œ— ์‚ญ์ œ
	const onDeleteClick = async () => {
		const ok = window.confirm('์ด ํŠธ์œ—์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?');

		if (ok) {
			await deleteDoc(doc(db, 'Tweets', tweetObj.id));
		}
	};

	return (
		<div key={tweetObj.id}>
			<h4>{tweetObj.text}</h4>
            // ํŠธ์œ— ์ž‘์„ฑ์ž๋งŒ(isCreator === true์ผ ๋•Œ) ์‚ญ์ œ, ์ˆ˜์ • ๋ฒ„ํŠผ์ด ๋ณด์ธ๋‹ค.
			{isCreator && (
				<>
					<button onClick={onDeleteClick}>Delete</button>
					<button>Edit</button>
				</>
			)}
		</div>

๋ฌธ์„œ ์‚ญ์ œ - Firebase


7. ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ

๐Ÿ“‚ Tweet.js

import { doc, updateDoc } from 'firebase/firestore';
import { db } from 'fbase';

const Tweet = ({ tweetObj, isCreator }) => {
	const [isEditing, setIsEditing] = useState(false); // ํŽธ์ง‘ ๋ชจ๋“œ
	const [newTweet, setNewTweet] = useState(tweetObj.text); // input

	const newTweetRef = doc(db, 'Tweets', tweetObj.id);

	const toggleEditing = () => setIsEditing((prev) => !prev);

	// input ํ•ธ๋“ค๋Ÿฌ
	const onChange = (e) => {
		const {
			target: { value },
		} = e;
		setNewTweet(value);
	};

  	// ํŠธ์œ— ์ˆ˜์ •
	const onSubmit = async (e) => {
		e.preventDefault();
		await updateDoc(newTweetRef, {
			text: newTweet,
		});
		setIsEditing(false);
	};


	return (
		<div key={tweetObj.id}>
			{isEditing ? (
				<>
					<form onSubmit={onSubmit}>
						<input value={newTweet} onChange={onChange} type='text' placeholder='Edit your tweet' required />
						<input type='submit' value='update' />
					</form>
					<button onClick={toggleEditing}>cancel</button>
				</>
			) : (
				<>
					<h4>{tweetObj.text}</h4>
					{isCreator && (
						<>
							<button onClick={onDeleteClick}>Delete</button>
							<button onClick={toggleEditing}>Edit</button>
						</>
					)}
				</>
			)}
		</div>
	);
};

๋ฌธ์„œ ์—…๋ฐ์ดํŠธ - Firebase

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ๋งŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณด๊ณ  ์‹ถ๊ณ ,
๋ฐ์ดํ„ฐ๊ฐ€ ์‚ญ์ œ, ์ˆ˜์ •๋˜๋Š” ๊ฒฝ์šฐ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณด๊ณ ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

profile
๋ธ”๋กœ๊ทธ ์ด์ „ -> https://janechun.tistory.com

0๊ฐœ์˜ ๋Œ“๊ธ€