From 78b398a4e2788fd65e19a7a54eee369557b48f37 Mon Sep 17 00:00:00 2001 From: HeeDragoN1123 Date: Fri, 3 Nov 2023 11:27:36 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=88=98=EC=A0=95]=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=EB=A1=9C=20chat=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chats/chats.gateway.spec.ts | 28 ++-- src/chats/chats.gateway.ts | 186 ++++++++++----------- src/chats/chats.module.ts | 8 +- src/chats/chats.service.spec.ts | 28 ++-- src/chats/chats.service.ts | 243 +++++++--------------------- src/chats/models/chattings.model.ts | 40 ++--- src/chats/models/sockets.model.ts | 24 ++- 7 files changed, 194 insertions(+), 363 deletions(-) diff --git a/src/chats/chats.gateway.spec.ts b/src/chats/chats.gateway.spec.ts index cbf323e..a78f880 100644 --- a/src/chats/chats.gateway.spec.ts +++ b/src/chats/chats.gateway.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ChatsGateway } from './chats.gateway'; +// import { Test, TestingModule } from '@nestjs/testing'; +// import { ChatsGateway } from './chats.gateway'; -describe('ChatsGateway', () => { - let gateway: ChatsGateway; +// describe('ChatsGateway', () => { +// let gateway: ChatsGateway; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ChatsGateway], - }).compile(); +// beforeEach(async () => { +// const module: TestingModule = await Test.createTestingModule({ +// providers: [ChatsGateway], +// }).compile(); - gateway = module.get(ChatsGateway); - }); +// gateway = module.get(ChatsGateway); +// }); - it('should be defined', () => { - expect(gateway).toBeDefined(); - }); -}); +// it('should be defined', () => { +// expect(gateway).toBeDefined(); +// }); +// }); diff --git a/src/chats/chats.gateway.ts b/src/chats/chats.gateway.ts index 0bcda9a..bcbba25 100644 --- a/src/chats/chats.gateway.ts +++ b/src/chats/chats.gateway.ts @@ -1,4 +1,7 @@ +import { Chatting } from './models/chattings.model'; +import { InjectModel } from '@nestjs/mongoose'; import { Logger } from '@nestjs/common'; +import { Socket, Server } from 'socket.io'; import { ConnectedSocket, MessageBody, @@ -9,129 +12,102 @@ import { WebSocketGateway, WebSocketServer, } from '@nestjs/websockets'; -import { Socket, Server } from 'socket.io'; -import { ChatsService } from './chats.service'; -import { IMessage, IRoomRequest } from './interfaces/chats.interface'; -import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; -import { LocalDateTime } from '@js-joda/core'; -import { Chatting } from './models/chattings.model'; - +// import { IMessage } from './room.chats.interface'; +// import { LocalDateTime } from '@js-joda/core'; @WebSocketGateway({ namespace: 'chattings', - //WebSocket 서버가 모든 원격 호스트로부터의 연결을 허용 - cors: true, - allowEIO3: true, + cors: { + origin: [ + 'http://localhost:5173', + 'https://d2r603zvpf912o.cloudfront.net', + 'https://totobon.store', + 'https://local-mingle-fe.vercel.app', + ], + methods: ['GET', 'POST'], + credentials: true, + }, }) export class ChatsGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; - private logger: Logger = new Logger('AppGateway'); - - //의존성 주입 - @InjectModel(Chatting.name) private readonly chattingModel: Model; - constructor(private readonly chatsService: ChatsService) {} - - //유저가 연결 되었을때 기존은 socket: Socket - handleConnection(@ConnectedSocket() client: Socket) { - this.logger.log(`Client connected: ${client.id}`); + private logger = new Logger('chat'); + constructor( + @InjectModel(Chatting.name) private readonly chattingModel: Model, + @InjectModel(Socket.name) + private readonly socketModel: Model + ) { + this.logger.log('constructor'); } - - //유저가 연결해제 되었을때 로직 - handleDisconnect(@ConnectedSocket() client: Socket) { - this.logger.log(`disconnected: ${client.id}`); - this.chatsService.disconnectClient(client, this.server); + // WebSocketGateway가 초기화될 때 실행되는 메소드 + // WebSocketGateway가 초기화되면 로그를 출력합니다. + afterInit() { + this.logger.log('init'); + } + // 클라이언트와의 연결이 해제될 때 실행되는 메소드 + // 클라이언트 소켓 연결이 끊기면 roomChatsService의 handleDisconnect 메소드 호출 + async handleDisconnect(@ConnectedSocket() socket: Socket) { + const user = await this.socketModel.findOne({ id: socket.id }); + if (user) { + socket.broadcast.emit('disconnect_user', user.data); + await user.deleteOne(); + } + this.logger.log(`disconnected : ${socket.id} ${socket.nsp.name}`); + // this.logger.log(`disconnected : ${socket.id} ${socket.nsp.name}`); + // await this.roomChatsService.handleDisconnect(socket); + // this.logger.log(`disconnected : ${socket.id} ${socket.nsp.name}`); + } + // 클라이언트와의 연결이 수립될 때 실행되는 메소드 + // 클라이언트가 연결되면 해당 클라이언트의 ID와 네임스페이스 정보를 로그에 출력 + async handleConnection(@ConnectedSocket() socket: Socket) { + this.logger.log(`connected : ${socket.id} ${socket.nsp.name}`); + // await this.logger.log(`connected : ${socket.id} ${socket.nsp.name}`); + } + // 클라이언트가 'join_room' 메시지를 보낼 때 실행되는 메소드 + @SubscribeMessage('join_room') + async handleJoinRoom( + @MessageBody() + payload: { nickname: string; roomId: number; profileImg: string }, + @ConnectedSocket() socket: Socket + ) { + socket.join(String(payload.roomId)); + this.logger.log( + `Joined room: ${payload.roomId}, Nickname: ${payload.nickname}` + ); + this.server.to(String(payload.roomId)).emit('user_connected', payload); } - // 클라이언트가 'submit_chat' 메시지를 보낼 때 실행되는 메소드 (채팅을하고 그걸 다른유저에게 브로드캐스팅) + // 클라이언트가 'submit_chat' 메시지를 보낼 때 실행되는 메소드 @SubscribeMessage('submit_chat') async handleSubmitChat( - @MessageBody() { roomId, nickname, profileImg, message }: IMessage - ): Promise { - const localDateTime = LocalDateTime.now().plusHours(9); - const period = localDateTime.hour() < 12 ? 'AM' : 'PM'; - const formattedHour = localDateTime.hour() % 12 || 12; - const minute = localDateTime.minute().toString().padStart(2, '0'); - const messageData: IMessage = { - message, - time: `${formattedHour}:${minute} ${period}`, - nickname, - roomId, - profileImg, - }; + @MessageBody() + messageData: { + message: string; + nickname: string; + profileImg: string; + time: string; + roomId: number; + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @ConnectedSocket() _socket: Socket + ) { + this.logger.log( + `New chat in room ${messageData.roomId}: ${messageData.message}` + ); - //const socketObj = await this.socketModel.findOne({ Socket }); + const socketObj = await this.socketModel.findOne({ id: _socket.id }); // MongoDB에 채팅 메시지 저장 await this.chattingModel.create({ - // user: socketObj, // 메세지를보낸 소켓 정보 - nickname: messageData.nickname, //메세지를 보낸 사용자의 닉네임 - profileImg: messageData.profileImg, //메세지를 보낸 사용자의 프로필 이미지 - roomId: messageData.roomId, // 채팅이 속한 방의 ID - time: messageData.time, // 메세지를 송신한 시간 - chat: messageData.message, // 실제 채팅 메시지 내용. - created: new Date(), // 채팅 생성 시간 기록 + user: socketObj, + nickname: messageData.nickname, + profileImg: messageData.profileImg, + roomId: messageData.roomId, + time: messageData.time, + chat: messageData.message, // 수정: messageData.message를 사용하여 채팅 저장 }); - this.logger.log(messageData); this.server.to(String(messageData.roomId)).emit('new_chat', messageData); } - - // 일정기간(3일)이 지난 채팅을 db에서 삭제 - async deleteOldChats() { - // 72시간(3일) 이상 지난 채팅 삭제 - const chatScheduler = new Date(); - // chatScheduler.setDate(chatScheduler.getDate() - 3); //3일 - //chatScheduler.setHours(chatScheduler.getHours() - 72); // 72시간 - chatScheduler.setMinutes(chatScheduler.getMinutes() - 2); // 4320분(3일) 테스트 2분 - await this.chattingModel.deleteMany({ created: { $lt: chatScheduler } }); - } - - // 유저가 방에 참석할때 - @SubscribeMessage('join_room') - async handleJoinRoom( - @ConnectedSocket() client: Socket, - @MessageBody() { nickname, roomId, profileImg, userId }: IRoomRequest - ): Promise { - client.leave(client.id); - client.join(String(roomId)); - - // 이전 채팅 내용을 불러옵니다. - const chatHistory = await this.chatsService.getChatHistory(roomId); - - // 이전 채팅 내용과 함께 사용자 정보를 클라이언트에게 전송합니다. - client.emit('chat_history', chatHistory); - this.chatsService.joinRoom(client, this.server, { - nickname, - roomId, - profileImg, - userId, - }); - } - - // 유저가 방을 삭제할때 - @SubscribeMessage('remove_room') - handleRemoveRoom( - @ConnectedSocket() client: Socket, - @MessageBody() { roomId }: IRoomRequest - ): void { - this.chatsService.removeRoom(client, this.server, roomId); - } - - // 유저가 방을 떠날때 - @SubscribeMessage('leave_room') - handleLeaveRoom( - @ConnectedSocket() client: Socket, - @MessageBody() { roomId }: IRoomRequest - ): void { - client.leave(String(roomId)); - this.chatsService.leaveRoom(client, this.server, roomId); - } - - // WebSocketGateway가 초기화될 때 실행되는 메소드 - // WebSocketGateway가 초기화되면 로그를 출력합니다. - afterInit() { - this.logger.log('init'); - } -} // 끝 +} diff --git a/src/chats/chats.module.ts b/src/chats/chats.module.ts index bf726b6..29adc08 100644 --- a/src/chats/chats.module.ts +++ b/src/chats/chats.module.ts @@ -1,9 +1,9 @@ +import { SocketSchema, Socket as SocketModel } from './models/sockets.model'; import { Module } from '@nestjs/common'; import { ChatsGateway } from './chats.gateway'; -import { ChatsService } from './chats.service'; -import { Chatting, ChattingSchema } from './models/chattings.model'; import { MongooseModule } from '@nestjs/mongoose'; -import { SocketSchema, Socket as SocketModel } from './models/sockets.model'; +import { Chatting, ChattingSchema } from './models/chattings.model'; +import { RoomChatsService } from './chats.service'; @Module({ imports: [ @@ -12,6 +12,6 @@ import { SocketSchema, Socket as SocketModel } from './models/sockets.model'; { name: SocketModel.name, schema: SocketSchema }, ]), ], - providers: [ChatsGateway, ChatsService], + providers: [ChatsGateway, RoomChatsService], }) export class ChatsModule {} diff --git a/src/chats/chats.service.spec.ts b/src/chats/chats.service.spec.ts index bcbc316..2be4b5a 100644 --- a/src/chats/chats.service.spec.ts +++ b/src/chats/chats.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ChatsService } from './chats.service'; +// import { Test, TestingModule } from '@nestjs/testing'; +// import { ChatsService } from './chats.service'; -describe('ChatsService', () => { - let service: ChatsService; +// describe('ChatsService', () => { +// let service: ChatsService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ChatsService], - }).compile(); +// beforeEach(async () => { +// const module: TestingModule = await Test.createTestingModule({ +// providers: [ChatsService], +// }).compile(); - service = module.get(ChatsService); - }); +// service = module.get(ChatsService); +// }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +// it('should be defined', () => { +// expect(service).toBeDefined(); +// }); +// }); diff --git a/src/chats/chats.service.ts b/src/chats/chats.service.ts index 4d5c9bc..25dbb5f 100644 --- a/src/chats/chats.service.ts +++ b/src/chats/chats.service.ts @@ -1,213 +1,78 @@ -import { Injectable, Logger, NotFoundException } from '@nestjs/common'; -import { Server, Socket } from 'socket.io'; -import { Socket as SocketModel } from './models/sockets.model'; -import { Chatting, Chatting as ChattingModel } from './models/chattings.model'; +import { Injectable } from '@nestjs/common'; +import { Socket } from 'socket.io'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; -import { IRoomRequest } from './interfaces/chats.interface'; - +import { Chatting } from './models/chattings.model'; +import { Socket as SocketModel } from './models/sockets.model'; @Injectable() -export class ChatsService { - private logger = new Logger('chat'); +export class RoomChatsService { constructor( @InjectModel(SocketModel.name) private readonly socketModel: Model, - @InjectModel(ChattingModel.name) - private readonly ChattingModel: Model - ) { - this.logger.log('constructor'); - } - //소켓연결 해제 - async disconnectClient(client: Socket, server: Server) { - // 클라이언트 ID를 기반으로 사용자 정보 조회 - const user = await this.socketModel.findOne({ clientId: client.id }); - if (!user) { - return server.to(client.id).emit('NotFound_user', NotFoundException); - } - const roomId = user.roomId; - // 클라이언트 ID에 해당하는 사용자를 삭제 - await this.socketModel.findOneAndDelete({ clientId: client.id }).exec(); - // 방 정보 조회 - const room = await this.ChattingModel.findOne({ roomId }); - if (!room) { - return server.to(client.id).emit('NotFound_room', NotFoundException); + @InjectModel(Chatting.name) + private readonly chattingModel: Model + ) {} + // 클라이언트 소켓의 연결이 끊겼을 때 호출되는 메서드 + async handleDisconnect(socket: Socket) { + const user = await this.socketModel.findOne({ id: socket.id }); + if (user) { + // 연결 해제한 사용자를 MongoDB에서 삭제 + await this.socketModel.deleteOne({ _id: user._id }); } - // 유저리스트에서 클라이언트 ID 제거 - const nickname = room.userList[client.id]?.nickname; - delete room.userList[client.id]; - // 업데이트된 데이터를 저장 - await this.ChattingModel.findOneAndUpdate( - { roomId }, - { $set: { userList: room.userList } } - ); - - //await this.leaveRoomRequestToApiServer(roomId); - // server - // .to(String(roomId)) - // .emit('disconnect_user', `${nickname}의 연결이 종료되었습니다.`); - this.emitEventForUserList(client, server, roomId, nickname, 'leave_user'); - this.logger.log(`disconnected: ${client.id}`); } - - // async leaveRoomRequestToApiServer(uuid: string): Promise { - // const headers = { - // 'socket-secret-key': process.env.SOCKET_SECRET_KEY ?? '', - // }; - // await axios.post(`${baseURL}/room/socket/leave/${uuid}`, undefined, { - // headers, - // }); - // } - - //유저가 방에 참여 - async joinRoom(client: Socket, server: Server, iRoomRequest: IRoomRequest) { - const { roomId, nickname, userId } = iRoomRequest; - //유저를 socketModel 에서 찾습니다. - const isExist = await this.socketModel.findOne({ userId: userId }); - //만약 유저가 존재하면 클라이언트에게 에러메세지 - if (isExist) { - //유저가 있으면 방을 나가는 로직 - //await this.leaveRoomRequestToApiServer(roomId); - return client.emit('joinRoom_Error', '이미 방에 접속한 사용자 입니다.'); - } - client.leave(client.id); - client.join(String(roomId)); - const roomData = await this.ChattingModel.findOne({ roomId }); - if (!roomData) { - await this.createRoom(client, iRoomRequest); + // 채팅방에 참여하는 메서드 + async handleJoinRoom( + payload: { nickname: string; roomId: number; profileImg: string }, + socket: Socket + ) { + const data = await this.socketModel.findOne({ id: socket.id }); + if (!data) { + // 사용자가 채팅방에 처음 참여할 때, 채팅방 정보를 생성 + await this.createRoom(socket, payload); } else { - await this.updateRoom(client, roomData, iRoomRequest); + // 이미 채팅방에 참여한 사용자인 경우, 사용자 정보 업데이트 + await this.updateRoom(socket, data.roomId, payload); } - server - .to(String(roomId)) - .emit('new-user', `${nickname} 유저가 채팅방에 참가하였습니다.`); - this.emitEventForUserList(client, server, roomId, nickname, 'new-user'); + } + // 채팅 메시지를 저장하는 메서드 + async handleSubmitChat(chat: string, socket: Socket) { + const socketObj = await this.socketModel.findOne({ id: socket.id }); + // MongoDB에 채팅 메시지를 저장합니다. + await this.chattingModel.create({ + user: socketObj, + chat, + roomId: socketObj.roomId, + nickname: socketObj.nickname, + profileImg: socketObj.profileImg, + time: socketObj.time, + }); } - //채팅방을 만듬 + // 채팅방 정보를 생성하는 메서드 async createRoom( - client: Socket, - { nickname, roomId, profileImg, userId }: IRoomRequest + socket: Socket, + payload: { nickname: string; roomId: number; profileImg: string } ) { - const newRoom = { roomId: roomId, user: client.id, userList: {} }; - newRoom.userList = { [client.id]: { nickname, profileImg } }; - await this.ChattingModel.create(newRoom); const newUser = { - clientId: client.id, - roomId: roomId, - nickname: nickname, - userId: userId, + id: socket.id, + nickname: payload.nickname, + roomId: payload.roomId, }; await this.socketModel.create(newUser); } - //채팅방을 참여하는 사용자 정보 업데이트 + // 채팅방 정보를 업데이트하는 메서드 async updateRoom( - client: Socket, - roomData: any, - { roomId, nickname, profileImg, userId }: IRoomRequest - ) { - // 새로운 사용자 정보를 준비합니다. - const newUser = { - clientId: client.id, - roomId, - nickname, - userId, - }; - //newUser를 socketModel을 사용하여 db에 저장 - await this.socketModel.create(newUser); - const findEventRoom = roomData; - //클라이언트 키를 사용해서 nickname, profileImg를 업데이트 - findEventRoom.userList[client.id] = { nickname, profileImg }; - //findOneAndUpdate 몽고디비에서 roomId와 일치하는 채팅방을 찾아서 유저리스트를 업데이트하여 저장 - await this.ChattingModel.findOneAndUpdate( - { roomId }, - // $set 연산자로 userList 를 업데이트 - { $set: { userList: findEventRoom.userList } } - ); - } - - // 사용자 목록 업데이트 이벤트 전송 - async emitEventForUserList( - client: Socket, - server: Server, - roomId: number, // 채팅방의 고유 식별자 - nickname: string, // 사용자의 닉네임 - userEvent: string // 전송할 이벤트의 이름 (예: 'new-user' 또는 'leave-user') + socket: Socket, + roomId: number, + payload: { nickname: string; profileImg: string } ) { - // 주어진 roomId로 채팅방 정보 조회 - const data = await this.ChattingModel.findOne({ roomId }); - - // 채팅방이 존재하지 않으면 클라이언트에게 'NotFoundException' 에러 메시지를 전송합니다. - if (!data) { - return server.to(client.id).emit('NotFound_data', NotFoundException); + const socketObj = await this.socketModel.findOne({ id: socket.id }); + if (socketObj && socketObj.roomId === roomId) { + // 이미 채팅방에 참여한 사용자인 경우, 사용자 정보를 업데이트 + socketObj.nickname = payload.nickname; + socketObj.profileImg = payload.profileImg; + await socketObj.save(); } - - // 채팅방에 있는 사용자 목록을 가져옵니다. - const userListObj = data['userList']; - - // 사용자 목록을 배열 형태로 변환합니다. - const userListArr = Object.values(userListObj); - - // 채팅방에 속한 모든 클라이언트에게 사용자 목록 업데이트 이벤트를 전송합니다. - server.to(String(roomId)).emit(userEvent, { nickname, userListArr }); - } - - //채팅방을 삭제 (클라이언트가 모임을 삭제 할때 이 매서드를 호출하면 채팅창을 삭제합니다.) - async removeRoom(client: Socket, server: Server, roomId: number) { - // 주어진 roomId 채팅방을 찾습니다. - const data = await this.ChattingModel.findOne({ roomId }).exec(); - - // 만약 채팅방이 존재하지 않는다면, 클라이언트에게 'NotFoundException' 에러를 전송합니다. - if (!data) { - return server.to(client.id).emit('NotFound_data', NotFoundException); - } - - // 채팅방이 존재하면 삭제 작업을 수행합니다. - await this.deleteByRoomId(roomId); - } - - async deleteByRoomId(roomId: number): Promise { - const result = await this.ChattingModel.findOneAndDelete({ roomId }).exec(); - return result; - } - - //방을 떠날때 - async leaveRoom(client: Socket, server: Server, roomId: number) { - // 주어진 roomId로 채팅방 정보 조회 - const room = await this.ChattingModel.findOne({ roomId }); - // 채팅방이 존재하지 않으면 클라이언트에게 'NotFoundException' 에러 메시지를 전송합니다. - if (!room) { - return server.to(client.id).emit('NotFound_room', NotFoundException); - } - const userId = room.userList[client.id]; - const nickname = room.userList[client.id]?.nickname; - - // 사용자 ID가 존재하면 사용자를 채팅방에서 제거 - if (userId) { - delete room.userList[client.id]; - } else { - // 사용자 ID가 존재하지 않으면 클라이언트에게 'NotFoundException' 에러 메시지를 전송합니다. - return server.to(client.id).emit('NotFound_userId', NotFoundException); - } - // 채팅방 업데이트: 사용자 목록 업데이트 - await this.ChattingModel.findOneAndUpdate( - { roomId }, - { $set: { userList: room.userList } } - ); - // 사용자 데이터 삭제 - await this.socketModel.deleteOne({ clientId: client.id }); - - // 나간 사용자에게 나간 것을 알리기 위한 메시지를 전송합니다. - server - .to(String(roomId)) - .emit('left_user', `${nickname} 유저가 채팅방을 떠났습니다.`); - // 유저리스트 보내주기 - this.emitEventForUserList(client, server, roomId, nickname, 'leave-user'); - } - - // roomId에 해당하는 이전 채팅 내용을 데이터베이스에서 불러옵니다. - async getChatHistory(roomId: number) { - const chatHistory = await this.ChattingModel.find({ roomId }).exec(); - return chatHistory; } } diff --git a/src/chats/models/chattings.model.ts b/src/chats/models/chattings.model.ts index 9a741f9..7741ebd 100644 --- a/src/chats/models/chattings.model.ts +++ b/src/chats/models/chattings.model.ts @@ -1,40 +1,34 @@ -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { IsNotEmpty, IsString } from 'class-validator'; -import { Document, SchemaOptions } from 'mongoose'; -// import { Socket as SocketModel } from './sockets.model'; +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { Document, SchemaOptions, Types } from 'mongoose'; +import { Socket as SocketModel } from './sockets.model'; const options: SchemaOptions = { - collection: 'chattings', + collection: 'chattings', // 데이터 베이스 이름 timestamps: true, }; @Schema(options) export class Chatting extends Document { - // @Prop({ - // type: { - // _id: { type: Types.ObjectId, required: true, ref: 'sockets' }, - // userId: { type: Number }, - // nickname: { type: String, required: true }, - // profileImg: { type: String }, // 추가: 프로필 이미지 - // roomId: { type: Number }, // 추가: 방 ID 또는 방 식별자 - // }, - // }) - // @IsNotEmpty() - // user: SocketModel; // 이코드는 필요없을 수도 있습니다. 기존코드때문에 임시로 넣음 + @Prop({ + type: { + _id: { type: Types.ObjectId, required: true, ref: 'sockets' }, + id: { type: String }, + nickname: { type: String, required: true }, + profileImg: { type: String }, // 추가: 프로필 이미지 + roomId: { type: Number }, // 추가: 방 ID 또는 방 식별자 + time: { type: Date }, + }, + }) + @IsNotEmpty() + user: SocketModel; - //모임방 id값 EventId를 roomId로 변환하여 쓰고 있음 @Prop({ required: true, - ref: 'Event', }) @IsNotEmpty() @IsString() - roomId: number; - - @Prop({ type: Object, required: true }) - @IsNotEmpty() - @IsString() // userList의 타입을 명시적으로 지정 - userList: object; // 유저 리스트에는 nickname , profileImg , userId 가 + chat: string; } export const ChattingSchema = SchemaFactory.createForClass(Chatting); diff --git a/src/chats/models/sockets.model.ts b/src/chats/models/sockets.model.ts index ca6bce8..b03d81e 100644 --- a/src/chats/models/sockets.model.ts +++ b/src/chats/models/sockets.model.ts @@ -1,6 +1,6 @@ -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { IsNotEmpty, IsString } from 'class-validator'; -import { SchemaOptions, Types, Document } from 'mongoose'; +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { Document, SchemaOptions, Types } from 'mongoose'; // Types 추가 const options: SchemaOptions = { id: false, @@ -11,22 +11,12 @@ const options: SchemaOptions = { @Schema(options) export class Socket extends Document { @Prop({ + unique: true, required: true, }) @IsNotEmpty() @IsString() - clientId: string; //소켓을 연결했을때 생기는 Id - - @Prop({ type: Types.ObjectId, ref: 'Event' }) // roomId 추가 - @IsNotEmpty() - roomId: number; // EventId를 roomId로 참조하여 사용 - - @Prop({ - required: true, - }) - @IsNotEmpty() - @IsString() - userId: string; //사용자 Id + id: string; @Prop({ required: true, @@ -35,8 +25,14 @@ export class Socket extends Document { @IsString() nickname: string; + @Prop({ type: Types.ObjectId, ref: 'Event' }) // roomId 추가 + roomId: number; // 이벤트 ID를 저장 + @Prop() profileImg: string; // profileImg 필드 추가 + + @Prop() + time: Date; // profileImg 필드 추가 } export const SocketSchema = SchemaFactory.createForClass(Socket);