// 'cmt'를 추가하기 위한 문서 경로 생성 (/tweets/{tweetId}/comments/{userId}) const cmtPath = `tweets/${tweetId}/comments/${userId}`; const cmtDocRef = doc(db, cmtPath); // 'comments' 문서 생성 await setDoc(cmtDocRef, { userId: userId, createdAt: Date.now(), content: cmt, });
좋아요 기능처럼, 사용자 id를 기준으로 댓글을 추가할 수 있게 구현하였지만,
이렇게 되면, 한 사람 당 댓글을 1개 밖에 달지 못하는 문제가 발생한다는 것을 발견하였다.
이를 위해, id로 문서를 만드는 게 아닌,
자동으로 만들어주는 collection함수를 사용하였다.
addDoc
자동 생성된 ID:
addDoc을 사용하면 Firestore가 자동으로 문서 ID를 생성.컬렉션 참조 필요:
addDoc은 특정 컬렉션 참조를 인수로 받아 그 컬렉션에 새로운 문서를 추가.중복 방지: 자동 생성된 ID를 사용하기 때문에 문서 ID의 중복을 피할 수 있음.
예시
javascriptconst commentsCollectionRef = collection(db, `tweets/${tweetId}/comments`); await addDoc(commentsCollectionRef, { userId: userId, createdAt: Date.now(), content: cmt, });
setDoc
사용자 지정 ID:
setDoc을 사용하면 문서 ID를 직접 지정할 수 있음.문서 참조 필요:
setDoc은 특정 문서 참조를 인수로 받아 그 문서에 데이터를 설정하거나 업데이트덮어쓰기: 기본적으로 문서를 덮어씀. 문서가 이미 존재하는 경우, 기존 데이터를 덮어씀.
단,
merge: true 옵션을 사용하면 병합할 수 있음.예시
//javascriptconst commentDocRef = doc(db, `tweets/${tweetId}/comments/{userId}`); javascriptconst commentDocRef = doc(db, `tweets/${tweetId}/comments`, customDocId); await setDoc(commentDocRef, { userId: userId, createdAt: Date.now(), content: cmt, });
인증 규칙 또한 수정해야 한다.
원래의 규칙에서는 댓글 문서의 ID와, 인증된 사용자의 ID를 비교하여 삭제 권한을 제어했는데.
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /tweets/{tweetId} { allow read, write: if request.auth != null; match /likes/{userId} { // 인증된 사용자만 'like'를 추가할 수 있음 allow create: if request.auth != null; // 사용자는 자신의 'like'만 삭제할 수 있음 allow delete: if request.auth.uid == userId; // 'like'를 읽을 수 있는 규칙 allow read: if request.auth != null; } match /comments/{userId} { // 인증된 사용자만 'comment'를 추가할 수 있음 allow create: if request.auth != null; // 사용자는 자신의 'comment'만 삭제할 수 있음 allow delete: if request.auth.uid == userId; // 'comment'를 읽을 수 있는 규칙 allow read: if request.auth != null; } } match /users/{userId} { // 인증된 사용자만 자신의 프로필 정보를 읽을 수 있음 allow read: if request.auth != null; // 인증된 사용자만 자신의 프로필 정보를 업데이트할 수 있음 allow create, update: if request.auth.uid == userId; } } }
수정한 코드는 문서 ID 대신 문서 내의
userId 필드를 사용해야 하므로, request.auth.uid == userId 조건을 request.auth.uid == resource.data.userId로 변경해야 한다.rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /tweets/{tweetId} { allow read, write: if request.auth != null; match /likes/{userId} { // 인증된 사용자만 'like'를 추가할 수 있음 allow create: if request.auth != null; // 사용자는 자신의 'like'만 삭제할 수 있음 allow delete: if request.auth.uid == userId; // 'like'를 읽을 수 있는 규칙 allow read: if request.auth != null; } match /comments/{documentId} { // 인증된 사용자만 'comment'를 추가할 수 있음 allow create: if request.auth != null; // 사용자는 자신의 'comment'만 삭제할 수 있음 (문서 내 userId 필드를 참조) allow delete: if request.auth.uid == resource.data.userId; // 'comment'를 읽을 수 있는 규칙 allow read: if request.auth != null; } } match /users/{userId} { // 인증된 사용자만 자신의 프로필 정보를 읽을 수 있음 allow read: if request.auth != null; // 인증된 사용자만 자신의 프로필 정보를 업데이트할 수 있음 allow create, update: if request.auth.uid == userId; } } }