npm install @stomp/stompjs sockjs-client
npm install --save-dev @types/sockjs-client
Uncaught ReferenceError: global is not defined
→브라우저 환경에서sockjs-client
를 사용할 때 발생하는 Node.js 전역 객체global
이 정의되지 않았다는 오류
sockjs-client
라이브러리 내부에서 global
변수를 사용하는데, 이는 Node.js 전역 객체이고 브라우저에서는 존재하지 않아 발생하는 문제야. 보통 이런 문제는 Vite + React 프로젝트에서 번들링 시 발생할 수 있어. 최근 Vite, Rollup, Webpack 5+에선 Node 전역 객체들을 자동으로 polyfill하지 않기 때문에 이런 문제가 생길 수 있어.
vite.config.ts
에서 define: { global: 'globalThis' }
설정 추가
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
define: {
global: 'globalThis' // ✅ global 참조를 globalThis로 대체
}
})
목적 | 위치 | 설명 |
---|---|---|
채팅방 생성 | chatService.ts |
POST /api/chat/rooms |
웹소켓 연결/구독 | useChatSocket.ts |
채팅방 입장 시 사용 |
채팅 상태 | chatStore.ts |
상태 관리용 zustand |
채팅 시작 버튼 | BoardDetailPage.tsx |
클릭 시 채팅방 생성 + 이동 |
1.. 채팅방 생성 API - chatService.ts
// features/chat/services/chatService.ts
import axios from 'axios'
export const createChatRoom = async (boardId: number) => {
const response = await axios.post('/api/chat/rooms', { boardId })
return response.data.data.roomId
}
chatStore.ts
// store/chatStore.ts
import { create } from 'zustand'
interface ChatStore {
connected: boolean
setConnected: (status: boolean) => void
}
export const useChatStore = create<ChatStore>((set) => ({
connected: false,
setConnected: (status) => set({ connected: status }),
}))
useChatSocket.ts
// features/chat/hooks/useChatSocket.ts
import { Client, IMessage } from '@stomp/stompjs'
import SockJS from 'sockjs-client'
import { useEffect, useRef } from 'react'
import { useChatStore } from '@/store/chatStore'
export const useChatSocket = (roomId: string, onMessage: (msg: any) => void) => {
const clientRef = useRef<Client | null>(null)
const setConnected = useChatStore((state) => state.setConnected)
useEffect(() => {
const socket = new SockJS('/ws')
const client = new Client({
webSocketFactory: () => socket,
connectHeaders: {
// 인증 필요 시 Authorization 헤더 추가
},
debug: (str) => console.log('[STOMP]', str),
onConnect: () => {
setConnected(true)
// 채팅방 메시지 구독
client.subscribe(`/topic/chat/room/${roomId}`, (message: IMessage) => {
const body = JSON.parse(message.body)
onMessage(body)
})
// 개인 메시지 구독
client.subscribe('/user/queue/messages', (message: IMessage) => {
const body = JSON.parse(message.body)
console.log('개인 메시지 수신', body)
})
// 입장 알림
client.publish({
destination: '/app/chat.enter',
body: JSON.stringify({ roomId }),
})
},
onDisconnect: () => {
setConnected(false)
},
reconnectDelay: 5000,
})
client.activate()
clientRef.current = client
return () => {
client.deactivate()
}
}, [roomId, onMessage])
}
BoardDetailPage.tsx