![트위터 클론코딩(with firebase) - 04](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPOnsD%2Fbtr5orySHQf%2FYo4XemR1SMfg7ajmXkDHbK%2Fimg.png)
5. NWEETING
5-1. Form and Database Setup
- Home.js에 input랑 useState 추가.
새로 생성해준 form 태그 내부에 input을 생성해줌.
하나는 text type의 input을, 하나는 submit type의 input을 생성해줌.
- text type의 input : 최대 글자수를 120자로 제한해둠.
그리고 onChange event 실행시 onChange 함수가 함께 실행되도록 함.
value는 nweet로 설정하여 nweet 값이 input에 들어오도록 함.
useState를 하나 생성해줌.
const [nweet, setNweet] = useState("");
그리고 onChange 함수를 선언해준 후 매개변수로 event를 넣어줌.
함수 내부에 const { target : { value } } = event; 를 선언해줌.
구조 분해 할당을 해준 것으로 const value = event.target.value; 와 같음.
그 다음에 setNweet(value); 코드 작성하여 input에 글을 작성할 때마다 nweet 값이 value에 들어오도록 함.
form 태그 역시 onSubmit event가 실행되면 onSubmit 함수가 함께 실행되도록 해줌.
onSubmit 함수의 매개변수로 event를 준 후 내부에 event.preventDefault(); 코드를 작성하여
button을 클릭시 새로고침이 되는 것을 막아줌.
이제 database를 만들어 볼 거임.
nwitter project의 Cloud Firestore로 이동하여 Database 생성하기 클릭.
우리는 test mode로 database를 만들 거임.
Cloud Firestore 위치는 asia-northeast3 (Seoul)로 설정.
5-2. Nweeting!
Cloud Firestore의 database는 NoSQL database임.
상당히 유연하고 규칙이 적으며, 사용하기 쉽다는 장점이 있음.
하지만 규칙이 많이 없어 제한되는 부분이 좀 있음.
다른 형태의 데이터베이스로는 SQL database가 있음.
SQL database에는 많은 규칙과 관습들이 있음.
매우 오래된 시스템으로, 더 높은 자유도를 가지고 있음.
- Firestore인 NoSQL database가 가지는 특징 두 가지.
1. Collection을 가지고 있음.
기본적으로 폴더와 같음. Collection은 document들을 가지고 있음.
2. Document를 가지고 있음.
컴퓨터에 있는 문서 같은 것.
Collection은 nweets,
Document는 "sdsd : sdsdsds" 필드를 가지고 있음.
Collection으로 개인 메세지 같은 것을 가질 수도 있음.
일단 nweets 라는 Collection을 삭제해줌.
❗ Firestore를 가져다 쓰기 위한 코드 추가
1. firebase.js에 import { getFirestore } from "firebase/firestore" 코드 작성.
Firebase가 최신 버전으로 업데이트 되면서import "firebase/firestore" => import { getFirestore } from "firebase/firestore" 로 코드 변경.
firestore와 관련된 문서는 되게 복잡하게 되어 있음...
firebase 공식 사이트가 아니라 Google Cloud 공식 사이트 쪽에 정보가 다 정리되어 있음.
❗ firestore에 관하여 더 자세히 살펴보고 싶다면? :
https://cloud.google.com/firestore/docs/manage-data/add-data
2. 그리고 하단에 firestore를 dbService에 담아 내보내줌.
이 역시 Firebase가 최신 버전으로 업데이트 되면서
export const dbService = firebase.firestore(); => export const authService = getAuth(app);
으로 코드 변경.
이제 해야 할 것은,
Home.js에서 onSubmit event가 실행될 때마다(onSubmit 함수가 실행될 때마다)
document를 생성하는 것임.
❗ Firebase에서 firestore에 관하여 찾기
- Firebase Docs로 이동
- Docs의 Reference로 이동
- firebase firestore로 이동
firestore의 CollectionReference로 들어가서
Collection에 관하여 알아보도록 하겠음.
Collection은 Collection path라는 것을 줘야 함.
Collection path는 참조된 Collection의 경로를 나타냄.
위에서 말했듯이, 이제 해야 할 것은
Home.js에서 onSubmit event가 실행될 때마다 Document를 생성시켜주는 것임.
- firestore를 가져다 쓸 수 있도록 Home.js에 dbService를 import해줌.(firebase.js에서)
- addDoc과 collection을 가져다 쓸 수 있도록 이 둘 역시 import해줌. (firebase/firestore에서)
Collection path를 지정해주기 위해서는 addDoc() 함수를 호출해야 함.
=> 데이터를 추가할 때는 setDoc, addDoc를 주로 사용
onSubmit 함수 내부에 docRef 변수 선언.
const docRef = addDoc(collection(dbservice, "nweets"), {
nweet : nweet, => nweet(key값) : nweet(useState의 nweet값 : input에 담기는 값)
createAt : Date.now(),
=> createAt(key값) : Date.now()(1970년 1월 1일 0시 0분 0초부터 현재까지 경과된 밀리 초를 반환)
});
"nweets"는 collection의 이름을 의미.
{
중괄호 내부에는 Document, 필드를 설정해줄 수 있음.
필드의 key : value,
}
promise를 return해야 하므로 async, await를 사용.
- adding data : data 추가
- Google Cloud 공식 문서 : https://cloud.google.com/firestore/docs/manage-data/add-data
- Add a document (문서 추가)
보통 setDoc를 쓰지만, 문서에 의미 있는 ID가 없는 경우가 있으므로
Firestore에서 자동으로 ID를 생성하도록 하는 것이 더 편리함.
다음 언어별 add()메서드를 호출하여 이 작업을 수행할 수 있음.
- Firebase 공식 문서 : https://firebase.google.com/docs/reference/js/firestore_.collectionreference#collectionreferencepath
Document 내부에는 id가 있음.
Document가 생성될 때마다 id가 새롭게 생성됨.
console을 찍어서 확인해볼 수 있음. => docRef.id
input창 안에 글자를 써서 submit button을 누르고 나면
input창이 빌 수 있게끔 setNweet(""); 코드 작성.
지금까지 작성한 코드들을 try, catch문 안에 집어넣어보겠음.
try, catch문은 예외 처리를 해줄 때 사용하는 자바스크립트 문법임.
예외 처리를 하는 이유는?
프로그램의 언어들이 항상 완벽하게 동작하지는 않음.
단순 버그이거나, 프로그래머가 잘못 작성했거나, 프로그래밍 언어 자체가 에러를 내는 경우가 있음.
에러가 발생하면 나머지 로직이 실행되지 않음. 그 시점에 실행 중이었던 작업을 완료할 수 없게 됨. 코드의 실행이 중단됨.
but,
try...catch...finally 구문을 사용하면 에러가 나더라도 코드의 실행을 지속할 수 있음.
- 사용 방법
try {
// 여기서 에러가 나면 에러가 난 시점에 코드의 흐름이
// catch로 넘어간다.
console.log('에러가 나기 직전까지의 코드는 잘 실행됩니다.');
new Array(-1); // RangeError: Invalid array length
console.log('에러가 난 이후의 코드는 실행되지 않습니다.');
} catch (e) {
console.log('코드의 실행 흐름이 catch 블록으로 옮겨집니다.');
alert(`다음과 같은 에러가 발생했습니다: ${e.name}: ${e.message}`);
}
- try : 에러가 났을 때 원상복구를 시도할 코드. 에러 발생시 코드의 실행 흐름이 catch 블록으로 옮겨감.
- catch : 에러에 대한 정보를 담고 있는 객체(위 예제의 e)를 사용할 수 있음.
- e.name : RangeError같은 에러의 이름
- e.meassage : Invalid array length 에러 메시지
5-3. Getting the Nweets
이제 Nweets를 가져와볼 거임.
이제 해야 할 것은
마운트 될 때마다 새로운 Document가 들어올 수 있도록 하는 것임.
- firestore를 가져다 쓸 수 있도록 Home.js에 dbService를 import해줌.(firebase.js에서)
- collection과 getDocs, query를 가져다 쓸 수 있도록 이 둘 역시 import해줌. (firebase/firestore에서)
- useState와 useEffect도 쓸 거기 때문에 import해줌. (react에서)
useState를 하나 생성해줄 거임. 초기값을 빈 배열로 한 nweets와 setNweets.
기존에 존재하는 Document들에 새로운 Document를 추가해줄 거임.
- getting data : data 가져오기
- Google Cloud 공식 문서 : https://cloud.google.com/firestore/docs/query-data/get-data
- Get multiple documents from a collection (컬렉션에서 여러 문서 가져오기)
컬렉션의 문서를 쿼리하여 한 번의 요청으로 여러 문서를 검색할 수도 있음.
where()를 사용하여 특정 조건을 충족하는 모든 문서를 쿼리한 다음 결과를 검색하는 데 get()을 사용할 수 있음.
5-4. Realtime Nweets
Document 실시간 업데이트 받기
- firebase 공식 문서 : https://firebase.google.com/docs/reference/js/v8/firebase.firestore.CollectionReference#onsnapshot
- Google Cloud 공식 문서 : https://cloud.google.com/firestore/docs/query-data/listen
onSnapshot은 기본적으로 데이터베이스의 변화를 실시간으로 알려줌.
5-5. Delete and Update
때론 원하지 않는 데도 어플리케이션이 너무 실시간으로 실행될 때가 있음.
ex) 만약 텍스트를 수정하거나 삭제한다면 모든 곳에서 그게 사라지는가? => 아님.
누군가가 수정하거나 지운 댓글들이 실시간으로 나타나는 걸 보고 싶지는 않음.
1. 먼저, nweets.map을 돌리는 과정에서 안에 코드를 더 작성해줄 것이므로 Nweet component를 새로 하나 생성.
(지저분해 보일 수 있으므로 component를 분리시켜 주겠다는 뜻)
2. Nweets component에 각각의 객체들, 즉 nweet를 props 해줌.
Nweet component에 기존에 있던 코드들을 작성한 후
Delete, Edit button도 추가해줌.
이제 우리에게 필요한 것은 자신이 작성한 Document를 찾아내는 것.
=> 가지고 있는 creatorId를 이용할 거임( userObj.uid )
nweet.creatorId와 userObj.uid가 일치하는 것을 찾아 inOwner에 담아준 후 props로 내려줌.
Nweet.js로 넘어가서 inOwner를 props로 내려받은 후
{ isOwner ? ( <> <button> Delete Nweet </button> <button> Edit Nweet </button> </> ) : ( <></> ) }
isOwner가 true면 Delete, Edit button이 보이도록 하고, false면 아무 것도 보이지 않게끔 함.
=> isOwner는 현재 로그인하고 있는 user를 의미하기 때문.
이제 Delete Nweet button을 눌렀을 때 삭제가 되게끔 할 거임.
<button onClick={ onDeleteClick }> Delete Nweet </button>
=> button을 onClick 했을 때 onDeleteClick 함수가 실행됨.
- Firebase Delete 문서 :
https://firebase.google.com/docs/reference/js/v8/firebase.firestore.DocumentReference#delete
- Delete ( 삭제 )
delete()는 문서를 삭제하는데 사용됨.
- Google Cloud Delete 문서 :
https://cloud.google.com/firestore/docs/manage-data/delete-data#collections
- Delete documents ( 문서 삭제 )
Google Cloud에도 문서를 삭제하려면 delete() 방식을 사용하라고 나와 있음.
그리고 그 안에서도 deleteDoc()를 사용하라고 나와 있음.
await deleteDoc(doc(db, "cities", "DC"));
그런데, 나중에 수정한 내용을 update할 때도 똑같은 방식을 사용되기 때문에
NweetTextRef라는 변수를 만들어 거기 doc(dbService, "nweets", `${nweet.id}`);를 담아줌.
맨 위에 doc와 deleteDoc도 함께 import해줌. (firebase/firestore에서)
아, 그리고 이 삭제 관련 코드를 작성하기 이전에 confirm(확인)창을 한 번 띄워보도록 하겠음.
"당신은 이 게시글을 삭제하시겠습니까?" 라고 삭제할 건지 물어보는 것.
그렇게 해서 그걸 ok 변수에 담아줌. =>
confirm창에 확인을 누르면 ok에 true값이 들어오고, 취소를 누르면 false가 들어옴.
그리고 변수 ok의 값을 이용하여 if문을 작성.
ok가 true일 때 await deleteDoc(NweetTextRef);, false일 때는 아무것도 반환하지 않음.
다음으로, 수정 기능을 추가해보도록 하겠음.
아무래도 추가, 삭제 등에 비해서 조금 복잡하지 않나 하는 생각이 들었음.
'(심층)리액트' 카테고리의 다른 글
트위터 클론코딩(with firebase) - 05 (1) | 2023.02.14 |
---|---|
트위터 클론코딩(with firebase) - 하나의 이메일로 여러 계정 생성이 안되는 문제 해결 (0) | 2023.02.09 |
트위터 클론코딩(with firebase) - 03 (0) | 2023.02.03 |
트위터 클론코딩(with firebase) - 02 (0) | 2023.02.01 |
트위터 클론코딩(with firebase) - 01 (6) | 2023.02.01 |
github : https://github.com/dnjfht
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!