Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/frontend/apps/web/app/stock/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ToastAlarm } from '@/src/features/alarm';
import AuthWrapper from '@/src/features/auth/ui/auth-wrapper';
import { ProfilePopover } from '@/src/features/user';
import { Header, StompWebSocketProvider, RQProvider } from '@/src/shared';
import { getUserIdFromCookie } from '@/src/shared/services/lib';
import { Toaster } from '@workspace/ui/components';

import '@workspace/ui/globals.css';

Expand All @@ -11,7 +13,6 @@ export default async function RootLayout({
children: React.ReactNode;
}>) {
const userId = await getUserIdFromCookie();

return (
<>
<header className="h-[68px] w-full flex items-center justify-between px-4 py-1 bg-muted">
Expand All @@ -22,6 +23,8 @@ export default async function RootLayout({
<StompWebSocketProvider userId={userId}>
<RQProvider>{children}</RQProvider>
</StompWebSocketProvider>
<Toaster />
<ToastAlarm />
</AuthWrapper>
</div>
</>
Expand Down
1 change: 1 addition & 0 deletions src/frontend/apps/web/src/features/alarm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ToastAlarm } from './model/toast-alarm';
33 changes: 33 additions & 0 deletions src/frontend/apps/web/src/features/alarm/model/toast-alarm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client';

import { useEffect } from 'react';
import { webSocketEvent } from '@/src/shared/providers/stomp-websocket-provider';
import { useToast } from '@workspace/ui/hooks/Toast/use-toast';
import { ToastAction } from '@workspace/ui/components';

export type Alarm = {
userNickname: string;
channelName: string;
text: string;
};

export const ToastAlarm = () => {
const { toast } = useToast();

useEffect(() => {
const handleMessage = (message: Alarm) => {
toast({
title: `${message.userNickname} #${message.channelName}`,
description: `${message.text}`,
});
};

webSocketEvent.on('alarmReceived', handleMessage);

return () => {
webSocketEvent.off('alarmReceived', handleMessage);
};
}, [toast]);

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import {
import * as StompJs from '@stomp/stompjs';

import SockJS from 'sockjs-client';
import EventEmitter from 'events';

export const webSocketEvent = new EventEmitter();

type WebSocketContextProps = {
client: StompJs.Client | null;
isConnected: boolean;
sessionId: string;
};

type WebSocketProviderProps = {
Expand All @@ -31,8 +35,7 @@ export const StompWebSocketProvider = ({
}: WebSocketProviderProps) => {
const client = useRef<StompJs.Client | null>(null);
const [isConnected, setIsConnected] = useState(false);

// const BASE_URL = `http://${process.env.NEXT_PUBLIC_BASE_URL}:${process.env.NEXT_PUBLIC_CHAT_SERVER1_PORT}`;
const sessionId = useRef<string | null>(null);
const BASE_URL = `${process.env.NEXT_PUBLIC_REAL_BASE_URL}`;

const connect = useCallback(() => {
Expand All @@ -50,6 +53,23 @@ export const StompWebSocketProvider = ({
onConnect: () => {
console.log('✅ WebSocket Connected');
setIsConnected(true);

const socketUrl = client.current.webSocket['_transport'].ws.url;
sessionId.current = socketUrl.split('/').slice(-2, -1)[0];

client.current.subscribe(
`/subscribe/notification.${sessionId.current}`,
(message) => {
try {
const payload = JSON.parse(message.body);
console.log('📩 Received:', payload);

webSocketEvent.emit('alarmReceived', payload);
} catch (error) {
console.error('❌ 메시지 파싱 실패:', error);
}
},
);
},
onStompError: (frame) => {
console.error('❌ Broker error:', frame.headers['message'], frame.body);
Expand All @@ -73,7 +93,11 @@ export const StompWebSocketProvider = ({

return (
<StompWebSocketContext.Provider
value={{ client: client.current, isConnected }}
value={{
client: client.current,
isConnected,
sessionId: sessionId.current,
}}
>
{children}
</StompWebSocketContext.Provider>
Expand Down