Node.js에서 실시간 통신 구축하기
Olivia Novak
Dev Intern · Leapcell

소개
오늘날 상호 연결된 디지털 환경에서 실시간 통신은 틈새 기능에서 현대 웹 애플리케이션의 필수 구성 요소로 전환되었습니다. 전 세계적인 대화를 촉진하는 인스턴트 메시징 플랫폼부터 최신 정보를 사용자에게 계속 알려주는 동적 알림 시스템에 이르기까지 데이터를 즉시 교환하는 능력은 매우 중요합니다.
기존 HTTP 요청-응답 주기는 종종 이러한 즉각성을 전달하는 데 부족하여 지연 시간을 유발하고 리소스를 비효율적으로 소비하는 빈번한 폴링이 필요합니다.
이것이 바로 WebSockets가 단일 TCP 연결을 통해 영구적이고 전이중 통신 채널을 제공하면서 등장하는 곳입니다.
이 글에서는 가벼운 ws
라이브러리 또는 강력한 Socket.IO 프레임워크를 사용하여 Node.js에서 WebSockets의 힘을 활용하여 매력적인 실시간 채팅 및 알림 서비스를 구축하는 방법을 탐구합니다.
실시간 통신을 위한 핵심 개념
구현에 들어가기 전에 컨텍스트에서 실시간 통신의 기반이 되는 핵심 기술에 대한 명확한 이해를 확립해 보겠습니다.
WebSockets: WebSockets는 브라우저와 서버 간의 양방향 대화형 통신 세션을 가능하게 하는 통신 프로토콜입니다. 상태 비저장이며 요청-응답 모델에 의존하는 HTTP와 달리 WebSockets는 영구 연결을 설정하여 서버와 클라이언트 모두 클라이언트가 명시적으로 요청하지 않고도 언제든지 데이터를 보낼 수 있도록 합니다. 이는 저지연, 고주파 데이터 교환이 필요한 애플리케이션에 이상적입니다.
Node.js: Chrome의 V8 JavaScript 엔진을 기반으로 구축된 JavaScript 런타임입니다. Node.js의 이벤트 기반, 비차단 I/O 모델은 수많은 동시 연결을 처리하는 데 매우 효율적이며, 이는 실시간 애플리케이션의 중요한 요구 사항입니다.
ws
라이브러리: Node.js를 위한 "순수" WebSocket 구현입니다.
빠르고 간단하며 WebSocket 프로토콜에 대한 직접적인 인터페이스를 제공합니다.
추가 추상화 계층 없이 원시 WebSocket 성능이 필요한 경우 훌륭한 선택입니다.
Socket.IO: 실시간의 양방향, 이벤트 기반 통신을 가능하게 하는 라이브러리입니다. 주로 WebSockets를 사용하지만, WebSockets를 완전히 지원하지 않는 브라우저 또는 환경에 대한 폴백(장기 폴링 포함)을 제공합니다. 또한 자동 재연결, 패킷 버퍼링, 브로드캐스팅 및 방과 같은 기능을 제공하여 복잡한 실시간 애플리케이션 개발을 단순화합니다.
ws
를 사용한 실시간 서비스 구축
ws
라이브러리는 WebSockets 구현을 위한 간단한 경로를 제공합니다.
ws
를 사용하여 간단한 채팅 서비스를 구축해 보겠습니다.
서버 측 구현 (ws-server.js
)
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', ws => { console.log('Client connected'); ws.on('message', message => { console.log(`Received: ${message}`); // 모든 연결된 클라이언트에게 메시지 브로드캐스트 wss.clients.forEach(client => { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(message.toString()); // 메시지가 문자열인지 확인 } }); }); ws.on('close', () => { console.log('Client disconnected'); }); ws.on('error', error => { console.error('WebSocket error:', error); }); ws.send('Welcome to the chat!'); }); console.log('WebSocket server started on port 8080');
이 서버는 8080 포트에서 WebSocket 서버를 초기화합니다. 클라이언트가 연결되면 연결을 기록합니다. 클라이언트로부터 메시지를 받으면 해당 메시지를 다른 모든 연결된 클라이언트에게 브로드캐스트하여 효과적으로 채팅방을 만듭니다.
클라이언트 측 구현 (index.html
)
<!DOCTYPE html> <html> <head> <title>WS Chat Client</title> </head> <body> <h1>WS Chat</h1> <div id="messages" style="border: 1px solid black; height: 300px; overflow-y: scroll; padding: 10px;"></div> <input type="text" id="messageInput" placeholder="Type your message..."> <button id="sendButton">Send</button> <script> const ws = new WebSocket('ws://localhost:8080'); const messagesDiv = document.getElementById('messages'); const messageInput = document.getElementById('messageInput'); const sendButton = document.getElementById('sendButton'); ws.onopen = () => { console.log('Connected to WebSocket server'); }; ws.onmessage = event => { const messageElement = document.createElement('p'); messageElement.textContent = event.data; messagesDiv.appendChild(messageElement); messagesDiv.scrollTop = messagesDiv.scrollHeight; // 바닥으로 스크롤 }; ws.onclose = () => { console.log('Disconnected from WebSocket server'); }; ws.onerror = error => { console.error('WebSocket error:', error); }; sendButton.onclick = () => { const message = messageInput.value; if (message) { ws.send(message); messageInput.value = ''; } }; messageInput.addEventListener('keypress', (event) => { if (event.key === 'Enter') { sendButton.click(); } }); </script> </body> </html>
이 클라이언트 측 코드는 ws
서버에 연결됩니다.
수신 메시지를 수신 대기하고 div
에 표시합니다.
사용자는 입력 필드에 메시지를 입력하고 서버로 보낼 수 있습니다.
Socket.IO를 사용한 실시간 서비스 구축
Socket.IO는 WebSockets를 기반으로 하며 더 높은 수준의 API와 추가 기능을 제공합니다.
서버 측 구현 (socketio-server.js
)
먼저 Socket.IO를 설치합니다: npm install socket.io express
const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const app = express(); const server = http.createServer(app); const io = socketIo(server); app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html'); // 클라이언트 HTML 제공 }); io.on('connection', (socket) => { console.log('A user connected'); // 채팅 메시지 처리 socket.on('chat message', (msg) => { console.log('message: ' + msg); io.emit('chat message', msg); // 모두에게 브로드캐스트 }); // 알림 처리 socket.on('send notification', (data) => { console.log('sending notification:', data.message); // 특정 사용자 또는 방을 대상으로 지정할 수 있습니다. io.emit('new notification', { message: data.message, timestamp: new Date() }); }); socket.on('disconnect', () => { console.log('User disconnected'); }); }); server.listen(3000, () => { console.log('Socket.IO server listening on port 3000'); });
여기서 Express 서버와 Socket.IO를 통합합니다.
클라이언트가 연결되면 'chat message'
및 'send notification'
과 같은 사용자 정의 이벤트에 대한 수신 대기자를 연결합니다.
io.emit()
함수는 모든 연결된 클라이언트에게 메시지를 브로드캐스트합니다.
클라이언트 측 구현 (index.html
)
<!DOCTYPE html> <html> <head> <title>Socket.IO Chat & Notifications</title> <script src="/socket.io/socket.io.js"></script> </head> <body> <h1>Socket.IO Chat</h1> <div id="messages" style="border: 1px solid black; height: 200px; overflow-y: scroll; padding: 10px; margin-bottom: 10px;"></div> <input type="text" id="chatInput" placeholder="Type your chat message..."> <button id="sendChatButton">Send Chat</button> <h2>Notifications</h2> <div id="notifications" style="border: 1px solid black; height: 150px; overflow-y: scroll; padding: 10px; margin-top: 20px;"></div> <input type="text" id="notificationInput" placeholder="Type your notification message..."> <button id="sendNotificationButton">Send Notification</button> <script> const socket = io(); // HTML이 제공되는 서버에 연결 const messagesDiv = document.getElementById('messages'); const chatInput = document.getElementById('chatInput'); const sendChatButton = document.getElementById('sendChatButton'); const notificationsDiv = document.getElementById('notifications'); const notificationInput = document.getElementById('notificationInput'); const sendNotificationButton = document.getElementById('sendNotificationButton'); // 수신 채팅 메시지 처리 socket.on('chat message', (msg) => { const item = document.createElement('li'); item.textContent = msg; messagesDiv.appendChild(item); messagesDiv.scrollTop = messagesDiv.scrollHeight; }); // 수신 알림 처리 socket.on('new notification', (data) => { const item = document.createElement('li'); item.textContent = `[${new Date(data.timestamp).toLocaleTimeString()}] ${data.message}`; notificationsDiv.appendChild(item); notificationsDiv.scrollTop = notificationsDiv.scrollHeight; }); sendChatButton.onclick = () => { const message = chatInput.value; if (message) { socket.emit('chat message', message); // 'chat message' 이벤트 발생 chatInput.value = ''; } }; chatInput.addEventListener('keypress', (event) => { if (event.key === 'Enter') { sendChatButton.click(); } }); sendNotificationButton.onclick = () => { const notificationMsg = notificationInput.value; if (notificationMsg) { socket.emit('send notification', { message: notificationMsg }); // 'send notification' 이벤트 발생 notificationInput.value = ''; } }; </script> </body> </html>
Socket.IO 클라이언트 라이브러리(Socket.IO에서 자동으로 제공됨)는 io()
함수를 제공하여 연결합니다.
'chat message'
및 'new notification'
이벤트를 수신 대기하고 적절하게 표시합니다.
socket.emit()
은 사용자 정의 이벤트를 서버로 보내는 데 사용됩니다.
애플리케이션 시나리오
Node.js와 함께하는 WebSockets의 힘은 수많은 실제 애플리케이션으로 확장됩니다.
- 실시간 채팅 애플리케이션: 시연한 바와 같이 인스턴트 메시징은 주요 사용 사례입니다. 그룹 채팅, 개인 메시지, 입력 표시기 등은 모두 실시간 기능의 이점을 누릴 수 있습니다.
- 라이브 알림: 새 이메일, 친구 요청, 뉴스 업데이트 또는 시스템 이벤트에 대한 즉각적인 경고 제공.
- 협업 도구: 공유 화이트보드, 공동 편집 문서, 프로젝트 관리 도구로, 변경 사항이 여러 사용자에게 즉시 반영되어야 합니다.
- 게임: 플레이어 위치, 점수 및 작업이 최소 지연 시간으로 동기화되어야 하는 실시간 멀티플레이어 게임.
- 금융 티커 및 대시보드: 실시간 주가, 암호화폐 데이터 또는 분석 업데이트 표시.
- IoT 장치 통신: 장치를 원격으로 제어하거나 센서 데이터를 즉시 수신합니다.
ws
와 Socket.IO 비교
기능 | ws 라이브러리 | Socket.IO |
---|---|---|
프로토콜 | 순수 WebSocket 구현 | 주로 WebSockets를 사용하며, 장기 폴링 및 기타 폴백 포함 |
사용 편의성 | 원시 WebSockets에 대한 간단하고 직접적인 API | 더 높은 수준의 API, 많은 복잡성 추상화 |
기능 | 기본 send/receive, 연결 관리 | 자동 재연결, 패킷 버퍼링, 브로드캐스팅, 방, 네임스페이스, 사용자 정의 이벤트, 내장 하트비트 메커니즘 |
브라우저 지원 | 네이티브 WebSocket 지원 필요 | 폴백 덕분에 광범위한 브라우저 지원 |
오버헤드 | 최소 오버헤드, 매우 가벼움 | 기능 세트로 인해 약간의 오버헤드 증가 |
사용 사례 | 직접적인 WebSocket 제어 또는 최소한의 종속성이 필요한 경우, 성능이 중요한 애플리케이션 | 견고성, 고급 기능 및 광범위한 호환성이 필요한 복잡한 실시간 애플리케이션 |
결론
단순한 ws
라이브러리 또는 기능이 풍부한 Socket.IO를 통해 WebSockets를 사용하여 Node.js 애플리케이션에 실시간 통신을 구축하면 상호 작용 및 사용자 참여의 새로운 차원을 열 수 있습니다.
두 도구 모두 개발자가 기존 HTTP의 기능을 훨씬 뛰어넘는 동적이고 반응성이 뛰어난 웹 환경을 만들 수 있도록 지원합니다.
이러한 강력한 기술을 활용함으로써 개발자는 현대 웹 상호 작용을 정의하는 인스턴트 채팅 서비스, 동적 알림 시스템 및 수많은 기타 실시간 애플리케이션을 효과적으로 만들 수 있습니다.