그룹채팅 - Part2 채팅방 입장 (처음 참여하는 채팅방, 이미 참여중인 채팅방)

Project Diary/Next.js + Prisma + MariaDB (KiloFlow)

사용자가 새로운 채팅방에 입장하거나 이미 참여 중인 채팅방에 다시 입장하는 기능을 구현하는 방법에 대해 알아보겠습니다. 이 기능은 사용자가 채팅방에 참여할 수 있도록 하며, 이미 참여 중인 채팅방이면 바로 입장하고 처음 참여하는 채팅방이면 모달을 띄워 참여 확인을 받습니다.


 

데이터베이스 스키마

 

chatroom_members 테이블

model chatroom_members {
  id          Int      @id @default(autoincrement())
  chatroom_id Int
  user_id     Int
  joined_at   DateTime @default(now())

  chatroom    chatrooms @relation(fields: [chatroom_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
  user        users     @relation(fields: [user_id], references: [user_id], onDelete: Cascade, onUpdate: Cascade)

  @@index([chatroom_id])
  @@index([user_id])
  @@unique([chatroom_id, user_id])
}
  • chatroom필드
    -  chatroom_id 필드는 chatrooms 모델의 id 필드를 참조합니다,
    - 'onDelete: Cascade'를 통해 해당 채팅방이 삭제될 때 연관된 회원 정보도 함께 삭제됩니다.
  • user필드
    - user_id 필드는 users 모델의 id 필드를 참조합니다.
    - ' onDelete: Cascade'를 통해 해당 사용자가 삭제될 때 연관된 회원 정보도 함께 삭제됩니다.

 

프론트엔드

 

사용자가 채팅방에 참여하는 기능

1. 채팅방 클릭 이벤트 핸들러

const handleChatroomClick = async (chatroom: Chatroom) => {
  // 사용자가 이미 참여 중인 채팅방인지 확인하기 위해 서버에 요청을 보냅니다.
  const res = await fetch(`/api/community/joined?currentUser=${currentUser.user_id}`);
  // 서버에서 응답받은 데이터를 JSON 형식으로 변환합니다.
  const joinedChatrooms = await res.json();

  // 현재 클릭한 채팅방이 사용자가 이미 참여 중인 채팅방인지 확인합니다.
  const isAlreadyJoined = joinedChatrooms.some((cr: any) => cr.chatroom_id === chatroom.id);

  if (isAlreadyJoined) {
    // 이미 참여 중인 채팅방이면 해당 채팅방으로 이동합니다.
    router.push(`/community/chat/${chatroom.id}`);
  } else {
    // 처음 참여하는 채팅방이면 모달을 띄웁니다.
    setSelectedChatroom(chatroom);
  }
};
  • if (isAlreadyJoined) { router.push(`/community/chat/${chatroom.id}`);}
    현재 클릭한 채팅방이 사용자가 이미 참여 중인 채팅방인지 확인합니다.
  • else { setSelectedChatroom(chatroom); }
    처음 참여하는 채팅방이면 selectedChatroom 상태를 클릭한 채팅방으로 설정하여 모달을 띄웁니다.

2. 모달 표시

{selectedChatroom && (
  <CommunityModal
    chatroom={selectedChatroom} // 선택된 채팅방 정보를 모달 컴포넌트에 전달합니다.
    currentUser={currentUser} // 현재 사용자 정보를 모달 컴포넌트에 전달합니다.
    onHide={() => setSelectedChatroom(null)} 
    // 모달을 닫을 때 selectedChatroom 상태를 null로 설정하여 모달을 숨깁니다.
  />
)}
  • {selectedChatroom && (...)}
    selectedChatroom 상태가 설정되어 있을 때만 모달을 표시합니다.
  • onHide={() => setSelectedChatroom(null)}
    모달을 닫을 때 selectedChatroom 상태를 null로 설정하여 모달을 숨깁니다.

 

백엔드

 

1. 사용자가 채팅방에 참여

채팅방 참여 API 엔드포인트

import { NextApiRequest, NextApiResponse } from "next";
import prisma from "../../../lib/prisma";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "POST") {
    const { chatroom_id, user_id } = req.body;

    // Prisma Client를 사용하여 chatroom_members 테이블에 새로운 레코드를 생성합니다.
    const chatroomMember = await prisma.chatroom_members.create({
      data: { chatroom_id: Number(chatroom_id), user_id: Number(user_id) },
    });

    // 생성된 chatroomMember 데이터를 응답으로 반환합니다.
    res.status(201).json(chatroomMember);
  } else {
    // 허용되지 않은 메서드에 대해 응답
    res.setHeader("Allow", ["POST"]);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

(설명 : 주석참고)

 

2. 사용자가 이미 참여 중인 채팅방 확인

참여 중인 채팅방 확인 API 엔드포인트

import { NextApiRequest, NextApiResponse } from "next";
import prisma from "../../../lib/prisma";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { currentUser } = req.query;

  if (req.method === "GET") {
    // Prisma Client를 사용하여 사용자가 참여 중인 모든 채팅방 ID를 가져옵니다.
    const chatrooms = await prisma.chatroom_members.findMany({
      where: { user_id: Number(currentUser) },
      select: { chatroom_id: true },
    });

    // 참여 중인 채팅방 ID 리스트를 클라이언트에 응답으로 반환합니다.
    res.status(200).json(chatrooms);
  } else {
    // 허용되지 않은 메서드에 대해 응답
    res.setHeader("Allow", ["GET"]);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

(설명 : 주석참고)

 


처음 참여하는 채팅방

 

참여중인 채팅방 입장