Firebase를 사용하여 나만의 댓글 시스템을 구축하는 방법
게시 됨: 2022-03-10댓글 섹션은 블로그 커뮤니티를 구축하는 좋은 방법입니다. 최근에 블로그를 시작하면서 댓글 섹션을 추가할 생각을 했습니다. 하지만 쉽지 않았습니다. Disqus 및 Commento와 같은 호스팅된 댓글 시스템에는 다음과 같은 고유한 문제가 있습니다.
- 그들은 귀하의 데이터를 소유합니다.
- 그들은 무료가 아닙니다.
- 당신은 그들을 많이 사용자 정의 할 수 없습니다.
그래서 나만의 댓글 시스템을 구축하기로 결정했습니다. Firebase는 백엔드 서버 실행에 대한 완벽한 호스팅 대안처럼 보였습니다.
우선, 자신만의 데이터베이스가 있는 모든 이점을 얻을 수 있습니다. 데이터를 제어하고 원하는 대로 구성할 수 있습니다. 둘째, 백엔드 서버를 설정할 필요가 없습니다. 프런트 엔드에서 쉽게 제어할 수 있습니다. 백엔드의 번거로움이 없는 호스팅 시스템이라는 두 가지 장점을 모두 갖춘 것과 같습니다.
이 포스트에서는 그것이 우리가 할 일입니다. 정적 사이트 생성기 Gatsby로 Firebase를 설정하는 방법을 알아보겠습니다. 그러나 원칙은 모든 정적 사이트 생성기에 적용될 수 있습니다.
뛰어들자!
Firebase란 무엇입니까?
Firebase는 데이터베이스, 호스팅, 클라우드 기능, 인증, 분석 및 스토리지와 같은 앱 개발자를 위한 도구를 제공하는 서비스로서의 백엔드입니다.
Cloud Firestore(Firebase의 데이터베이스)는 이 프로젝트에 사용할 기능입니다. NoSQL 데이터베이스입니다. 이는 행, 열 및 테이블이 있는 SQL 데이터베이스처럼 구조화되지 않았음을 의미합니다. 큰 JSON 트리로 생각할 수 있습니다.
프로젝트 소개
GitHub에서 저장소를 복제하거나 다운로드하여 프로젝트를 초기화해 보겠습니다.
진행하면서 변경 사항을 더 쉽게 추적할 수 있도록 모든 단계에 대해 두 개의 분기(시작 부분과 끝 부분)를 만들었습니다.
다음 명령을 사용하여 프로젝트를 실행해 보겠습니다.
gatsby develop
브라우저에서 프로젝트를 열면 기본 블로그의 뼈대가 보일 것입니다.
댓글 섹션이 작동하지 않습니다. 단순히 샘플 주석을 로드하고 주석이 제출되면 세부 정보를 콘솔에 기록합니다.
우리의 주요 임무는 코멘트 섹션을 작동시키는 것입니다.
댓글 섹션 작동 방식
무엇이든 하기 전에 주석 섹션의 코드가 어떻게 작동하는지 이해합시다.
네 가지 구성 요소가 주석 섹션을 처리합니다.
-
blog-post.js
-
Comments.js
-
CommentForm.js
-
Comment.js
먼저 게시물에 대한 댓글을 식별해야 합니다. 이것은 각 블로그 게시물에 대해 고유한 ID를 만들어 수행하거나 항상 고유한 슬러그를 사용할 수 있습니다.
blog-post.js
파일은 모든 블로그 게시물의 레이아웃 구성 요소입니다. 블로그 게시물의 슬러그를 얻기위한 완벽한 진입점입니다. 이것은 GraphQL 쿼리를 사용하여 수행됩니다.
export const query = graphql` query($slug: String!) { markdownRemark(fields: { slug: { eq: $slug } }) { html frontmatter { title } fields { slug } } } `
Comments.js
구성 요소로 보내기 전에 Gatsby가 슬러그에 추가하는 후행 슬래시( /
)를 제거하기 위해 substring()
메서드를 사용합시다.
const slug = post.fields.slug.substring(1, post.fields.slug.length - 1) return ( <Layout> <div className="container"> <h1>{post.frontmatter.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.html }} /> <Comments comments={comments} slug={slug} /> </div> </Layout> ) }
Comments.js
구성 요소는 각 주석을 매핑하고 해당 데이터를 모든 응답과 함께 Comment.js
에 전달합니다. 이 프로젝트를 위해 나는 댓글 시스템을 한 단계 더 깊이 들어가기로 결정했습니다.
또한 구성 요소는 최상위 주석을 캡처하기 위해 CommentForm.js
를 로드합니다.
const Comments = ({ comments, slug }) => { return ( <div> <h2>Join the discussion</h2> <CommentForm slug={slug} /> <CommentList> {comments.length > 0 && comments .filter(comment => !comment.pId) .map(comment => { let child if (comment.id) { child = comments.find(c => comment.id === c.pId) } return ( <Comment key={comment.id} child={child} comment={comment} slug={slug} /> ) })} </CommentList> </div> ) }
CommentForm.js
로 넘어갑시다. 이 파일은 간단하여 의견 양식을 렌더링하고 제출을 처리합니다. 제출 방법은 세부 정보를 콘솔에 기록하기만 하면 됩니다.
const handleCommentSubmission = async e => { e. preventDefault() let comment = { name: name, content: content, pId: parentId ∣∣ null, time: new Date(), } setName("") setContent("") console.log(comment) }
Comment.js
파일에는 많은 일이 있습니다. 더 작은 조각으로 나누자.
먼저 주석을 렌더링하는 SingleComment
구성 요소가 있습니다.
멋진 아바타를 얻기 위해 Adorable API를 사용하고 있습니다. Moment.js 라이브러리는 사람이 읽을 수 있는 형식으로 시간을 렌더링하는 데 사용됩니다.
const SingleComment = ({ comment }) => ( <div> <div className="flex-container"> <div className="flex"> <img src="https://api.adorable.io/avazars/65/[email protected]" alt="Avatar" /> </div> <div className="flex"> <p className="comment-author"> {comment.name} <span>says</span> </p> {comment.time} &&(<time>(moment(comment.time.toDate()).calendar()}</time>)} </div> </div> </p>{comment.content}</p> </div> )
파일의 다음은 Comment
구성 요소입니다. 이 구성 요소는 하위 주석이 전달된 경우 하위 주석을 표시합니다. 그렇지 않으면 "응답" 버튼 또는 "회신 취소" 버튼을 클릭하여 켜고 끌 수 있는 응답 상자를 렌더링합니다.
const Comment = ({ comment, child, slug }) => { const [showReplyBox, setShowReplyBox] = useState(false) return ( <CommentBox> <SingleComment comment={comment} /> {child && ( <CommentBox child className=comment-reply"> <SingleComment comment={child} /> </CommentBox> )} {!child && ( <div> {showReplyBox ? ( <div> <button className="btn bare" onClick={() => setShowReplyBoy(false)} > Cancel Reply </button> <CommentForm parentId={comment.id} slug={slug} /> </div> ) : ( <button className="btn bare" onClick={() => setShowReplyBox(true)}> Reply </button> )} </div> )} </div> )} </CommentBox>
이제 개요가 있으므로 의견 섹션을 만드는 단계를 살펴보겠습니다.
1. Firebase 추가
먼저 프로젝트에 Firebase를 설정해 보겠습니다.
가입하여 시작하십시오. Firebase로 이동하여 Google 계정에 가입합니다. 계정이 없으면 "시작하기"를 클릭하십시오.
"프로젝트 추가"를 클릭하여 새 프로젝트를 추가합니다. 프로젝트 이름을 추가하고 "프로젝트 만들기"를 클릭합니다.
프로젝트를 만든 후에는 Cloud Firestore를 설정해야 합니다.
왼쪽 메뉴에서 "데이터베이스"를 클릭합니다. "Cloud Firestore"라는 페이지가 열리면 "데이터베이스 생성"을 클릭하여 새 Cloud Firestore 데이터베이스를 생성합니다.
팝업이 나타나면 "테스트 모드에서 시작"을 선택하십시오. 그런 다음 가장 가까운 Cloud Firestore 위치를 선택합니다.
이와 같은 페이지가 표시되면 Cloud Firestore 데이터베이스가 성공적으로 생성되었음을 의미합니다.
응용 프로그램에 대한 논리를 설정하여 마치겠습니다. 애플리케이션으로 돌아가 Firebase를 설치합니다.
yarn add firebase
루트 디렉토리에 새 파일 firebase.js
를 추가합니다. 다음 내용을 붙여넣습니다.
import firebase from "firebase/app" import "firebase/firestore" var firebaseConfig = 'yourFirebaseConfig' firebase.initializeApp(firebaseConfig) export const firestore = firebase.firestore() export default firebase
yourFirebaseConfig
를 프로젝트용으로 바꿔야 합니다. 그것을 찾으려면 Firebase 앱에서 '프로젝트 개요' 옆에 있는 톱니바퀴 아이콘을 클릭하세요.
설정 페이지가 열립니다. 앱의 부제목 아래에서 다음과 같은 웹 아이콘을 클릭합니다.
팝업이 열립니다. "앱 닉네임" 필드에 이름을 입력하고 "앱 등록"을 클릭합니다. 그러면 firebaseConfig
객체가 제공됩니다.
<!-- The core Firebase JS SDK is always required and must be listed first --> <script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-app.js"></script> <!-- TODO: Add SDKs for Firebase products that you want to use https://firebase.google.com/docs/web/setup#available-libraries --> <script> // Your web app's Firebase configuration var firebaseConfig = { ... }; // Initialize Firebase firbase.initializeApp(firebaseConfig); </script>
firebaseConfig
객체의 콘텐츠만 복사하여 firebase.js
파일에 붙여넣습니다.
Firebase API 키를 노출해도 되나요?
네. Google 엔지니어가 말한 대로 API 키를 노출하는 것은 괜찮습니다.
API 키의 유일한 목적은 Google의 데이터베이스로 프로젝트를 식별하는 것입니다. Cloud Firestore에 대해 강력한 보안 규칙을 설정한 경우 누군가가 API 키를 도용해도 걱정할 필요가 없습니다.
우리는 마지막 섹션에서 보안 규칙에 대해 이야기할 것입니다.
현재로서는 Firestore를 테스트 모드로 실행하고 있으므로 API 키를 공개해서는 안 됩니다.
Firestore를 사용하는 방법?
다음 두 가지 유형 중 하나로 데이터를 저장할 수 있습니다.
- 수집
컬렉션에는 문서가 포함되어 있습니다. 문서의 배열과 같습니다. - 문서
문서에는 필드-값 쌍의 데이터가 포함되어 있습니다.
컬렉션에는 문서만 포함될 수 있으며 다른 컬렉션은 포함될 수 없습니다. 그러나 문서에는 다른 컬렉션이 포함될 수 있습니다.
즉, 컬렉션 내에 컬렉션을 저장하려면 다음과 같이 컬렉션을 문서에 저장하고 해당 문서를 컬렉션에 저장합니다.
{collection-1}/{document}/{collection-2}
데이터를 구조화하는 방법?
Cloud Firestore는 본질적으로 계층적이므로 사람들은 다음과 같이 데이터를 저장하는 경향이 있습니다.
blog/{blog-post-1}/content/comments/{comment-1}
그러나 이러한 방식으로 데이터를 저장하면 종종 문제가 발생합니다.
의견을 받고 싶다고 말합니다. 블로그 컬렉션 깊숙이 저장된 댓글을 찾아야 합니다. 이렇게 하면 코드가 더 오류가 발생하기 쉽습니다. Chris Esplin은 하위 컬렉션을 사용하지 않을 것을 권장합니다.
데이터를 병합된 개체로 저장하는 것이 좋습니다.
blog-posts/{blog-post-1} comments/{comment-1}
이렇게 하면 데이터를 쉽게 가져오고 보낼 수 있습니다.
Firestore에서 데이터를 가져오는 방법?
데이터를 가져오기 위해 Firebase는 두 가지 방법을 제공합니다.
-
get()
내용을 한 번 가져오기 위한 것입니다. -
onSnapshot()
이 방법은 데이터를 보낸 다음 구독을 취소하지 않는 한 업데이트를 계속 보냅니다.
Firestore에 데이터를 보내는 방법?
데이터 가져오기와 마찬가지로 Firebase에는 데이터를 저장하는 두 가지 방법이 있습니다.
-
set()
문서의 ID를 지정하는 데 사용됩니다. -
add()
자동 ID로 문서를 생성할 때 사용합니다.
알아요, 이해가 많이 되었습니다. 그러나 걱정하지 마십시오. 프로젝트에 도달하면 이러한 개념을 다시 검토할 것입니다.
2. 샘플 날짜 만들기
다음 단계는 쿼리할 샘플 데이터를 만드는 것입니다. Firebase로 이동하여 이를 수행해 보겠습니다.
Cloud Firestore로 이동합니다. "컬렉션 시작"을 클릭합니다. "컬렉션 ID"에 대한 comments
을 입력하고 "다음"을 클릭합니다.
"문서 ID"에 대해 "자동 ID. 다음 데이터를 입력하고 "저장"을 클릭합니다.
데이터를 입력하는 동안 "필드" 및 "유형"이 위의 스크린샷과 일치하는지 확인하십시오. 그런 다음 "저장"을 클릭합니다.
이것이 Firestore에서 수동으로 주석을 추가하는 방법입니다. 절차가 복잡해 보이지만 걱정하지 마십시오. 이제부터 앱에서 댓글을 추가할 것입니다.
이 시점에서 데이터베이스는 다음과 같습니다. comments/{comment}
.
3. 댓글 데이터 가져오기
샘플 데이터를 쿼리할 준비가 되었습니다. 블로그에 대한 데이터를 가져오는 것으로 시작해 보겠습니다.
blog-post.js
로 이동하여 방금 만든 Firebase 파일에서 Firestore를 가져옵니다.
import {firestore} from "../../firebase.js"
쿼리를 위해 React의 useEffect
후크를 사용합니다. 아직 가져오지 않았다면 가져오도록 합시다.
useEffect(() => { firestore .collection(`comments`) .onSnapshot(snapshot => { const posts = snapshot.docs .filter(doc => doc.data().slug === slug) .map(doc => { return { id: doc.id, ...doc.data() } }) setComments(posts) }) }, [slug])
데이터를 가져오는 데 사용되는 방법은 onSnapshot
입니다. 이는 상태 변경 사항도 수신하기를 원하기 때문입니다. 따라서 사용자가 브라우저를 새로 고칠 필요 없이 댓글이 업데이트됩니다.
슬러그가 현재 슬러그와 일치하는 주석을 찾기 위해 filter
및 map
메소드를 사용했습니다.
마지막으로 생각해야 할 것은 정리입니다. onSnapshot
은 계속 업데이트를 보내기 때문에 애플리케이션에 메모리 누수가 발생할 수 있습니다. 다행히 Firebase는 깔끔한 수정을 제공합니다.
useEffect(() => { const cleanUp = firestore .doc(`comments/${slug}`) .collection("comments") .onSnapshot(snapshot => { const posts = snapshot.docs.map(doc => { return { id: doc.id, ...doc.data() } }) setComments(posts) }) return () => cleanUp() }, [slug])
완료되면 gatsby develop
을 실행하여 변경 사항을 확인합니다. 이제 Firebase에서 데이터를 가져오는 주석 섹션을 볼 수 있습니다.
주석을 저장하는 작업을 해보자.
4. 스토어 댓글
주석을 저장하려면 CommentForm.js
파일로 이동하십시오. Firestore도 이 파일로 가져오겠습니다.
import { firestore } from "../../firebase.js"
Firebase에 댓글을 저장하려면 Firestore가 자동 ID로 문서를 생성하기를 원하기 때문에 add()
메서드를 사용합니다.
handleCommentSubmission
메소드에서 그렇게 합시다.
firestore .collection(`comments`) .add(comment) .catch(err => { console.error('error adding comment: ', err) })
먼저 주석 컬렉션에 대한 참조를 얻은 다음 주석을 추가합니다. 또한 주석을 추가하는 동안 오류를 포착하기 위해 catch
메서드를 사용하고 있습니다.
이때 브라우저를 열면 댓글 섹션이 작동하는 것을 볼 수 있습니다. 새로운 댓글을 추가하고 답글을 게시할 수 있습니다. 더 놀라운 것은 페이지를 새로 고칠 필요 없이 모든 것이 작동한다는 것입니다.
Firestore에서 데이터를 저장하고 있는지 확인할 수도 있습니다.
마지막으로 Firebase에서 한 가지 중요한 사항인 보안 규칙에 대해 이야기해 보겠습니다.
5. 보안 규칙 강화
지금까지는 테스트 모드에서 Cloud Firestore를 실행했습니다. 이것은 URL에 대한 액세스 권한이 있는 모든 사람이 우리 데이터베이스에 추가하고 읽을 수 있음을 의미합니다. 그건 무섭다.
이를 해결하기 위해 Firebase는 보안 규칙을 제공합니다. Cloud Firestore에서 데이터베이스 패턴을 생성하고 특정 활동을 제한할 수 있습니다.
두 가지 기본 작업(읽기 및 쓰기) 외에도 Firebase는 가져오기, 나열, 만들기, 업데이트 및 삭제와 같은 보다 세분화된 작업을 제공합니다.
읽기 작업은 다음과 같이 나눌 수 있습니다.
-
get
단일 문서를 가져옵니다. -
list
문서 또는 컬렉션 목록을 가져옵니다.
쓰기 작업은 다음과 같이 나눌 수 있습니다.
-
create
새 문서를 만듭니다. -
update
기존 문서를 업데이트합니다. -
delete
문서를 삭제합니다.
애플리케이션을 보호하려면 Cloud Firestore로 돌아가세요. "규칙"에서 다음을 입력하십시오.
service cloud.firestore { match /databases/{database}/documents { match /comments/{id=**} { allow read, create; } } }
첫 번째 줄에서 서비스를 정의합니다. 이 경우에는 Firestore입니다. 다음 줄은 Firebase에 comments
컬렉션 내부의 모든 항목을 읽고 생성할 수 있음을 알려줍니다.
우리가 이것을 사용했다면 :
allow read, write;
... 즉, 사용자가 기존 댓글을 업데이트하고 삭제할 수 있으며, 이는 우리가 원하지 않습니다.
Firebase의 보안 규칙은 매우 강력하여 특정 데이터, 활동, 심지어 사용자까지 제한할 수 있습니다.
자신의 의견 섹션을 작성하려면
축하 해요! Firebase의 위력을 방금 확인했습니다. 안전하고 빠른 응용 프로그램을 구축하는 데 매우 뛰어난 도구입니다.
우리는 매우 간단한 댓글 섹션을 만들었습니다. 그러나 더 많은 가능성을 탐색하는 것을 막을 수는 없습니다.
- 프로필 사진을 추가하고 Firebase용 Cloud Storage에 저장합니다.
- Firebase를 사용하여 사용자가 계정을 만들고 Firebase 인증을 사용하여 인증하도록 허용합니다.
- Firebase를 사용하여 인라인 Medium과 유사한 댓글을 만드세요.
시작하는 가장 좋은 방법은 Firestore의 설명서로 이동하는 것입니다.
마지막으로 아래 댓글 섹션으로 이동하여 Firebase를 사용하여 댓글 섹션을 구축한 경험에 대해 논의해 보겠습니다.
유용한 프론트엔드 및 UX 비트, 일주일에 한 번 제공됩니다.
작업을 더 잘 수행하는 데 도움이 되는 도구가 있습니다. 이메일을 통해 Vitaly의 스마트 인터페이스 디자인 체크리스트 PDF 를 구독하고 받으십시오.
프론트엔드 및 UX에서. 190,000명의 사람들이 신뢰합니다.