그룹채팅 - Part6 방장의 권한(2) - 강퇴

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

방장이 특정 사용자를 강제로 퇴장시키는 기능에 대해서 설명하겠습니다.


 

프론트엔드

 

1. 참여 사용자 목록 가져오기

특정 채팅방의 사용자 목록을 가져오는 API를 호출하여 참여 사용자 목록을 상태에 저장합니다.

const fetchParticipatingUsers = async () => {
  const res = await fetch(`/api/community/current-chatroom-info?roomId=${roomId}&action=users`);
  const data = await res.json();
  setParticipatingUsers(data); // 참여 사용자 목록을 상태에 저장
};

 

2. 방장 여부 확인

현재 사용자가 방장인지 확인하기 위해 채팅방 정보를 가져오는 API를 호출합니다.

const checkIfOwner = async () => {
  const res = await fetch(`/api/community/current-chatroom-info?roomId=${roomId}&action=info`);
  const data = await res.json();
  if (currentUser && data.owner_id === currentUser.user_id) {
    setIsOwner(true); // 현재 사용자가 방장인 경우 isOwner 상태를 true로 설정
  }
  setChatroomInfo(data); // 채팅방 정보를 상태에 저장
};

 

3. 사용자 강퇴 기능 구현

강퇴 요청이 성공하면 최신 사용자 목록을 가져옵니다.

const kickUser = async (userId: number, userNickname: string) => {
  if (confirm(`${userNickname}님을 강제로 퇴장시키겠습니까?`)) {
    const res = await fetch(`/api/community/join`, {
      method: "DELETE",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        chatroom_id: roomId,
        user_id: userId,
        action: "kick",
      }),
    });

    if (res.ok) {
      fetchParticipatingUsers(); // 강퇴 후 최신 사용자 목록을 가져옴
      socket.emit("kick_room", {
        roomId,
        user: { userId: userId, nickname: userNickname },
      }); // 다른 사용자들에게 강퇴 메시지를 전송
      router.push("/community/list"); // 강퇴 후 채팅방 목록으로 이동
    } else {
      alert("사용자 강퇴에 실패했습니다."); // 강퇴 요청이 실패한 경우
    }
  }
};
  • kickUser
    - 강퇴 확인 후 API 요청을 보내고, 성공 시 최신 사용자 목록을 가져옵니다.
    - 다른 사용자들에게 강퇴 메시지를 전송하고, 채팅방 목록으로 이동합니다.

4. 사용자 목록 렌더링 및 강퇴 버튼 추가

참여 중인 사용자 목록을 렌더링하고, 방장인 경우 강퇴 버튼을 표시합니다.

{participatingUsers.map((user) => (
  <div className="user__item" key={user.user_id}>
    <Image
      src={user.profile_image}
      alt="유저프로필"
      width={50}
      height={50}
    /> {/* 사용자 프로필 이미지를 보여줌 */}
    <span>{user.nickname}</span> {/* 사용자 닉네임을 보여줌 */}
    {user.user_id === chatroomInfo?.owner_id && <span>(방장)</span>} {/* 방장을 표시 */}
    {isOwner && user.user_id !== chatroomInfo?.owner_id && (
      <button
        className="kick"
        onClick={() => kickUser(user.user_id, user.nickname)}
      >
        강퇴
      </button> {/* 방장일 경우, 다른 사용자에게 강퇴 버튼을 보여줌 */}
    )}
  </div>
))}

 


 

백엔드

 

1. 사용자 강퇴 API 엔드포인트

// pages/api/community/join.ts

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

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

    if (action === "kick") {
      try {
        // 사용자를 채팅방에서 강퇴
        await prisma.chatroom_members.deleteMany({
          where: {
            chatroom_id: Number(chatroom_id),
            user_id: Number(user_id),
          },
        });
        res.status(200).json({ message: "User kicked successfully" }); // 강퇴 성공 시 응답
      } catch (error) {
        res.status(500).json({ error: "Error kicking user" }); // 오류 발생 시 응답
      }
    } else {
      res.status(400).json({ message: "Invalid action" }); // 유효하지 않은 action
    }
  } else {
    res.setHeader("Allow", ["DELETE"]); // 허용되지 않는 메서드에 대한 응답 설정
    res.status(405).end(`Method ${req.method} Not Allowed`); // 405 상태 코드 응답
  }
}