WebSocket은 클라이언트(주로 브라우저)와 서버 간에 지속적이고 양방향(Full-duplex) 통신을 제공하는 네트워크 프로토콜입니다.
HTTP의 요청-응답 모델과 달리, 한 번 연결이 성립되면 양쪽에서 자유롭게 데이터를 주고받을 수 있어 실시간성이 중요한 다양한 서비스(채팅, 알림, 게임, 주식 시세 등)에 널리 사용됩니다.
클라이언트가 HTTP 프로토콜로 서버에 WebSocket 연결을 요청합니다.
서버가 이를 수락하면, HTTP 프로토콜에서 WebSocket 프로토콜로 업그레이드(Upgrade)됩니다.
양방향으로 텍스트/바이너리 데이터를 프레임 단위로 주고받습니다.
서버가 먼저 클라이언트로 메시지를 push할 수도 있습니다.
Full-duplex, Low-latency
양방향, 저지연 통신(HTTP Polling, SSE 대비 오버헤드가 적음)
단일 연결
한 번 연결 후, 다수의 메시지를 주고받으며 추가 연결/해제 과정이 없음
실시간성
서버에서 클라이언트로 즉시 데이터 전송 가능(예: 알림, 실시간 채팅 등)
표준 포트 사용
ws://(80), wss://(443) 포트를 사용해 방화벽 환경에서도 활용 가능
브라우저 지원
Chrome, Firefox, Edge, Safari 등 대부분의 최신 브라우저에서 기본 지원
분야 | 예시 및 설명 |
---|---|
실시간 채팅 | 메신저, 라이브 방송 채팅, 고객센터 채팅 등 |
데이터 방송 | 실시간 주식/코인 시세, 스포츠 점수, 뉴스 속보 |
동기화/협업 | Figma, Google Docs 등 실시간 공동 편집 |
게임/IoT | 멀티플레이어 게임, IoT 기기 상태 모니터링 |
알림/푸시 | 실시간 알림, 상태 변화 알림 등 |
const socket = new WebSocket('wss://example.com/socket');
socket.onopen = () => {
console.log('WebSocket 연결 완료');
socket.send('Hello Server!');
};
socket.onmessage = (event) => {
console.log('서버로부터 메시지:', event.data);
};
socket.onclose = () => {
console.log('WebSocket 연결 종료');
};
socket.onerror = (error) => {
console.error('WebSocket 에러:', error);
};
ws://
는 비암호화, wss://
는 암호화된 연결에 사용됩니다.implementation 'org.springframework.boot:spring-boot-starter-websocket'
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic"); // 구독 경로
config.setApplicationDestinationPrefixes("/app"); // 메시지 송신 경로
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-chat").setAllowedOrigins("*").withSockJS(); // 엔드포인트 등록
}
}
@EnableWebSocketMessageBroker
로 STOMP 기반 메시지 브로커 활성화
SockJS 지원으로 WebSocket 미지원 환경에서도 fallback 가능
public class ChatMessage {
private String from;
private String text;
// getter, setter
}
@Controller
public class ChatController {
@MessageMapping("/chat")
@SendTo("/topic/messages")
public ChatMessage send(ChatMessage message) {
return message;
}
}
/app/chat
으로 메시지 전송 시, /topic/messages
를 구독한 모든 클라이언트에게 전달<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs@2/dist/stomp.min.js"></script>
<script>
var socket = new SockJS('/ws-chat');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
stompClient.subscribe('/topic/messages', function(message) {
console.log('수신:', JSON.parse(message.body));
});
stompClient.send("/app/chat", {}, JSON.stringify({from: "user", text: "안녕하세요!"}));
});
</script>
보안: 항상 wss://
(TLS) 프로토콜 사용 권장
하트비트(Heartbeat): 주기적 ping/pong 메시지로 연결 유지
에러 핸들링: 연결 실패/종료/재연결 처리 로직 구현
연결 제한: 서버 리소스 보호를 위해 동시 연결 수 제한
구분 | HTTP | WebSocket |
---|---|---|
통신 방향 | 단방향 (클라이언트 → 서버) | 양방향 (클라이언트 ↔ 서버, Full-duplex) |
연결 방식 | 요청-응답 후 연결 종료, 매 요청마다 새 연결 | 한 번 연결 후 지속적으로 연결 유지 |
오버헤드 | 높음 (매 요청마다 헤더 포함, 연결/해제 반복) | 낮음 (초기 핸드셰이크 후 작은 프레임만 사용) |
실시간성 | 낮음 (폴링, 롱폴링 필요) | 매우 높음 (즉시 데이터 송수신 가능) |
상태 관리 | 무상태 (Stateless) | 상태 유지 (Stateful, 연결 지속) |
주요 활용 사례 | 웹페이지, API, 파일 다운로드, 정적 데이터 | 채팅, 알림, 게임, 실시간 데이터 방송 등 |
데이터 형식 | 주로 텍스트 (HTML, JSON, XML) | 텍스트/바이너리 모두 지원 |
보안 프로토콜 | HTTPS (443) | WSS (443) |