|
1 | | -import { useEffect, useRef, useState, ChangeEvent, KeyboardEvent } from "react"; |
| 1 | +import { |
| 2 | + useEffect, |
| 3 | + useRef, |
| 4 | + useState, |
| 5 | + useCallback, |
| 6 | + ChangeEvent, |
| 7 | + KeyboardEvent |
| 8 | +} from "react"; |
2 | 9 | import { useLocation, useNavigate } from "react-router-dom"; |
3 | 10 | import { Helmet } from "react-helmet"; |
4 | 11 | import { authInstance } from "@/api/axios"; |
@@ -67,6 +74,65 @@ const Chat = () => { |
67 | 74 |
|
68 | 75 | const isTopicChat = mode === "topicChat"; |
69 | 76 |
|
| 77 | + const handleWebSocketMessage = useCallback( |
| 78 | + (wsMessage: WebSocketMessage) => { |
| 79 | + if (wsMessage.type === "ERROR") { |
| 80 | + // 에러 메시지 처리 |
| 81 | + const errorMessage: Message = { |
| 82 | + role: "assistant", |
| 83 | + content: wsMessage.message, |
| 84 | + messageType: "system" |
| 85 | + }; |
| 86 | + |
| 87 | + // 중복 시스템 메시지 방지 |
| 88 | + setMessages((prev) => { |
| 89 | + const lastMessage = prev[prev.length - 1]; |
| 90 | + if ( |
| 91 | + lastMessage?.messageType === "system" && |
| 92 | + lastMessage.content === wsMessage.message |
| 93 | + ) { |
| 94 | + return prev; |
| 95 | + } |
| 96 | + return [...prev, errorMessage]; |
| 97 | + }); |
| 98 | + } else if (wsMessage.type === "NOTICE") { |
| 99 | + // 시스템 알림 메시지 처리 (입장/퇴장) |
| 100 | + const systemMessage: Message = { |
| 101 | + role: "assistant", |
| 102 | + content: wsMessage.message, |
| 103 | + messageType: "system" |
| 104 | + }; |
| 105 | + |
| 106 | + // 중복 시스템 메시지 방지 |
| 107 | + setMessages((prev) => { |
| 108 | + const lastMessage = prev[prev.length - 1]; |
| 109 | + if ( |
| 110 | + lastMessage?.messageType === "system" && |
| 111 | + lastMessage.content === wsMessage.message |
| 112 | + ) { |
| 113 | + return prev; |
| 114 | + } |
| 115 | + return [...prev, systemMessage]; |
| 116 | + }); |
| 117 | + } else if ( |
| 118 | + wsMessage.type === null && |
| 119 | + wsMessage.nickname && |
| 120 | + wsMessage.message |
| 121 | + ) { |
| 122 | + // 일반 채팅 메시지 처리 |
| 123 | + const newMessage: Message = { |
| 124 | + role: wsMessage.nickname === nickname ? "user" : "assistant", |
| 125 | + content: wsMessage.message, |
| 126 | + nickname: wsMessage.nickname, |
| 127 | + mbti: wsMessage.mbti || undefined, |
| 128 | + messageType: "text" |
| 129 | + }; |
| 130 | + setMessages((prev) => [...prev, newMessage]); |
| 131 | + } |
| 132 | + }, |
| 133 | + [nickname] |
| 134 | + ); |
| 135 | + |
70 | 136 | useEffect(() => { |
71 | 137 | if (!isTopicChat) { |
72 | 138 | return; |
@@ -111,9 +177,6 @@ const Chat = () => { |
111 | 177 | } |
112 | 178 |
|
113 | 179 | // WebSocket 연결 시도 |
114 | | - const wsUrl = |
115 | | - import.meta.env.VITE_WEBSOCKET_URL || "ws://localhost:8080"; |
116 | | - |
117 | 180 | try { |
118 | 181 | const connected = await websocketService.connect({ |
119 | 182 | nickname, |
@@ -166,7 +229,14 @@ const Chat = () => { |
166 | 229 | websocketService.disconnect(); |
167 | 230 | } |
168 | 231 | }; |
169 | | - }, [isTopicChat, openChatId, nickname, mbti, navigate]); |
| 232 | + }, [ |
| 233 | + isTopicChat, |
| 234 | + openChatId, |
| 235 | + nickname, |
| 236 | + mbti, |
| 237 | + navigate, |
| 238 | + handleWebSocketMessage |
| 239 | + ]); |
170 | 240 |
|
171 | 241 | useEffect(() => { |
172 | 242 | const fetchMessages = async () => { |
@@ -217,62 +287,6 @@ const Chat = () => { |
217 | 287 | setIsOpen(nextState); |
218 | 288 | }; |
219 | 289 |
|
220 | | - const handleWebSocketMessage = (wsMessage: WebSocketMessage) => { |
221 | | - if (wsMessage.type === "ERROR") { |
222 | | - // 에러 메시지 처리 |
223 | | - const errorMessage: Message = { |
224 | | - role: "assistant", |
225 | | - content: wsMessage.message, |
226 | | - messageType: "system" |
227 | | - }; |
228 | | - |
229 | | - // 중복 시스템 메시지 방지 |
230 | | - setMessages((prev) => { |
231 | | - const lastMessage = prev[prev.length - 1]; |
232 | | - if ( |
233 | | - lastMessage?.messageType === "system" && |
234 | | - lastMessage.content === wsMessage.message |
235 | | - ) { |
236 | | - return prev; |
237 | | - } |
238 | | - return [...prev, errorMessage]; |
239 | | - }); |
240 | | - } else if (wsMessage.type === "NOTICE") { |
241 | | - // 시스템 알림 메시지 처리 (입장/퇴장) |
242 | | - const systemMessage: Message = { |
243 | | - role: "assistant", |
244 | | - content: wsMessage.message, |
245 | | - messageType: "system" |
246 | | - }; |
247 | | - |
248 | | - // 중복 시스템 메시지 방지 |
249 | | - setMessages((prev) => { |
250 | | - const lastMessage = prev[prev.length - 1]; |
251 | | - if ( |
252 | | - lastMessage?.messageType === "system" && |
253 | | - lastMessage.content === wsMessage.message |
254 | | - ) { |
255 | | - return prev; |
256 | | - } |
257 | | - return [...prev, systemMessage]; |
258 | | - }); |
259 | | - } else if ( |
260 | | - wsMessage.type === null && |
261 | | - wsMessage.nickname && |
262 | | - wsMessage.message |
263 | | - ) { |
264 | | - // 일반 채팅 메시지 처리 |
265 | | - const newMessage: Message = { |
266 | | - role: wsMessage.nickname === nickname ? "user" : "assistant", |
267 | | - content: wsMessage.message, |
268 | | - nickname: wsMessage.nickname, |
269 | | - mbti: wsMessage.mbti || undefined, |
270 | | - messageType: "text" |
271 | | - }; |
272 | | - setMessages((prev) => [...prev, newMessage]); |
273 | | - } |
274 | | - }; |
275 | | - |
276 | 290 | const handleSend = async (messageToSend: string) => { |
277 | 291 | if (!messageToSend.trim()) return; |
278 | 292 |
|
|
0 commit comments