Skip to content

Commit cdc0183

Browse files
committed
feat : SSE전역변수로 관리할지 store 하나 만들어서 만들면서 고민중
1 parent 9dc3f83 commit cdc0183

File tree

2 files changed

+86
-17
lines changed

2 files changed

+86
-17
lines changed

src/hooks/useServerSentEvents.tsx

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,44 @@
11
import { EventSourcePolyfill } from 'event-source-polyfill';
2-
import { useEffect } from 'react';
2+
import { useEffect, useRef } from 'react';
33

44
import useAuthStore from '@/stores/authStore';
55

66
export const useServerSentEvents = () => {
77
const accessToken = useAuthStore.getState().accessToken;
8+
const sourceRef = useRef<EventSourcePolyfill | null>(null);
89

910
useEffect(() => {
10-
if (!accessToken) return console.log('구독 연결 실패');
11-
12-
let source: EventSourcePolyfill | null = null;
11+
if (!accessToken) {
12+
console.log('로그인 정보 확인불가');
13+
return;
14+
}
1315

1416
const connectSSE = () => {
1517
try {
1618
console.log('구독 시작');
17-
source = new EventSourcePolyfill(`${import.meta.env.VITE_API_URL}/api/notifications/sub`, {
18-
headers: {
19-
Authorization: `Bearer ${accessToken}`,
19+
sourceRef.current = new EventSourcePolyfill(
20+
`${import.meta.env.VITE_API_URL}/api/notifications/sub`,
21+
{
22+
headers: {
23+
Authorization: `Bearer ${accessToken}`,
24+
},
2025
},
21-
});
26+
);
2227

23-
source.onmessage = (payload) => {
24-
console.log(payload);
28+
sourceRef.current.onmessage = (event) => {
29+
console.log(event);
2530
console.log('알림 전송');
2631
};
2732

28-
source.addEventListener('notification', (event) => {
29-
console.log(event);
30-
console.log('알림 전송 dd');
31-
});
33+
// sourceRef.current.addEventListener('notification', (event) => {
34+
// console.log(event);
35+
// console.log('알림 전송 dd');
36+
// });
3237

33-
source.onerror = (error) => {
38+
sourceRef.current.onerror = (error) => {
3439
console.log(error);
3540
console.log('에러 발생함');
36-
source?.close();
41+
sourceRef.current?.close();
3742
// 재연결 로직 추가 가능
3843
setTimeout(connectSSE, 5000); // 5초 후 재연결 시도
3944
};
@@ -45,7 +50,16 @@ export const useServerSentEvents = () => {
4550
connectSSE();
4651

4752
return () => {
48-
source?.close();
53+
console.log('컴포넌트 언마운트로 인한 구독해제');
54+
closeSSE();
4955
};
5056
}, [accessToken]);
57+
58+
// 바깥으로 보낼 closeSSE 함수
59+
const closeSSE = () => {
60+
sourceRef.current?.close();
61+
sourceRef.current = null;
62+
};
63+
64+
return { closeSSE };
5165
};

src/stores/sseStore.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { EventSourcePolyfill } from 'event-source-polyfill';
2+
import { create } from 'zustand';
3+
4+
import useAuthStore from '@/stores/authStore'; // 액세스 토큰을 가져올 Zustand 스토어
5+
6+
interface SSEState {
7+
messages: string[];
8+
connectSSE: () => void;
9+
closeSSE: () => void;
10+
}
11+
12+
export const useSSEStore = create<SSEState>((set, get) => {
13+
let source: EventSourcePolyfill | null = null; // SSE 인스턴스 저장
14+
15+
return {
16+
messages: [],
17+
18+
connectSSE: () => {
19+
const accessToken = useAuthStore.getState().accessToken; // authStore에서 변수 가져오기
20+
if (!accessToken) {
21+
console.log('엑세스 토큰이 존재하지 않습니다. 구독 불가');
22+
return;
23+
}
24+
25+
console.log('🟢 SSE 구독 시작');
26+
27+
// 기존 SSE 연결 종료
28+
get().closeSSE();
29+
30+
// 새로운 SSE 연결 생성
31+
source = new EventSourcePolyfill(`${import.meta.env.VITE_API_URL}/api/notifications/sub`, {
32+
headers: { Authorization: `Bearer ${accessToken}` },
33+
});
34+
35+
source.onmessage = (event) => {
36+
console.log('SSE 메시지 수신:', event.data);
37+
set((state) => ({ messages: [...state.messages, event.data] })); // 메시지 전역 저장
38+
};
39+
40+
source.onerror = (error) => {
41+
console.log('SSE 오류 발생:', error);
42+
get().closeSSE();
43+
setTimeout(() => get().connectSSE(), 5000); // 5초 후 재연결
44+
};
45+
},
46+
47+
// 🔥 SSE 종료 함수 (로그아웃 시 실행)
48+
closeSSE: () => {
49+
console.log('SSE 수동 종료');
50+
source?.close();
51+
source = null;
52+
set({ messages: [] }); // 상태 초기화
53+
},
54+
};
55+
});

0 commit comments

Comments
 (0)