JavaScript의 WebSocket API는 서버와 클라이언트 간의 양방향 통신을 가능하게 해주는 프로토콜입니다. 이는 HTTP와 달리 클라이언트와 서버 간의 지속적인 연결을 유지하여, 실시간 데이터 전송이 필요한 애플리케이션에서 매우 유용하게 사용됩니다.
1. WebSocket 개요
1.1 기본 개념
WebSocket은 HTML5 표준의 일부로, 단방향 통신을 제공하는 HTTP와는 달리, 지속적인 양방향 통신을 지원합니다. 클라이언트와 서버 간의 연결이 한 번 맺어지면, 추가적인 요청 없이도 데이터를 양방향으로 주고받을 수 있습니다.
1.2 WebSocket의 장점
- 실시간 데이터 전송: 지연 시간 없이 데이터를 주고받을 수 있습니다.
- 낮은 오버헤드: HTTP 요청과 응답에서 발생하는 오버헤드를 줄일 수 있습니다.
- 지속적인 연결: 연결을 유지한 상태에서 데이터를 주고받기 때문에, 끊임없이 새로운 연결을 설정할 필요가 없습니다.
2. WebSocket 프로토콜
WebSocket은 기존의 HTTP 연결을 업그레이드하여 사용합니다. 클라이언트는 ws://
또는 보안 연결인 wss://
를 사용하여 서버와 연결을 설정합니다.
2.1 핸드셰이크
클라이언트와 서버 간의 연결은 HTTP 핸드셰이크로 시작됩니다. 클라이언트는 WebSocket 연결을 요청하고, 서버는 이를 승인하면 WebSocket 연결이 설정됩니다.
클라이언트 요청 예:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
서버 응답 예:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
3. JavaScript WebSocket 사용법
3.1 클라이언트 측 WebSocket
JavaScript에서는 WebSocket 객체를 사용하여 WebSocket 연결을 설정하고, 메시지를 주고받으며, 연결 상태를 관리할 수 있습니다.
3.1.1 WebSocket 연결 설정
const socket = new WebSocket('ws://example.com/socket');
3.1.2 이벤트 핸들러 설정
WebSocket 객체는 다양한 이벤트를 처리할 수 있는 이벤트 핸들러를 제공합니다.
// 연결이 열리면 호출됨
socket.onopen = function(event) {
console.log('WebSocket connection opened:', event);
};
// 메시지를 수신하면 호출됨
socket.onmessage = function(event) {
console.log('Message received:', event.data);
};
// 오류가 발생하면 호출됨
socket.onerror = function(event) {
console.error('WebSocket error:', event);
};
// 연결이 닫히면 호출됨
socket.onclose = function(event) {
console.log('WebSocket connection closed:', event);
};
3.1.3 메시지 보내기
메시지를 보내기 위해서는 send
메서드를 사용합니다.
socket.send('Hello, Server!');
3.1.4 연결 닫기
연결을 닫으려면 close
메서드를 사용합니다.
socket.close();
3.2 서버 측 WebSocket
서버 측에서는 다양한 라이브러리를 사용하여 WebSocket 서버를 구축할 수 있습니다. 여기서는 Node.js 환경에서 popular한 ws
라이브러리를 사용한 예를 설명합니다.
3.2.1 WebSocket 서버 설정
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function(ws) {
console.log('Client connected');
// 클라이언트로부터 메시지를 수신하면 호출됨
ws.on('message', function(message) {
console.log('Received:', message);
// 클라이언트에 메시지 보내기
ws.send('Hello, Client!');
});
// 연결이 닫히면 호출됨
ws.on('close', function() {
console.log('Client disconnected');
});
// 오류가 발생하면 호출됨
ws.on('error', function(error) {
console.error('WebSocket error:', error);
});
});
4. WebSocket 예제 애플리케이션
여기서는 간단한 채팅 애플리케이션 예제를 통해 WebSocket의 사용법을 설명합니다.
4.1 클라이언트 측 코드
HTML:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Chat</title>
</head>
<body>
<input id="messageInput" type="text" placeholder="Type a message">
<button id="sendButton">Send</button>
<div id="chatBox"></div>
<script src="chat.js"></script>
</body>
</html>
JavaScript (chat.js
):
const socket = new WebSocket('ws://localhost:8080');
const messageInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
const chatBox = document.getElementById('chatBox');
socket.onopen = function() {
console.log('Connected to server');
};
socket.onmessage = function(event) {
const message = document.createElement('p');
message.textContent = 'Server: ' + event.data;
chatBox.appendChild(message);
};
socket.onerror = function(error) {
console.error('WebSocket error:', error);
};
socket.onclose = function() {
console.log('Disconnected from server');
};
sendButton.addEventListener('click', function() {
const message = messageInput.value;
socket.send(message);
messageInput.value = '';
const userMessage = document.createElement('p');
userMessage.textContent = 'You: ' + message;
chatBox.appendChild(userMessage);
});
4.2 서버 측 코드
Node.js 서버 코드 (server.js
):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function(ws) {
console.log('Client connected');
ws.on('message', function(message) {
console.log('Received:', message);
ws.send('You said: ' + message);
});
ws.on('close', function() {
console.log('Client disconnected');
});
ws.on('error', function(error) {
console.error('WebSocket error:', error);
});
});
5. WebSocket 보안
5.1 HTTPS와 WSS
- HTTPS: 보안된 HTTP 연결로, WebSocket을 사용할 때도 보안된
wss://
프로토콜을 사용하는 것이 좋습니다. - WSS: 보안된 WebSocket 연결로, 데이터가 암호화되어 전송됩니다.
5.2 인증 및 권한 부여
WebSocket 연결을 설정하기 전에, HTTP 핸드셰이크 단계에서 인증을 수행할 수 있습니다. 또한, 연결이 설정된 후에도 토큰을 통해 추가적인 인증 및 권한 부여를 구현할 수 있습니다.
6. 고급 WebSocket 기능
6.1 다중 클라이언트 관리
WebSocket 서버는 여러 클라이언트와의 연결을 관리할 수 있으며, 각 클라이언트에 대해 별도의 이벤트 핸들러를 설정할 수 있습니다.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function(ws) {
console.log('Client connected');
ws.on('message', function(message) {
console.log('Received:', message);
// 모든 클라이언트에게 메시지 전송
wss.clients.forEach(function(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
6.2 심장박동 (Heartbeat) 구현
클라이언트와 서버 간의 연결 상태를 유지하기 위해 주기적으로 심장박동 메시지를 주고받을 수 있습니다.
// 클라이언트 측
setInterval(function() {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: 'ping' }));
}
}, 30000);
// 서버 측
wss.on('connection', function(ws) {
ws.isAlive = true;
ws.on('pong', function() {
ws.isAlive = true;
});
const interval = setInterval(function() {
wss.clients.forEach(function(ws) {
if (!ws.isAlive) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
ws.on('close', function() {
clearInterval(interval);
});
});
결론
WebSocket은 실시간 양방향 통신을 필요로 하는 애플리케이션에서 매우 유
용한 기술입니다. 채팅 애플리케이션, 실시간 데이터 스트리밍, 온라인 게임 등 다양한 분야에서 활용될 수 있습니다. JavaScript를 사용하여 클라이언트 측에서 WebSocket을 설정하고, Node.js를 사용하여 서버 측에서 WebSocket 서버를 구현함으로써, 효율적이고 실시간성을 갖춘 웹 애플리케이션을 개발할 수 있습니다.