웹소켓이란?
WebSocket은 클라이언트와 서버 간에 지속적인 연결을 유지하면서 실시간 양방향 통신을 가능하게 해주는 프로토콜.
HTTP와는 다르게, 한번 연결이 맺어지면 클라이언트나 서버 어느 쪽이든 자유롭게 데이터를 주고받을 수 있음.
- HTTP: 기본 포트는 80번
- HTTPS: 기본 포트는 443번
- WebSocket (ws): 기본 포트는 80번
- WebSocket Secure (wss): 기본 포트는 443번
- 초기 연결은 HTTP로 시작 → 그 후 WebSocket 프로토콜로 업그레이드
얼마 전 구현한 웹소켓 채팅을 예를 들어보자.
const ws = new WebSocket("ws://" + tempLocation + "/ws/chat");
// 여기서 tempLocation 에는 "localhost:8080" 을 넣어주었다.
위 코드에서 웹소켓 연결을 열어주며 new WebSocket을 생성할 때 ws:// 를 붙여주었다.
ws:// 는 웹소켓 연결을 만들 때 웹소켓 프로토콜임을 명시해 주기 위해 반드시 필요함.
코드의 의미는 웹소켓 서버가 localhost:8080 포트에서 웹소켓 연결을 기다리고 있다고 해석가능하다.
백엔드 서버에서는 다음과 같이 WebSocketConfig 클래스를 만들어 주었는데,
이 클래스파일을 통해 웹소켓 설정을 하는 것이다.
웹소켓은 기본적으로 HTTP는 80번 포트에서 실행되지만, 스프링부트가 기본적으로 웹 서버를 8080번 포트에서 구동하고 있다. 즉, localhost:8080은 HTTP 서버의 포트이고, 웹소켓은 이 서버를 통해 연결된다.
package jpabasic.toyvaserver.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration // 스프링 설정 클래스임을 명시
@EnableWebSocket // WebSocket 기능을 활성화
public class WebSocketConfig implements WebSocketConfigurer {
private final WebSocketHandler webSocketHandler;
public WebSocketConfig() {
webSocketHandler = new ChatWebSocketHandler();
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// WebSocket 엔드포인트를 "/ws/chat"으로 설정
// (ws://localhost:8080/ws/chat 로 요청 들어오면, WebSocket 통신 시작)
registry.addHandler(webSocketHandler, "/ws/chat")
.setAllowedOrigins("http://localhost:3000"); // ws 에 대한CORS 허용
}
}
웹소켓 연결 과정은?
웹소켓 핸드셰이크를 통해 연결함.
웹소켓 연결은 HTTP 프로토콜을 기반으로 시작한다.
초기 요청은 HTTP 요청으로 전송되며, 이를 웹소켓 핸드셰이크라고 부름.
1-1 클라이언트에서 서버로 요청
클라이언트가 웹소켓 서버에 연결을 요청할 때, HTTP GET 요청을 보냄.
이 요청에는 웹소켓 연결을 시작하고자 하는 의도가 담겨있음.
예를 들어 const socket = new WebSocket("ws://localhost:8080/ws/chat");
웹소켓 클라이언트는 ws://localhost:8080/ws/chat로 아래 헤더들을 포함한 HTTP GET 요청을 보낸다.
- Upgrade: websocket: HTTP 프로토콜에서 웹소켓 프로토콜로 업그레이드하려는 요청
- Connection: Upgrade: 연결을 업그레이드하려는 요청
- Sec-WebSocket-Key: 클라이언트가 보내는 임의의 키 값 (서버가 응답을 생성할 때 사용)
- Sec-WebSocket-Version: 웹소켓 프로토콜 버전
1-2 서버의 응답
서버는 클라이언트의 요청을 처리하고, HTTP 응답을 보내면서 웹소켓 연결을 승인한다.
서버는 요청 헤더의 정보를 바탕으로 웹소켓 연결을 설정하고, 101 Switching Protocols 상태 코드로 응답함.
서버의 응답 헤더 예시:
- HTTP/1.1 101 Switching Protocols: 웹소켓 연결을 수락하는 응답 상태 코드
- Upgrade: websocket: 서버가 HTTP에서 웹소켓으로 업그레이드되었음을 알림
- Connection: Upgrade: 연결이 업그레이드되었음을 알림
- Sec-WebSocket-Accept: 서버가 클라이언트의 Sec-WebSocket-Key에 대한 응답을 포함 (해시 값)
2. 연결 완료되고 양방향 통신시작
핸드셰이크가 성공적으로 완료되면, HTTP 연결이 웹소켓 연결로, 지속적인 양방향 연결로 전환됨.
이 상태에서 클라이언트와 서버는 데이터를 실시간으로 주고받을 수 있게 됨.
3. 클라이언트와 서버가 실시간으로 메시지 주고받음
4. 클라이언트 혹은 서버가 연결 종료하며 종료됨.
[ ]
웹소켓은 어디에 사용될까?
웹소켓은 다음과 같이 실시간성이 중요한 서비스에서 주로 사용함
- 채팅 애플리케이션 (1:1, 그룹 채팅)
- 실시간 알림 (푸시 알림, SNS 알림 등)
- 실시간 협업 도구 (예: Google Docs)
- 주식/코인 시세 실시간 반영
- 온라인 게임 (실시간 위치 전송 등)
- 라이브 방송/댓글 시스템
채팅을 왜 웹소켓으로 구현할까?
우선 채팅은 실시간 양방향 통신이 핵심인 서비스인데,
웹소켓은 실시간 양방향 통신에 적합한 기술로, 지연시간을 최소화하고 효율적으로 데이터를 주고받을 수 있게 해 준다.
HTTP 방식은 주기적인 요청을 보내는 방식으로 실시간성을 구현하는 데 한계가 있지만, 웹소켓은 연결을 유지한 채 클라이언트와 서버가 자유롭게 메시지를 주고받을 수 있어 실시간 서비스에서 중요한 역할을 함.
채팅 같은 서비스에서는 빠르고 즉각적인 반응이 요구되므로, 웹소켓이 거의 필수임.
- 비동기 처리:
웹소켓은 비동기적으로 데이터를 처리할 수 있기 때문에, 클라이언트와 서버 간의 실시간 통신이 가능.
클라이언트가 메시지를 보낼 때마다 서버가 그 메시지를 바로 받게 되며,
서버는 그 메시지를 지체 없이 다른 클라이언트로 전송가능.
->
서버가 클라이언트의 요청 안 기다리고, 필요한 순간에 메시지를 자동으로 푸시할 수 있는 구조라서, 실시간성 굿굿. - 속도와 효율성:
예를 들어, 채팅 애플리케이션에서 수많은 사용자가 동시에 메시지를 주고받을 때, 웹소켓은 메시지 전송 속도와 응답 속도를 모두 개선할 수 있음. 이를 통해 수많은 사용자에게 실시간으로 메시지를 전달할 수 있어, 전체 시스템의 확장성 또한 좋아짐.
- HTTP 방식의 한계:
일반적인 HTTP는 요청-응답 구조라, 실시간으로 클라이언트에게 알리는 건 힘듦.
클라이언트가 계속 요청(polling) 해야 하는 비효율적인 방식 - 웹소켓은 연결 유지:
한 번 연결 후, 서버가 클라이언트에게 알아서 메시지를 push 할 수 있음. - 지연시간 최소화:
연결 유지 상태에서 빠르게 데이터를 주고받을 수 있음.
웹소켓 없이도 채팅 구현 가능할까?
이론적으로는 가능 하지만 비효율적이다.
대표적인 대안으로 Polling 방식 그리고 SSE (Server-Sent Events) 방식으로 구현 가능.
1. Long Polling
클라이언트가 일정 주기로 서버에 메시지를 요청하는 방식.
실시간성이 떨어지고, 너무 자주 요청하면 서버에 불필요한 부하가 발생함
- 클라이언트가 요청을 보내고, 서버가 응답을 최대한 늦게 보내는 방식
- 클라이언트가 응답을 받으면 곧바로 다시 요청 → 무한 루프
- 단점: 서버 자원 소모 많고, 반응 속도 떨어짐
2. Short Polling
서버가 응답을 보낼 때까지 요청을 보류하고, 응답 후 클라이언트가 다시 요청을 보내는 방식.
실시간성은 어느 정도 확보되지만, 매번 요청-응답을 반복하므로 서버 리소스를 많이 소모함
- 주기적으로 일정 시간마다 요청 → 새로운 메시지 있으면 응답
- 단점: 실시간성 떨어지고, 트래픽 낭비 심함
3. SSE (Server-Sent Events)
서버에서 클라이언트로만 데이터를 푸시할 수 있는 방식.
단방향 통신에만 적합하고, 클라이언트에서 서버로 보내는 메시지는 별도의 HTTP 요청으로 처리해야 함
- 서버 → 클라이언트 방향으로만 단방향 실시간 전송 가능
- 양방향 채팅에는 부적합
그래서 결론적으로 실시간성과 효율성을 고려하면 웹소켓이 가장 적합하다~
'정리' 카테고리의 다른 글
| CICD와 무중단 배포 (0) | 2025.04.15 |
|---|---|
| java, spring 개념 정리 (0) | 2025.04.13 |
| OSI 7계층과 존재 이유, TCP/IP 4계층 (0) | 2025.04.11 |
| CORS와 SOP (0) | 2025.04.10 |
| Https와 SSL HandShake (0) | 2025.04.09 |