-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsocketService.js
More file actions
169 lines (154 loc) · 5.23 KB
/
socketService.js
File metadata and controls
169 lines (154 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';
/** 작성자: 김대호, 조윤상 */
let stompClient = null;
let subscriptions = new Map();
// 구독 대기 큐
let subscriptionQueue = [];
let isConnected = false;
// WebSocket 연결 상태 추적
const setConnected = (connected) => {
isConnected = connected;
if (connected) {
// 연결 완료 시 큐에 있는 구독들 처리
subscriptionQueue.forEach(({ destination, callback, resolve, reject }) => {
try {
const subscription = performSubscribe(destination, callback);
resolve(subscription);
} catch (error) {
reject(error);
}
});
subscriptionQueue = [];
}
};
// 실제 구독 수행 함수
const performSubscribe = (destination, callback) => {
// 동일한 주소에 대한 중복 구독 방지 (기존 구독 해지 후 재구독)
if (subscriptions.has(destination)) {
subscriptions.get(destination).unsubscribe();
subscriptions.delete(destination);
}
const subscription = stompClient.subscribe(destination, (message) => {
callback(JSON.parse(message.body));
});
subscriptions.set(destination, subscription);
return subscription;
};
const BASE_URL = window.location.hostname === "localhost"
? "http://localhost:8081/ws/chat"
: "https://api.sysonetaskmanager.store/ws/chat";
// WebSocket 연결
export const connectWebSocket = (onConnected) => {
if (stompClient && stompClient.active) {
console.log('WebSocket is already connected.');
setConnected(true);
if (onConnected) onConnected();
return;
}
stompClient = new Client({
webSocketFactory: () => new SockJS(BASE_URL),
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
onConnect: () => {
console.log('WebSocket connected!');
setConnected(true);
// 연결 성공 후, 콜백 실행
if (onConnected) onConnected();
},
onStompError: (frame) => {
console.error('Broker reported error: ' + frame.headers['message']);
console.error('Additional details: ' + frame.body);
setConnected(false);
},
// 연결 끊김 시 재연결 시도
onDisconnect: (frame) => {
console.log('WebSocket disconnected:', frame);
setConnected(false);
// 필요한 경우 재연결 로직 추가
},
});
stompClient.activate();
};
// WebSocket 연결 해제
export const disconnectWebSocket = () => {
if (stompClient) {
stompClient.deactivate();
stompClient = null;
subscriptions.clear();
console.log('WebSocket disconnected!');
}
};
// 공통 구독/해제 유틸 함수
const manageSubscription = (action, destination, callback) => {
if (action === 'subscribe') {
if (subscriptions.has(destination)) {
subscriptions.get(destination).unsubscribe();
subscriptions.delete(destination);
}
const subscription = stompClient.subscribe(destination, (message) => {
callback(JSON.parse(message.body));
});
subscriptions.set(destination, subscription);
return subscription;
} else if (action === 'unsubscribe') {
if (subscriptions.has(destination)) {
subscriptions.get(destination).unsubscribe();
subscriptions.delete(destination);
}
}
};
export const subscribe = (destination, callback) => {
return new Promise((resolve, reject) => {
if (isConnected && stompClient && stompClient.active) {
try {
const subscription = manageSubscription('subscribe', destination, callback);
resolve(subscription);
} catch (error) {
reject(error);
}
} else {
console.warn('STOMP client is not connected. Queueing subscription for ', destination);
subscriptionQueue.push({ destination, callback, resolve, reject });
}
});
}
// 특정 채팅방 토픽 구독
export const subscribeToChatRoom = (chatRoomId, onMessageReceived) => {
return subscribe(`/topic/chatroom/${chatRoomId}`, onMessageReceived);
};
// 개인 알림 큐 구독
export const subscribeToUserQueue = (queueName, onNotificationReceived) => {
return subscribe(`/user/queue/${queueName}`, onNotificationReceived);
};
// 구독 해지
export const unsubscribe = (destination) => {
manageSubscription('unsubscribe', destination);
}
// 메시지 전송 (발행)
export const sendMessage = (chatMessage) => {
if (stompClient && stompClient.active) {
stompClient.publish({
destination: '/app/send',
body: JSON.stringify(chatMessage),
});
} else {
console.error('Cannot send message, STOMP client is not connected.');
}
};
// 초대 메시지 전송
export const sendInviteMessage = (chatRoomId, memberId, memberIdList) => {
if (stompClient && stompClient.active) {
stompClient.publish({
destination: '/app/invite',
body: JSON.stringify({
chatRoomId,
memberId,
memberIdList,
}),
});
} else {
console.error('Cannot send invite message, STOMP client is not connected.');
}
};