그룹채팅 - 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`);
}
}
(설명 : 주석참고)