Skip to content

Commit 5c822e4

Browse files
authored
Merge pull request #67 from CommitField/main
Feat: 채팅백엔드 연결
2 parents 565724c + b0c898a commit 5c822e4

File tree

3 files changed

+100
-111
lines changed

3 files changed

+100
-111
lines changed

src/components/ChatRoom.jsx

Lines changed: 56 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import ChatService from '../services/ChatService';
44
import webSocketService from '../services/WebSocketService';
55
import './ChatStyles.css';
66

7+
// Define API_BACKEND_URL
8+
const API_BACKEND_URL = 'http://localhost:8090';
9+
710
const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
811
const { roomId: paramRoomId } = useParams();
912
const roomId = propRoomId || paramRoomId; // 속성으로 받은 값 우선, 없으면 URL 파라미터 사용
@@ -153,79 +156,59 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
153156

154157
if (!newMessage.trim()) return;
155158

156-
// 먼저 입력 필드 초기화 (UX 향상)
157159
const messageText = newMessage;
158160
setNewMessage('');
159161

160-
// 새 메시지 객체 생성
161-
const newMsg = {
162-
chatMsgId: `local-${Date.now()}`, // 로컬 메시지 ID
163-
userId: userInfo.id,
164-
nickname: userInfo.nickname,
165-
message: messageText,
166-
sendAt: new Date().toISOString()
167-
};
162+
try {
163+
// 현재 사용자 정보 가져오기
164+
const userResponse = await fetch(`${API_BACKEND_URL}/api/user/chatinfo`, {
165+
credentials: 'include'
166+
});
167+
const userData = await userResponse.json();
168+
169+
if (!userData || !userData.username) {
170+
throw new Error('사용자 정보를 가져올 수 없습니다.');
171+
}
168172

169-
// 메시지 목록에 바로 추가 (낙관적 UI 업데이트)
170-
const updatedMessages = [...messages, newMsg];
171-
setMessages(updatedMessages);
173+
// 새 메시지 객체 생성
174+
const newMsg = {
175+
chatMsgId: `local-${Date.now()}`,
176+
userId: userData.username,
177+
nickname: userData.nickname || userData.username,
178+
message: messageText,
179+
sendAt: new Date().toISOString()
180+
};
172181

173-
// 로컬 스토리지에 메시지 저장
174-
saveChatMessages(roomId, updatedMessages);
182+
// 메시지 목록에 바로 추가 (낙관적 UI 업데이트)
183+
setMessages(prev => [...prev, newMsg]);
175184

176-
// 메시지 전송 시도
177-
try {
178-
// 1. 웹소켓으로 먼저 시도
185+
// 웹소켓으로 메시지 전송
179186
const wsSuccess = await webSocketService.sendMessage(
180187
roomIdInt,
181188
messageText,
182-
userInfo.id,
183-
userInfo.nickname
189+
userData.username,
190+
userData.nickname || userData.username
184191
);
185192

186-
console.log('Message sent via WebSocket, success:', wsSuccess);
187-
188-
// 2. 웹소켓 실패 시 REST API로 시도
189193
if (!wsSuccess) {
190-
console.log('WebSocket send failed, trying REST API');
191-
try {
192-
const response = await ChatService.sendMessage(roomId, messageText);
193-
if (!response || !response.success) {
194-
console.error('API message send failed:', response);
195-
throw new Error(response?.message || '메시지 전송에 실패했습니다.');
196-
}
197-
} catch (apiErr) {
198-
console.error('REST API send failed:', apiErr);
199-
// 실패 알림 표시 (기존 메시지는 유지)
200-
const failedMessages = messages.map(msg =>
201-
msg.chatMsgId === newMsg.chatMsgId
202-
? { ...msg, failed: true, failReason: '전송 실패' }
203-
: msg
204-
);
205-
setMessages(failedMessages);
206-
207-
// Update localStorage with failed status
208-
saveChatMessages(roomId, failedMessages);
209-
210-
// 사용자에게 알림
211-
alert(apiErr.message || '메시지 전송에 실패했습니다.');
194+
// 웹소켓 전송 실패 시 REST API로 시도
195+
const response = await ChatService.sendMessage(roomId, messageText);
196+
if (!response.success) {
197+
throw new Error('메시지 전송 실패');
212198
}
213199
}
214200
} catch (err) {
215-
console.error('Error in message send flow:', err);
216-
// 실패 표시 추가
217-
const failedMessages = messages.map(msg =>
218-
msg.chatMsgId === newMsg.chatMsgId
219-
? { ...msg, failed: true, failReason: '전송 실패' }
220-
: msg
201+
console.error('Error sending message:', err);
202+
alert(err.message || '메시지 전송에 실패했습니다.');
203+
204+
// 실패한 메시지 표시
205+
setMessages(prev =>
206+
prev.map(msg =>
207+
msg.chatMsgId === `local-${Date.now()}`
208+
? { ...msg, failed: true, failReason: '전송 실패' }
209+
: msg
210+
)
221211
);
222-
setMessages(failedMessages);
223-
224-
// Update localStorage with failed status
225-
saveChatMessages(roomId, failedMessages);
226-
227-
// 사용자에게 알림
228-
alert('메시지 전송에 실패했습니다.');
229212
}
230213
};
231214

@@ -299,31 +282,25 @@ const ChatRoom = ({ roomId: propRoomId, onLeaveRoom, refreshRooms }) => {
299282
};
300283

301284
// 현재 로그인한 사용자 정보 가져오기
302-
const getCurrentUser = () => {
303-
// 이 부분은 실제 애플리케이션에서 로그인한 사용자 정보를 가져오는 방식에 따라 다를 수 있음
304-
// OAuth2 사용자 정보 가져오기 (localStorage나 sessionStorage에서)
305-
const userInfoStr = localStorage.getItem('userInfo');
306-
if (userInfoStr) {
307-
try {
308-
const user = JSON.parse(userInfoStr);
309-
setUserInfo({
310-
id: user.id,
311-
nickname: user.nickname || '사용자'
312-
});
313-
} catch (err) {
314-
console.error('Error parsing user info:', err);
315-
// 기본값 설정
316-
setUserInfo({
317-
id: 1, // 테스트용 임시 ID
318-
nickname: '사용자'
319-
});
285+
const getCurrentUser = async () => {
286+
try {
287+
const response = await fetch(`${API_BACKEND_URL}/api/user/chatinfo`, {
288+
credentials: 'include'
289+
});
290+
const userData = await response.json();
291+
292+
if (!userData || !userData.username) {
293+
throw new Error('사용자 정보를 가져올 수 없습니다.');
320294
}
321-
} else {
322-
// 사용자 정보가 없으면 기본값 설정
295+
323296
setUserInfo({
324-
id: 1, // 테스트용 임시 ID
325-
nickname: '사용자'
297+
id: userData.username,
298+
nickname: userData.nickname || userData.username
326299
});
300+
} catch (err) {
301+
console.error('Failed to get current user:', err);
302+
alert('사용자 정보를 가져올 수 없습니다. 로그인 페이지로 이동합니다.');
303+
navigate('/', { replace: true });
327304
}
328305
};
329306

src/services/ChatService.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,36 @@ const ChatService = {
286286

287287
sendMessage: async (roomId, message) => {
288288
try {
289-
if (!roomId || !message) {
289+
if (!roomId || !message?.trim()) {
290290
throw new Error('채팅방 ID와 메시지 내용은 필수입니다.');
291291
}
292292

293-
if (message.trim() === '') {
294-
throw new Error('메시지 내용은 비어있을 수 없습니다.');
293+
// 사용자 정보 가져오기
294+
const userResponse = await apiClient.get('/api/user/chatinfo');
295+
console.log('User info:', userResponse);
296+
297+
if (!userResponse || !userResponse.username) {
298+
throw new Error('사용자 정보를 찾을 수 없습니다.');
295299
}
296300

297-
console.log('Sending message to room', roomId, ':', message);
298-
const response = await apiClient.post(`/chat/msg/${roomId}`, { message });
299-
console.log('Send message response:', response);
300-
return response;
301+
// HTTP API를 통해 메시지 저장
302+
const response = await apiClient.post(`/chat/msg/${roomId}`, {
303+
message: message.trim()
304+
});
305+
306+
if (!response.success) {
307+
throw new Error('메시지 저장 실패');
308+
}
309+
310+
return {
311+
...response,
312+
userData: {
313+
id: userResponse.username,
314+
nickname: userResponse.nickname || userResponse.username
315+
}
316+
};
301317
} catch (error) {
302-
console.error('Error sending message:', error);
318+
console.error('Message send error:', error);
303319
throw error;
304320
}
305321
},

src/services/WebSocketService.js

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -320,45 +320,41 @@ class WebSocketService {
320320

321321
// 메시지 전송 메서드
322322
async sendMessage(roomId, message, userId, nickname) {
323-
// Validate inputs
324-
if (!roomId || !message || !userId) {
325-
console.error('Missing required fields for sending message:', { roomId, message, userId });
326-
return false;
327-
}
323+
try {
324+
if (!roomId || !message) {
325+
console.error('Missing required fields for sending message:', { roomId, message });
326+
return false;
327+
}
328328

329-
// Ensure roomId is a number
330-
const roomIdNum = parseInt(roomId);
329+
// 사용자 정보 가져오기
330+
const userResponse = await fetch(`${API_BACKEND_URL}/api/user/chatinfo`, {
331+
credentials: 'include'
332+
});
333+
const userData = await userResponse.json();
331334

332-
try {
333-
// 연결 확인 및 필요시 연결
334-
if (!this.isConnected) {
335-
try {
336-
await this.connect();
337-
} catch (err) {
338-
console.warn('Failed to connect WebSocket for sending message:', err);
339-
return false;
340-
}
335+
if (!userData || !userData.id) {
336+
console.error('Failed to get user info');
337+
return false;
341338
}
342339

343340
const chatMessage = {
344341
type: 'CHAT',
345-
roomId: roomIdNum,
346-
userId: userId,
347-
from: nickname || '사용자',
342+
roomId: parseInt(roomId),
343+
userId: userData.id,
344+
from: userData.nickname,
345+
username: userData.username,
346+
email: userData.email,
348347
message: message,
349348
sendAt: new Date().toISOString()
350349
};
351350

352-
console.log('Sending message:', chatMessage);
351+
console.log('Sending message with user info:', chatMessage);
353352

354-
// WebSocket connected, send the message
355-
if (this.isConnected && this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
353+
if (this.isConnected && this.webSocket?.readyState === WebSocket.OPEN) {
356354
this.webSocket.send(JSON.stringify(chatMessage));
357355
return true;
358356
} else {
359-
// Queue the message for when the connection is established
360357
this.pendingMessages.push(chatMessage);
361-
console.log('WebSocket not ready, queuing message');
362358
return false;
363359
}
364360
} catch (error) {

0 commit comments

Comments
 (0)