코딩 정보/NextJs

[NextJs] 파이어 베이스를 통해 채팅을 구현해보자

꽁이꽁설꽁돌 2025. 5. 12. 01:43
728x90
반응형
     

목차

     

    파이어 베이스 가입 및 설정

    위와 같이 가입한 후 firestore database를 만들어주자

     

     

    다음과 같이 규칙 설정을 해주자

    우리는 일단 테스트를 진행할 것이므로 보안 규칙을 모두 다 접근 가능하게 설정해 주자

     

     

    규칙 설정 코드

    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if true;
        }
      }
    }

     

     

    그 후 아래 프로젝트 설정에서 다음과 같은 코드를 복사해주자

     

    위의 코드를 fire-config.ts 로 파일에 넣어주자

     

     

    firestore 특징

    SQL 데이터베이스와 달리 테이블이나 행이 없으며, 컬렉션으로 정리되는 문서에 데이터를 저장합니다. 그리고 각 문서에는 키-값 쌍이 들어 있습니다.


    출처: Cloud Firestore 데이터 모델

     

    Cloud Firestore 데이터 모델  |  Firebase

    이제 MongoDB 호환성을 갖춘 Firestore Enterprise 버전을 사용할 수 있습니다. 자세히 알아보기 의견 보내기 Cloud Firestore 데이터 모델 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장

    firebase.google.com

     

    따라서 컬렉션안에서 문서를 만들 수 있습니다. 이때 문서는 직접 추가할 수 있고 형식은 지정해 주지 않아도 

    코드에 따라 알아서 만들어 집니다. 또한 문서 아이디가 중복될 경우 데이터를 덮어 저장 합니다.

     

    테스트 채팅 구현

    실시간 채팅창

    'use client';
    
    import React, { useEffect, useState } from 'react';
    import { collection, onSnapshot } from 'firebase/firestore';
    import db from '../../../../fire-config';
    
    interface Chat {
      id: string;
      text: string;
    }
    
    /**
     * @description
     * 특정 채팅방의 채팅 목록을 실시간으로 가져옵니다.
     */
    function ChatCollection({ roomId }: { roomId: string }) {
      const [chatData, setChatData] = useState<Chat[]>([]);
    
      useEffect(() => {
        const messagesRef = collection(db, 'chats', roomId, 'messages');
        const unsubscribe = onSnapshot(messagesRef, (snapshot) => {
          const data = snapshot.docs.map((doc) => ({
            id: doc.id,
            ...(doc.data() as { text: string }),
          }));
          setChatData(data);
        });
    
        return () => unsubscribe();
      }, [roomId]);
    
      return (
        <div>
          {chatData.map((chat) => (
            <p key={chat.id}>{chat.text}</p>
          ))}
        </div>
      );
    }
    
    export default ChatCollection;

     

    채팅 구현

    'use client';
    
    import React, { useState } from 'react';
    import { addDoc, collection } from 'firebase/firestore';
    import db from '../../../../fire-config';
    
    /**
     * @description
     * 채팅 메시지를 특정 채팅방에 추가하는 입력 컴포넌트입니다.
     */
    function ChatInput({ roomId }: { roomId: string }) {
      const [message, setMessage] = useState('');
    
      async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
        e.preventDefault();
        if (!message.trim()) return;
    
        await addDoc(collection(db, 'chats', roomId, 'messages'), {
          text: message,
        });
        setMessage('');
      }
    
      return (
        <form onSubmit={onSubmit}>
          <input
            type="text"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
            placeholder="Type your message..."
          />
          <button type="submit">전송</button>
        </form>
      );
    }
    
    export default ChatInput;

     

    특정 방 입장 

    'use client';
    
    import ChatCollection from './chat-collection';
    import ChatInput from './chat-input';
    
    export default function ChatTest() {
      const roomId = 'userA_userB'; // 실제 유저 ID로 대체
    
      return (
        <div>
          <h1>Chat Room</h1>
          <ChatCollection roomId={roomId} />
          <ChatInput roomId={roomId} />
        </div>
      );
    }

     

    반응형