WebSocket부터 이해하자
- Socket
- WebSocket

Socket 이란
Socket 의 개념
Socket 의 사전적 의미는 다른 부분이 들어갈 수 있도록 만들어 놓은 구멍 또는 서로 다른 것이 연결될 수 있도록 마련된 창구 를 뜻한다.

네트워크에서 Socket 은 컴퓨터 프로그램이 네트워크를 통해 데이터를 주고받을 수 있도록 하는 연결점이다. 벽에 콘센트가 없으면 전기 플러그를 꽂아 전기를 사용할 수 없듯이, 네트워크 통신에서도 송신 측 (Client Socket) 과 수신 측 (Server Socket) 모두에 소켓이 열려 있어야 그 통로를 통해 데이터가 오갈 수 있다.
Socket Programming
프로세스 간 통신 (IPC) 을 위해 소켓을 활용하는 네트워크 프로그래밍 기법이다. 서로 동일한 구조의 소켓을 사용하지만, Client Socket과 Server Socket은 역할에 따라 동작 흐름이 다르다.

Client Socket 의 처리 흐름
| 단계 | 함수 | 설명 |
|---|---|---|
| 1 | 소켓 생성 | - 연결 대상 정보(IP, Port 등)가 없는 빈 소켓을 생성 |
| 2 | 연결 요청 (connect) | - 통신 대상의 IP 주소와 포트 번호를 지정하여 연결을 요청
- 요청이 수락되어야 connect() 실행이 완료됨 |
| 3-1 | 데이터 송수신 (send) | - 클라이언트가 데이터를 보낼 시점과 크기를 직접 제어 가능 |
| 3-2 | 데이터 수신 (recv) | - 상대가 데이터를 언제, 얼마나 보낼지 알 수 없으므로, 일반적으로 별도의 스레드에서 처리 |
| 4 | 소켓 종료 (close) | - 통신이 완료되면 소켓을 닫아 연결을 종료 |
Server Socket 의 처리 흐름
| 단계 | 함수 | 설명 |
|---|---|---|
| 1 | 소켓 생성 (socket) | - 연결 대상 정보가 없는 빈 소켓을 생성 |
| 2 | 소켓과 포트 바인딩 (bind) | - 생성된 소켓에 포트 번호를 연결 - 여러 프로세스가 동시에 실행될 수 있으므로 서로 다른 포트를 사용해야 데이터가 올바른 프로세스에 전달됨 - 하나의 프로세스가 같은 포트를 공유하는 여러 소켓을 가질 수도 있음 예를 들어 채팅 서버가 여러 사용자와 동시에 통신 가능 |
| 3 | 연결 요청 대기 (listen) | - 클라이언트의 연결 요청을 받을 준비 - 요청이 들어오기 전까지 대기 상태로 있으며, 요청이 감지되면 반환됨 |
| 4 | 연결 수락 (accept) | - accept()는 실제 연결을 수립하는 단계
- 연결 요청이 수락되면 새로운 소켓을 생성하여 해당 클라이언트와의 통신 전용으로 사용
- 기존 Server Socket은 요청 수락 기능만 담당하고, 데이터 송수신은 새로 생성된 소켓이 담당 |
| 5 | 데이터 송수신 (send, recv) | - 클라이언트 소켓과 동일하게 동작 - 특히 수신은 비동기적으로 처리하기 위해 별도의 스레드에서 운영하는 경우가 많음 |
| 6 | 소켓 종료 (close) | - Server Socket은 자신의 소켓뿐 아니라, 클라이언트 연결 시 새로 생성된 소켓도 함께 관리 및 종료해야 함 |
Port 의 역할
네트워크에서 데이터를 교환할 때, 운영체제는 각 프로세스에 고유한 포트 번호를 부여하여 통신 대상을 식별한다. 데이터 전송 시 목적지 포트를 지정하면, 수신 측에서 해당 포트 번호를 가진 프로세스가 데이터를 받아 처리한다.
WebSocket 프로토콜이란
HTTP 프로토콜의 기본 통신 방식
일반적으로 가장 널리 사용되는 HTTP 프로토콜은 요청과 응답으로 구성된 단방향 통신 방식을 따른다. 클라이언트가 요청을 보내면 서버는 이를 처리한 뒤 응답을 반환하며, 응답이 완료되면 클라이언트와 서버 간 연결은 즉시 종료된다.
이러한 구조는 전통적인 웹사이트 구현에 매우 적합하다. 웹페이지를 제공하는 경우, 서버가 클라이언트와 연결을 지속적으로 유지할 필요가 없기 때문이다. 덕분에 서버는 적은 하드웨어 자원으로도 다수의 클라이언트 요청을 효율적으로 처리할 수 있다.
HTTP 의 실시간 통신 제약
HTTP 프로토콜로 실시간 양방향 상호작용 애플리케이션을 구현하려면 두 가지 주요 제약이 존재한다.
1. HTTP 에서는 항상 클라이언트가 연결을 시작한다.
서버는 클라이언트의 요청이 오기 전까지 아무런 데이터를 보낼 수 없으며, 서버에서 먼저 이벤트를 전달하는 것이 불가능하다. 이 때문에 서버 이벤트를 클라이언트에게 알리기 위해 Polling(주기적 요청)을 사용하지만, 이벤트가 드문 경우 불필요한 호출과 리소스 낭비가 발생한다.
2. HTTP 연결이 유지되지 않아 상태나 문맥을 유지하기 어렵다.
HTTP 연결은 요청-응답 후 즉시 종료되는 단방향 연결이므로, 상태나 문맥(Context)을 유지하기 어렵다. 또한 HTTP 헤더의 크기가 크기 때문에, 짧은 메시지를 자주 주고받는 서비스에서는 네트워크 대역폭 낭비가 심해진다.
HTTP 방식의 실시간 통신 시도
WebSocket 이 나오기 전에는 HTTP 를 사용하여 실시간 통신을 구현하려는 시도가 있었다. 하지만 모두 요청/응답 헤더가 불필요하게 크다는 단점이 있었다.
1. HTTP Polling
클라이언트가 1 초, 10 초 등 주기적으로 서버에 요청을 보내 새로운 이벤트를 확인한다.

