diff --git a/packages/common/src/components/chat/Message.tsx b/packages/common/src/components/chat/Message.tsx
index 07d776d8..bb7ffe34 100644
--- a/packages/common/src/components/chat/Message.tsx
+++ b/packages/common/src/components/chat/Message.tsx
@@ -29,7 +29,11 @@ export default function Message({
익명 {sender}
{isMyMessage && (나)
}
- {children}
+
+ {children}
+
);
}
diff --git a/packages/common/src/constants/socket.ts b/packages/common/src/constants/socket.ts
index c7626bdd..fbbbacec 100644
--- a/packages/common/src/constants/socket.ts
+++ b/packages/common/src/constants/socket.ts
@@ -5,6 +5,8 @@ export const CHAT_SOCKET_ENDPOINTS = {
PUBLISH: '/app/chat.sendMessage',
BLOCK: '/topic/block',
NOTICE: '/app/chat.sendNotice',
+ SUBSCRIBE_CHAT_LIST: '/user/queue/chatHistory',
+ PUBLISH_CHAT_LIST: '/app/chat.getHistory',
} as const;
export const RACING_SOCKET_ENDPOINTS = {
diff --git a/packages/common/src/utils/socket.ts b/packages/common/src/utils/socket.ts
index b9f9ed9b..907edc01 100644
--- a/packages/common/src/utils/socket.ts
+++ b/packages/common/src/utils/socket.ts
@@ -1,7 +1,7 @@
import { Client, IFrame, IMessage, StompSubscription } from '@stomp/stompjs';
import SockJS from 'sockjs-client';
-export type SocketSubscribeCallbackType = (data: unknown, messageId: string) => void;
+export type SocketSubscribeCallbackType = (data: unknown) => void;
export interface SubscriptionProps {
destination: string;
@@ -88,11 +88,7 @@ export default class Socket {
const subscriptionProps = {
destination,
headers,
- callback: (message: IMessage) => {
- const messageId = message.headers['message-id'];
- const data = JSON.parse(message.body);
- callback(data, messageId);
- },
+ callback: (message: IMessage) => callback(JSON.parse(message.body)),
};
const subscription = this.client.subscribe(
diff --git a/packages/user/src/components/event/chatting/index.tsx b/packages/user/src/components/event/chatting/index.tsx
index 26ed685d..acf0a4e4 100644
--- a/packages/user/src/components/event/chatting/index.tsx
+++ b/packages/user/src/components/event/chatting/index.tsx
@@ -1,8 +1,8 @@
import { ChatList } from '@softeer/common/components';
-import ChatInput from 'src/components/event/chatting/inputArea/input/index.tsx';
import { UseSocketReturnType } from 'src/hooks/socket/index.ts';
import Chat from './Chat.tsx';
import ChatInputArea from './inputArea/index.tsx';
+import ChatInput from './inputArea/input/index.tsx';
/** 실시간 기대평 섹션 */
diff --git a/packages/user/src/components/event/racing/index.tsx b/packages/user/src/components/event/racing/index.tsx
index 51ad2e69..df4723db 100644
--- a/packages/user/src/components/event/racing/index.tsx
+++ b/packages/user/src/components/event/racing/index.tsx
@@ -7,23 +7,26 @@ import RacingRankingDisplay from './controls/index.tsx';
import RacingDashboard from './dashboard/index.tsx';
/** 실시간 레이싱 섹션 */
-const RealTimeRacing = memo(({ racingSocket }: Pick) => {
- const { ranks, votes, onCarFullyCharged } = racingSocket;
- const { isCharged, handleCharge } = useChargeHandler(onCarFullyCharged);
+const RealTimeRacing = memo(
+ ({
+ racingSocket: { ranks, votes, onCarFullyCharged },
+ }: Pick) => {
+ const { isCharged, handleCharge } = useChargeHandler(onCarFullyCharged);
- return (
-
- );
-});
+ return (
+
+ );
+ },
+);
export default RealTimeRacing;
diff --git a/packages/user/src/hooks/socket/index.ts b/packages/user/src/hooks/socket/index.ts
index 2981108e..c30b62a3 100644
--- a/packages/user/src/hooks/socket/index.ts
+++ b/packages/user/src/hooks/socket/index.ts
@@ -4,26 +4,33 @@ import socketManager from 'src/services/socket.ts';
import useChatSocket from './useChatSocket.ts';
import useRacingSocket from './useRacingSocket.ts';
+export type UseSocketReturnType = ReturnType;
+
export default function useSocket() {
const { token } = useAuth();
const chatSocket = useChatSocket();
const racingSocket = useRacingSocket();
- const { onReceiveMessage, onReceiveBlock, ...chatSocketProps } = chatSocket;
+ const { onReceiveMessage, onReceiveChatList, onReceiveBlock, ...chatSocketProps } = chatSocket;
const { onReceiveStatus, ...racingSocketProps } = racingSocket;
const isSocketInitialized = useRef(false);
useLayoutEffect(() => {
- if (!isSocketInitialized.current) {
- socketManager.connectSocketClient({
- token,
- onReceiveMessage,
- onReceiveStatus,
- onReceiveBlock,
- });
- isSocketInitialized.current = true;
- }
+ const connetSocket = async () => {
+ if (!isSocketInitialized.current) {
+ await socketManager.connectSocketClient({
+ token,
+ onReceiveChatList,
+ onReceiveMessage,
+ onReceiveStatus,
+ onReceiveBlock,
+ });
+ isSocketInitialized.current = true;
+ }
+ };
+
+ connetSocket();
}, [token, onReceiveMessage, onReceiveStatus, onReceiveBlock]);
return { chatSocket: chatSocketProps, racingSocket: racingSocketProps };
diff --git a/packages/user/src/hooks/socket/useChatSocket.ts b/packages/user/src/hooks/socket/useChatSocket.ts
index e989e77e..26fc2cb1 100644
--- a/packages/user/src/hooks/socket/useChatSocket.ts
+++ b/packages/user/src/hooks/socket/useChatSocket.ts
@@ -14,21 +14,20 @@ export default function useChatSocket() {
const [storedChatList, storeChatList] = useChatListStorage();
const [chatList, setChatList] = useState(storedChatList);
+ const [isChatListSubscribed, setIsChatListSubscribed] = useState(false);
+
useEffect(() => storeChatList(chatList), [chatList]);
const handleIncomingMessage: SocketSubscribeCallbackType = useCallback(
- (data: unknown, messageId: string) => {
- const parsedData = data as Omit;
- const parsedMessage = { id: messageId, ...parsedData };
- setChatList((prevMessages) => [...prevMessages, parsedMessage] as ChatProps[]);
+ (data: unknown) => {
+ setChatList((prevMessages) => [...prevMessages, data] as ChatProps[]);
},
- [],
+ [setChatList],
);
const handleIncomingBlock: SocketSubscribeCallbackType = useCallback(
(data: unknown) => {
const { id, blockId } = data as { id: string; blockId: string };
-
setChatList((prevMessages) =>
prevMessages.map((message) => (message.id === blockId ? { id, type: 'b' } : message)),
);
@@ -36,28 +35,65 @@ export default function useChatSocket() {
[setChatList],
);
- const handleSendMessage = useCallback((content: string) => {
- try {
- const socketClient = socketManager.getSocketClient();
+ const socketClient = socketManager.getSocketClient();
+
+ const handleSendMessage = useCallback(
+ (content: string) => {
+ try {
+ const chatMessage = { content };
+
+ socketClient.sendMessages({
+ destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIBE,
+ body: chatMessage,
+ });
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ toast({
+ description:
+ errorMessage.length > 0 ? errorMessage : '기대평 전송 중 문제가 발생했습니다.',
+ });
+ }
+ },
+ [socketClient],
+ );
- const chatMessage = { content };
+ const handleIncomingChatHistory: SocketSubscribeCallbackType = useCallback(
+ (data: unknown) => {
+ setChatList(data as ChatProps[]);
+ },
+ [setChatList],
+ );
- socketClient.sendMessages({
- destination: CHAT_SOCKET_ENDPOINTS.PUBLISH,
- body: chatMessage,
+ const handleRequestForSendingChatHistory = useCallback(async () => {
+ try {
+ await socketClient.sendMessages({
+ destination: CHAT_SOCKET_ENDPOINTS.PUBLISH_CHAT_LIST,
+ body: {},
});
+ setIsChatListSubscribed(true);
} catch (error) {
const errorMessage = (error as Error).message;
toast({
description:
- errorMessage.length > 0 ? errorMessage : '기대평을 보내는 중 문제가 발생했습니다.',
+ errorMessage.length > 0 ? errorMessage : '기대평 내역을 불러오는 중 문제가 발생했습니다.',
});
}
- }, []);
+ }, [setIsChatListSubscribed, socketClient]);
+
+ const handleReceiveChatList: SocketSubscribeCallbackType = useCallback(
+ (data: unknown) => {
+ if (!isChatListSubscribed) {
+ handleRequestForSendingChatHistory();
+ }
+ handleIncomingChatHistory(data);
+ },
+ [isChatListSubscribed],
+ );
return {
onReceiveMessage: handleIncomingMessage,
onReceiveBlock: handleIncomingBlock,
+ onReceiveChatList: handleReceiveChatList,
onSendMessage: handleSendMessage,
messages: chatList,
};
diff --git a/packages/user/src/services/socket.ts b/packages/user/src/services/socket.ts
index 05bca8d6..9b4e7bea 100644
--- a/packages/user/src/services/socket.ts
+++ b/packages/user/src/services/socket.ts
@@ -14,6 +14,8 @@ class SocketManager {
private onReceiveBlock: SocketSubscribeCallbackType | null = null;
+ private onReceiveChatList: SocketSubscribeCallbackType | null = null;
+
private onReceiveStatus: SocketSubscribeCallbackType | null = null;
constructor(token: string | null) {
@@ -33,11 +35,13 @@ class SocketManager {
onReceiveMessage,
onReceiveBlock,
onReceiveStatus,
+ onReceiveChatList,
}: {
token: string | null | undefined;
onReceiveMessage: SocketSubscribeCallbackType;
onReceiveBlock: SocketSubscribeCallbackType;
onReceiveStatus: SocketSubscribeCallbackType;
+ onReceiveChatList: SocketSubscribeCallbackType;
}) {
if (this.socketClient) {
await this.socketClient.disconnect();
@@ -45,6 +49,7 @@ class SocketManager {
this.initializeSocketClient(token);
+ this.onReceiveChatList = onReceiveChatList;
this.onReceiveMessage = onReceiveMessage;
this.onReceiveBlock = onReceiveBlock;
this.onReceiveStatus = onReceiveStatus;
@@ -63,11 +68,19 @@ class SocketManager {
onReceiveBlock: this.onReceiveBlock!,
onReceiveMessage: this.onReceiveMessage!,
onReceiveStatus: this.onReceiveStatus!,
+ onReceiveChatList: this.onReceiveChatList!,
});
}
subscribeToTopics() {
if (this.socketClient && this.socketClient.client.connected) {
+ if (this.onReceiveChatList) {
+ this.socketClient.subscribe({
+ destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIBE_CHAT_LIST,
+ callback: this.onReceiveChatList,
+ });
+ }
+
if (this.onReceiveMessage) {
this.socketClient.subscribe({
destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIBE,