프로젝트에 사용할 ws라이브러리 이용법에 대해
먼저 필요한 패키지들을 설치한다.
$ pnpm install @nestjs/websockets @nestjs/platform-ws ws
nestjs에서 WebSocket은 socket.io가 기본으로 되어있어 ws를 사용하려면 main.ts
에서 설정을 해줘야한다.(테스트에서도)
app.useWebSocketAdapter(new WsAdapter(app));
RestApi에서는 controller가 있지만 ws에서는 gateway파일이 있다. 둘다 클라이언트에서 오는 요청을 처리하는 곳이다.
gateway파일에서 각종 응답처리 로직을 작성하면 된다.
데코레이터 등은 추후 추가 예정
//클라이언트
const ws = new WebSocket('ws://localhost:3000/chat');
const messages = document.getElementById('messages');
ws.onopen = () => {
console.log('연결됨');
addMessage('시스템', '서버에 연결되었습니다.');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch(data.event) {
case 'response':
addMessage('서버', data.data);
break;
case 'broadcast':
addMessage(data.data.sender, data.data.message);
break;
case 'serverTime':
addMessage('서버시간', data.data.time);
break;
}
};
ws.onclose = () => {
addMessage('시스템', '서버와 연결이 끊어졌습니다.');
};
function sendMessage() {
const nameInput = document.getElementById('nameInput');
const messageInput = document.getElementById('messageInput');
if (messageInput.value) {
ws.send(JSON.stringify({
event: 'chat',
data: {
sender: nameInput.value || '익명',
message: messageInput.value
}
}));
messageInput.value = '';
}
}
function addMessage(sender, message) {
const li = document.createElement('li');
li.textContent = `${sender}: ${message}`;
messages.appendChild(li);
messages.scrollTop = messages.scrollHeight;
}
클라이언트와 서버에서 각각 요청 보내고 받기(ai생성 예제)
//서버
interface ChatMessage {
sender: string;
message: string;
}
@WebSocketGateway({
path: '/chat'
})
export class ChatGateway {
@WebSocketServer()
server: Server;
// 클라이언트로부터 메시지 수신
@SubscribeMessage('chat')
handleChat(client: WebSocket, message: ChatMessage): void {
console.log(`메시지 수신: ${message.sender}: ${message.message}`);
// 클라이언트에게 응답
client.send(JSON.stringify({
event: 'response',
data: `서버 응답: "${message.message}" 메시지를 받았습니다.`
}));
// 모든 클라이언트에게 브로드캐스트
this.broadcast({
event: 'broadcast',
data: {
sender: message.sender,
message: message.message,
time: new Date().toISOString()
}
});
}
// 서버에서 주기적으로 메시지 전송 (예: 5초마다)
onModuleInit() {
setInterval(() => {
this.broadcast({
event: 'serverTime',
data: {
time: new Date().toISOString()
}
});
}, 5000);
}
// 모든 클라이언트에게 메시지 브로드캐스트
private broadcast(message: any): void {
const messageStr = JSON.stringify(message);
this.server.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(messageStr);
}
});
}
}