HTTP 통신을 이용하면 클라이언트에서 서버에 요청을 보내야만 서버에 응답을 할 수 있다.
즉, 서버에서는 요청을 받지 않으면 클라이언트에 통신할 수 없는 것이다.
이러한 문제점을 해결하기 위해서 양방향으로 통신할 수 있는 웹 소켓(Web Socket) 통신을 이용해야 한다.
채팅, 문의, 알림과 같은 ‘실시간’ 이라는 키워드가 필요한 기능들은 HTTP 통신을 사용해서 구현할 수 없다. (계속된 요청 한계)
이러한 기능을 제작할 때 소켓 통신을 이용해야 한다.
| 종류 | 설명 |
|---|---|
| 폴링(polling) | - 단방향 - 클라이언트 -> 서버 - 클라이언트에서 주기적으로 서버에 업데이트 있는 지 확인하는 요청을 보냄 |
| 웹 소켓 (web Socket) |
- 양방향 - 클라이언트 <-> 서버 - 한 번 웹 소켓을 연결하면 계속 연결된 상태로 있어서 따로 업데이트가 있는지 요청을 보낼 필요가 없음 - node의 모듈 및 라이브러리 : ws, Socket.IO |

1. 연결 설정 (Connection Establishment)
1-1. 핸드셰이크 요청 (Handshake Request)
1-2. 핸드셰이크 응답 (Handshake Response)
2. 데이터 전송 (Data Transfer)
3. 연결 종료 (Connection Termination)
3-1. 종료 핸드셰이크 (Close Handshake)
3-2. 비정상 종료 (Abnormal Termination)

위 사용 과정에 대해서 자세히 알아보자.
1. 연결 설정 (Connection Establishment)
1-1. 핸드셰이크 요청 (Handshake Request)
: 클라이언트는 HTTP를 사용하여 웹소켓 서버에 연결 요청을 보냅니다.
이 요청은 업그레이드(Upgrade) 헤더를 포함하여 웹소켓 프로토콜로의 전환을 요청합니다.
//예시 요청 헤더
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
1-2. 핸드셰이크 응답 (Handshake Response)
: 서버는 클라이언트의 요청을 검토한 후, 연결을 승인하는 응답을 반환합니다.
이 응답도 업그레이드 헤더를 포함합니다.
//예시 요청 헤더
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
핸드쉐이크(HandShake)
- 정보기술과 전기통신 및 관련 분야에서 채널에 대한 정상적인 통신이 시작되기 전에 두 개의 실체 간에 확립된 통신 채널의 변수를 동적으로 설정하는 자동화된 협상 과정
- 정상적인 정보 전송 이전에 이루어짐
2. 데이터 전송 (Data Transfer)
Node.js - Express 설치
https://velog.io/@yedi/Node.js-Express
//index.html -> 클라이언트
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h4>채팅페이지입니다.</h4>
<button id="send" onclick="socket.send('안녕하세요')">메세지 보내기</button>
<script>
//웹소켓 열어달라고 서버에게 부탁하는 코드
//WebSocket 연결 요청의 경우 http://가 아닌 ws://나 wws:// 작성
let socket = new WebSocket("ws://localhost:8081");
</script>
</body>
</html>
//server.js -> 서버
const express = require('express');
const app = express();
app.use("/", function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.listen(8080);
//웹소켓 열기
const WebSocket = require('ws');
const socket = new WebSocket.Server({
port: 8081
});
//웹소켓으로 오는 유저 메세지를 받으려면
socket.on('connection', (ws, req) => {
ws.on('message', (msg) => {
console.log('사용자가 보낸 것 : ' + msg);
//웹소켓으로 서버 -> 유저 메세지 보내기
ws.send('잘가');
});
});
3. 연결 종료 (Connection Termination)
3-1. 종료 핸드셰이크 (Close Handshake)
: 클라이언트 또는 서버는 연결을 종료할 수 있습니다.
종료 요청은 종료 프레임(close frame)을 통해 전송되며, 상대방은 이를 수신한 후 응답 프레임을 전송하여 연결을 정상적으로 종료합니다.
//server.js -> 서버
socket.on('connection', (ws, req) => {
// 연결 종료
socket.on('close', () => {
console.log('연결 종료');
});
});
3-2. 비정상 종료 (Abnormal Termination)
: 네트워크 문제 등으로 인해 비정상적으로 연결이 종료될 수 있습니다.
이 경우, 클라이언트와 서버는 연결이 끊어진 후 재연결을 시도할 수 있습니다.
//server,js -> 서버
socket.on('connection', (ws, req) => {
// 에러
socket.on('error', (error) => {
console.log('에러 발생');
});
});
웹소켓 연결의 예시 전체 흐름
https://www.youtube.com/watch?v=yXPCg5eupGM
https://www.chanstory.dev/blog/post/26
https://velog.io/@delay100/Socket
https://hudi.blog/websocket-with-nodejs/