| 구분 | 내용 |
|---|---|
| 장점 | - 클라이언트와 서버 모두 구현이 간단함 |
| 단점 | - 실시간성이 보장되지 않는다. 메시지가 도착하더라도 다음 요청 주기까지 대기해야 함 - 응답 여부와 무관하게 주기적으로 요청을 보내므로, 서버에 불필요한 부하가 발생 |
2. HTTP Long Polling
클라이언트가 서버로 요청을 보내고, 이벤트가 발생할 때까지 기다린다. 이벤트가 발생하면 서버가 응답을 보내고, 클라이언트는 즉시 다시 요청을 보내 연결을 유지한다.

| 구분 | 내용 |
|---|---|
| 장점 | - Polling에 비해 요청 횟수가 줄어들어 네트워크 트래픽이 감소함 |
| 단점 | - 이벤트 발생 빈도가 높을 경우, 결과적으로 Polling과 요청량이 큰 차이가 없음 - 여러 클라이언트에서 동시에 이벤트가 발생하면 서버에 부하가 집중될 수 있음 |
3. HTTP Streaming (SSE)
클라이언트가 서버로 요청을 보내 연결을 맺은 후, 이벤트가 발생해도 연결을 끊지 않는다.

| 구분 | 내용 |
|---|---|
| 장점 | - 서버는 지속적으로 클라이언트로 메시지를 전송 가능 |
| 단점 | - 클라이언트는 스트리밍 중 동일한 TCP 포트에서 읽기와 쓰기를 동시에 수행할 수 없어, 추가 요청을 보낼 수 없음 - 요청을 보내려면 별도의 포트를 사용해야 함 - 클라이언트 측에서 문제가 발생해도, 서버는 그 사실을 즉시 감지하기 어려움 |
WebSocket
웹소켓은 기존 통신 방식의 한계를 극복하고, 클라이언트와 서버 간 효율적인 실시간 양방향 통신을 제공하는 프로토콜이다. 이를 통해 하나의 서버가 여러 클라이언트와 동시에 데이터를 주고받을 수 있으며, 빠르고 안정적인 실시간 메시지 교환이 가능하다.
WebSocket은 이름에 Socket이 포함되어 있지만, 앞서 설명한 네트워크 소켓(TCP Socket)과는 개념적으로 다르다. WebSocket은 웹 환경에서 두 프로그램이 메시지를 교환하기 위한 응용 계층 프로토콜이며, 브라우저와 서버 간 실시간 통신을 위해 설계되었다.
| 구분 | 설명 |
|---|---|
| Socket | - TCP/IP 프로토콜을 기반으로 동작 - 클라이언트와 서버 간 지속적인 연결을 유지하는 실시간 통신 방식 |
| WebSocket | - HTTP 프로토콜을 사용하는 웹 환경에서 실시간 통신을 구현하기 위해 등장한 프로토콜 - 초기에는 HTTP 핸드셰이크를 수행한 후, 연결을 WebSocket 프로토콜로 업그레이드하여 양방향 실시간 통신을 가능하게 함 |
또한 OSI 7계층 구조에서 TCP는 4계층(전송 계층)에 위치하며, WebSocket은 7계층(응용 계층)에서 HTTP 핸드셰이크 이후 TCP 연결을 업그레이드하여 사용한다. 이 덕분에 WebSocket은 TCP의 순서 보장·재전송 등 신뢰성 있는 특성을 그대로 활용할 수 있다.
웹소켓의 한계
WebSocket은 실시간 양방향 통신을 위한 강력한 기술이지만, 몇 가지 제약과 한계를 가진다.
| 단점 | 설명 |
|---|---|
| 구현 복잡성 | - HTTP 기반의 Polling, Long Polling, Streaming 방식보다 설계와 구현이 상대적으로 복잡하다. |
| 호환성 문제 | - WebSocket은 HTML5 이후 등장한 기술이기 때문에, HTML5 이전 환경에서는 적용이 어렵다. - 예를 들어, Internet Explorer는 버전 10 이상부터 WebSocket을 지원한다. |
| Stateful 특성 | - WebSocket은 Stateful Protocol로, 클라이언트와 서버가 연결 상태를 지속적으로 유지해야 한다. - 연결을 유지하는 것만으로도 네트워크 및 서버 자원을 소모하므로, 일정한 운영 비용이 발생한다. |
| 비정상 종료 대응 필요 | - 네트워크 장애나 브라우저 종료 등으로 인해 예기치 않게 연결이 끊어질 수 있으므로, 이에 대한 복구 및 재연결 전략이 반드시 필요하다. |
Stateful과 Stateless
웹소켓 통신 과정
핸드셰이크
WebSocket은 HTTP와 완전히 별개의 프로토콜이 아니라, HTTP를 기반으로 업그레이드되는 형태의 통신이다.
클라이언트가 WebSocket 연결을 시작할 때, 먼저 서버에 HTTP GET 요청을 보낸다. 이 요청에는 Connection: Upgrade 와 Upgrade: websocket 같은 같은 특수 헤더가 포함된다.
GET /chat HTTP/1.1
Host: www.test.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13서버가 WebSocket을 지원한다면, 다음과 같은 응답을 보내며 프로토콜 업그레이드(HTTP → WebSocket)를 완료한다.
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=이 과정을 핸드셰이크(Handshake)라고 하며, 완료되는 즉시 클라이언트와 서버는 WebSocket 프로토콜을 이용한 양방향 통신을 시작할 수 있다.
데이터 전송
핸드셰이크가 완료되면, 클라이언트와 서버는 메시지를 Frame 단위로 주고받는다. 하나의 메시지는 여러 개의 데이터 조각(Frame)으로 구성될 수 있으며, 브라우저 환경에서는 send() 메서드를 통해 텍스트 또는 바이너리 데이터를 전송할 수 있다.
Frame 의 종류
연결 종료
데이터 송수신이 완료되면, 클라이언트와 서버 모두 연결을 종료하기 위한 Frame 을 전송할 수 있다. 연결을 종료하고 싶은 쪽에서 Close Frame 을 보내면, 상대쪽에서 응답으로 Close Frame 을 전송한다. 이렇게 WebSocket 연결이 종료된다.
데이터 송수신이 완료되면, 클라이언트나 서버 중 어느 한쪽이 Close Frame을 전송해 연결 종료를 요청한다. 상대가 이에 대한 응답으로 Close Frame을 다시 보내면, WebSocket 연결이 완전히 종료된다.
WebSocket 클라이언트
브라우저 WebSocket 클라이언트
대부분의 WebSocket 클라이언트는 JavaScript를 실행할 수 있는 브라우저 환경에서 동작한다. 브라우저에서는 WebSocket 표준 API를 사용해 손쉽게 클라이언트 코드를 작성할 수 있다.
서버와 통신하려면 WebSocket 클래스를 이용해 객체를 생성하며, ws:// 또는 wss:// 프로토콜을 사용하는 서버 URL을 생성자에 전달한다.
const socket = new WebSocket("ws://www.test.com/chat");객체가 성공적으로 생성되면 핸드셰이크가 완료되고 서버와 메시지 교환이 가능해진다.
이벤트 처리
웹소켓 객체로 서버에서 발생하는 4 가지 이벤트 (open, message, error, close) 를 처리할 수 있다. 특히 message 이벤트를 통해 서버 메시지를 자주 받는다.
이벤트 핸들러는 addEventListener 메서드로 설정한다.
socket.addEventListener("open", (event) => {
console.log("서버와 연결을 맺었습니다.");
});
socket.addEventListener("message", (event) => {
console.log("서버에서 받은 메시지:", event.data);
});
socket.addEventListener("error", (event) => {
console.error("에러:", event);
});
socket.addEventListener("close", (event) => {
console.log("서버와 연결을 끊었습니다.");
});on<이벤트> 속성에 직접 함수를 할당하는 방법도 있다.
socket.onopen = (event) => {
console.log("서버와 연결을 맺었습니다.");
};
socket.onmessage = (event) => {
console.log("서버에서 받은 메시지:", event.data);
};
socket.onerror = (event) => {
console.error("에러:", event);
};
socket.onclose = (event) => {
console.log("서버와 연결을 끊었습니다.");
};서버로 메시지를 보낼 때는 send() 메서드를 사용한다.
socket.send("하이 웹소켓!");브라우저 호환성
WebSocket이 실시간 양방향 통신의 표준 기술로 자리 잡은 지는 오래되었으며, 현재 대부분의 모던 브라우저에서 WebSocket API를 기본적으로 지원한다.
그러나 WebSocket을 지원하지 않는 구형 브라우저를 함께 대응해야 하는 경우에는 Socket.IO와 같은 호환성 라이브러리를 사용하는 것이 일반적이다. Socket.IO는 WebSocket이 가능한 환경에서는 WebSocket 방식으로 통신하고, 그렇지 않은 환경에서는 HTTP 기반 통신(Long Polling 등)을 이용해 유사한 실시간 동작을 구현한다.
웹소켓 한계 극복 라이브러리
WebSocket의 한계, 특히 HTML5 이전 기술 환경에서 사용할 수 없다는 제약을 보완하기 위해 여러 라이브러리가 등장했다. 그중 대표적인 기술이 Socket.IO이다.
Socket.IO
Socket.IO는 Node.js 기반의 실시간 통신 라이브러리로, 브라우저 종류나 기술 지원 여부와 무관하게 일관된 실시간 통신 환경을 제공한다.
즉, WebSocket을 지원하지 않는 구형 브라우저에서도 HTTP 기반의 대체 통신 방식(Long Polling 등)을 통해 유사한 동작을 구현할 수 있다.
동작 방식
특징 및 제약사항
SockJS
SockJS는 Socket.IO와 마찬가지로 브라우저 종류와 관계없이 실시간 통신을 구현할 수 있도록 설계된 라이브러리이다. 즉, WebSocket을 지원하지 않는 환경에서도 안정적인 통신을 유지할 수 있도록 다양한 메커니즘을 제공한다.
동작 방식
Socket.IO 와의 차이점
Spring Framework에서는 WebSocket 사용 시 구형 브라우저 대응을 위해 SockJS 프로토콜을 채택하고 있다. SockJS 프로토콜은 브라우저 내의 SockJS-client와 서버 측 SockJS-server 간 통신 규약으로, 브라우저 호환성을 최대한 확보하도록 설계되었다.
따라서 백엔드에서 Spring Framework를 사용한다면, 프론트엔드 또한 SockJS-client를 사용하는 것이 자연스럽고 호환성이 높다.
STOMP 프로토콜
STOMP 란?
STOMP는 이름 그대로 텍스트 기반의 간단한 메시징 프로토콜이다. WebSocket은 단순히 양방향 데이터 전송을 위한 통신 채널만 제공할 뿐, 메시지의 구조나 의미를 규정하지 않는다.
따라서 WebSocket만으로 채팅 서비스를 구현하려면 다음과 같은 요소를 직접 정의해야 한다. 이러한 불편함을 해결하고 메시지 송수신 과정을 표준화하기 위해 만들어진 것이 STOMP이다.
STOMP 의 역할
STOMP는 WebSocket 위에서 동작하며, 클라이언트와 서버 간 메시지의 형식, 유형, 처리 절차를 정의한다. 덕분에 복잡한 메시지 교환 과정을 단순화하고 효율적으로 관리할 수 있다.
STOMP 의 장점
StompJS
StompJS 는 클라이언트 측에서 STOMP 프로토콜을 쉽게 사용할 수 있도록 구현된 JavaScript 라이브러리
다. 이를 이용하면 브라우저나 프론트엔드 환경에서도 STOMP 기반 WebSocket 통신을 간단히 구현할 수 있다.
참고자료