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
|
// app/api/notifications/stream/route.ts
import { NextRequest } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
import realtimeNotificationService from '@/lib/realtime/RealtimeNotificationService';
export async function GET(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.id) {
return new Response('Unauthorized', { status: 401 });
}
const userId = session.user.id;
const encoder = new TextEncoder();
const stream = new ReadableStream({
start(controller) {
// 클라이언트 등록
const clientId = realtimeNotificationService.addClient(userId, controller);
console.log(`SSE stream started for user ${userId} (${clientId})`);
// 초기 연결 확인 메시지
controller.enqueue(encoder.encode("data: {\"type\":\"connected\"}\n\n"));
// 연결 해제 처리
request.signal.addEventListener('abort', () => {
console.log(`SSE stream ended for user ${userId} (${clientId})`);
realtimeNotificationService.removeClient(userId, controller);
controller.close();
});
},
cancel() {
console.log(`SSE stream cancelled for user ${userId}`);
realtimeNotificationService.removeClient(userId, controller);
}
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no', // Nginx 버퍼링 비활성화
},
});
} catch (error) {
console.error('Error creating SSE stream:', error);
return new Response('Internal Server Error', { status: 500 });
}
}
|