그룹채팅 - Part1 채팅방 생성

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

새로운 그룹 채팅방을 만드는 방법에 대해 설명하겠습니다.


 

데이터베이스 스키마

 

chatrooms 테이블

model chatrooms {
  id           Int      @id @default(autoincrement())
  name         String
  tags         String
  image_url    String?
  max_members  Int
  created_at   DateTime @default(now())
  updated_at   DateTime @updatedAt
  owner_id     Int

  user         users    @relation(fields: [owner_id], references: [user_id], onDelete: Cascade, onUpdate: Cascade)

  @@index([id])
}

- 채팅방의 이름(name), 태그(tags), 이미지 URL(image_url), 최대 멤버 수(max_members), 생성 시간(created_at), 업데이트 시간(updated_at), 방장 ID(owner_id)를 저장합니다.
- owner_id는 users 테이블과 관계를 맺고 있습니다.

 


 

프론트엔드

 

채팅방생성 컴포넌트

import { useState } from "react"; 

const CreateChatroom = () => {
  // 상태 변수를 선언합니다.
  const [name, setName] = useState(""); // 채팅방 이름을 관리하는 상태 변수
  const [tags, setTags] = useState(""); // 채팅방 태그를 관리하는 상태 변수
  const [maxMembers, setMaxMembers] = useState(10); // 최대 멤버 수를 관리하는 상태 변수
  const [image, setImage] = useState(null); // 이미지 파일을 관리하는 상태 변수

  // 폼 제출 시 호출되는 함수입니다.
  const handleSubmit = async (e) => {
    e.preventDefault(); // 기본 폼 제출 동작을 막습니다.

    // 폼 데이터를 생성합니다.
    const formData = new FormData();
    formData.append("name", name); // 이름을 폼 데이터에 추가합니다.
    formData.append("tags", tags); // 태그를 폼 데이터에 추가합니다.
    formData.append("max_members", maxMembers); // 최대 멤버 수를 폼 데이터에 추가합니다.
    formData.append("image", image); // 이미지를 폼 데이터에 추가합니다.

    // 서버에 POST 요청을 보냅니다.
    const res = await fetch("/api/chatrooms", {
      method: "POST",
      body: formData, // 폼 데이터를 요청 본문에 포함합니다.
    });

    // 응답이 성공적인 경우
    if (res.ok) {
      const data = await res.json(); // 응답 데이터를 JSON으로 변환합니다.
      console.log("Chatroom created:", data); // 생성된 채팅방 정보를 콘솔에 출력합니다.
    } else {
      // 응답이 실패한 경우
      console.error("Failed to create chatroom"); // 에러 메시지를 콘솔에 출력합니다.
    }
  };

  return (
    <form onSubmit={handleSubmit}> {/* 폼 제출 시 handleSubmit 함수를 호출합니다. */}
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)} // 입력값이 변경될 때 name 상태를 업데이트합니다.
        placeholder="Chatroom Name" // 입력 필드의 자리 표시자입니다.
      />
      <input
        type="text"
        value={tags}
        onChange={(e) => setTags(e.target.value)} // 입력값이 변경될 때 tags 상태를 업데이트합니다.
        placeholder="Tags" // 입력 필드의 자리 표시자입니다.
      />
      <input
        type="number"
        value={maxMembers}
        onChange={(e) => setMaxMembers(e.target.value)} // 입력값이 변경될 때 maxMembers 상태를 업데이트합니다.
        placeholder="Max Members" // 입력 필드의 자리 표시자입니다.
      />
      <input
        type="file"
        onChange={(e) => setImage(e.target.files[0])} // 파일이 선택될 때 image 상태를 업데이트합니다.
      />
      <button type="submit">Create Chatroom</button> {/* 폼 제출 버튼입니다. */}
    </form>
  );
};

export default CreateChatroom;

(설명 : 주석참고)

 


 

<백엔드>

1. Multer 실행

const runMiddleware = (
  req: NextApiRequest,
  res: NextApiResponse,
  fn: Function
) => {
  return new Promise((resolve, reject) => {
    fn(req, res, (result: any) => {
      if (result instanceof Error) {
        return reject(result); // 미들웨어 실행 중 오류가 발생하면 reject하여 에러를 처리합니다.
      }
      return resolve(result); // 미들웨어 함수의 실행이 완료될 때까지 기다리게 합니다.
    });
  });
};

(설명 : 주석참고)

 

2. 채팅방 생성 핸들러

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method === "POST") {
    try {
      // Multer 미들웨어 실행
      await runMiddleware(req, res, upload.single("image"));

      // 요청 본문에서 필요한 데이터를 추출합니다.
      const { name, tags, max_members, owner_id, image } = req.body;

      // 이미지 파일이 업로드된 경우 해당 파일의 경로를 설정합니다.
      const imageUrl = req.file ? `/uploads/${req.file.filename}` : image;

      // Prisma Client를 사용하여 chatrooms 테이블에 새로운 채팅방 레코드를 생성합니다.
      const chatroom = await prisma.chatrooms.create({
        data: {
          name, // 채팅방 이름 설정
          tags, // 채팅방 태그 설정
          image_url: imageUrl, // 이미지 URL 설정
          max_members: Number(max_members), // 최대 멤버 수 설정
          owner_id: Number(owner_id), // 방장 ID 설정
        },
      });

      // 채팅방 생성이 성공적으로 완료되면 201 상태 코드와 생성된 채팅방 데이터를 클라이언트에 응답으로 보냅니다.
      res.status(201).json(chatroom);
    } catch (error) {
      console.log(error);
      // 예외가 발생할 경우 에러를 로그로 출력하고, 클라이언트에 500 상태 코드와 함께 에러 메시지를 응답으로 보냅니다.
      res.status(500).json({ message: "Internal server error" });
    }
  } else {
    // POST 요청 이외의 요청이 들어올 경우, 허용된 메서드를 명시하고 405 상태 코드와 함께 응답을 종료합니다.
    res.setHeader("Allow", ["POST"]);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

(설명 : 주석참고)