반응형
1. 개요 - “실시간 통신, 어떤 방식을 써야 할까?”
채팅, 주식 차트, 알림 서비스처럼 실시간 업데이트가 필요한 서비스를 만들다 보면
“웹소켓을 써야 할까? 아니면 SSE(Server-Sent Events)가 더 나을까?”
라는 고민을 하게 됩니다.
두 방식 모두 서버에서 클라이언트로 실시간 데이터를 푸시(push) 하지만,
기술적인 구조와 사용 목적은 확실히 다릅니다.
2. WebSocket과 SSE 핵심 비교표
| 구분 | WebSocket | SSE (Server-Sent Events) |
| 연결 방식 | 양방향 (Full Duplex) | 단방향 (서버 → 클라이언트) |
| 프로토콜 | ws://, wss:// | http://, https:// (기존 HTTP 유지) |
| 데이터 전송 | 양쪽 모두 실시간 송수신 가능 | 서버가 클라이언트에 이벤트 push |
| 브라우저 지원 | 대부분 지원 (IE 제외) | 대부분 지원 (IE, Edge 구버전 제외) |
| 연결 유지 | 지속 연결 (Upgrade Handshake) | HTTP 스트림 유지 |
| 재연결 | 수동 구현 필요 | 기본 자동 재연결 지원 |
| 전송 포맷 | 자유 (텍스트, 바이너리) | 텍스트 기반 (EventStream) |
| 서버 부하 | 낮음 (효율적 연결) | 다수 클라이언트 시 부하↑ |
| 대표 활용 | 채팅, 실시간 게임, 주식 트레이딩 | 실시간 알림, 뉴스 피드, 로그 스트림 |
3. WebSocket 동작 원리
1️. 클라이언트 → 서버
- 일반 HTTP로
Upgrade: websocket요청 - 서버가 이를 승인하면 WebSocket 연결로 전환
2️. 양방향 통신 시작
- 이후부터는 TCP 연결 기반 실시간 통신
- HTTP 헤더 오버헤드가 없음
3️. 프레임(Frame) 단위로 송수신
- 메시지는 JSON, 이진 데이터, 텍스트 등 자유롭게 전송 가능
- 웹소켓 예시 코드 (JavaScript)
const socket = new WebSocket("wss://example.com/chat");
socket.onopen = () => console.log("연결 성공!");
socket.onmessage = (event) => console.log("서버 메시지:", event.data);
socket.onclose = () => console.log("연결 종료");
socket.send(JSON.stringify({ user: "kim", message: "안녕하세요!" }));
- 대표 활용 서비스
- 실시간 채팅 (KakaoTalk Web, Discord)
- 주식/코인 시세 스트리밍
- 온라인 게임
- IoT 데이터 전송
4. SSE(Server-Sent Events) 동작 원리
SSE는 말 그대로 서버가 이벤트를 “보낸다(Server-Sent)”는 개념입니다.
HTTP 연결을 하나만 유지하면서 지속적으로 데이터를 푸시합니다.
단방향이지만, 가볍고 구현이 매우 쉽습니다.
1️. 클라이언트가 /events에 GET 요청
2️. 서버는 응답 헤더에 Content-Type: text/event-stream 설정
3️. 연결을 닫지 않고, 주기적으로 이벤트를 전송
- SSE 클라이언트 예제 (JavaScript)
const eventSource = new EventSource("https://example.com/events");
eventSource.onmessage = (event) => {
console.log("새 이벤트:", event.data);
};
eventSource.onerror = (err) => {
console.error("연결 오류", err);
};
- SSE 서버 예시 (Spring Boot)
@GetMapping("/events")
public SseEmitter stream() {
SseEmitter emitter = new SseEmitter();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
emitter.send(SseEmitter.event()
.name("news")
.data("Breaking News " + i));
Thread.sleep(1000);
}
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
- 대표 활용 서비스
- 실시간 알림(Notification)
- 뉴스/주가 피드
- 실시간 로그 모니터링
- 브라우저 기반 모니터링 대시보드
5. WebSocket vs SSE 선택 기준
| 상황 | 추천 방식 | 이유 |
| 실시간 채팅, 게임, IoT | WebSocket | 양방향 통신 필수 |
| 실시간 알림, 대시보드 | SSE | 구현 단순, HTTP 기반 |
| 방화벽/프록시 환경 | SSE | HTTP 사용으로 통과 용이 |
| 모바일/저전력 환경 | SSE | 유지비용 적음 |
| 바이너리 전송 필요 | WebSocket | JSON 외 데이터 가능 |
| 확장성(분산 서버) | WebSocket | 효율적 연결 유지 |
| 한 줄 요약 : “양방향이면 WebSocket, 단방향 알림이면 SSE” |
6. 보안 및 스케일링 고려사항
| 구분 | 고려사항 | 설명 |
|---|---|---|
| HTTPS 필수 | (필수) | 브라우저에서 혼합 콘텐츠 차단 방지 |
| 인증 처리 | 헤더 토큰 / 쿠키 | WebSocket은 초기 Handshake 시 토큰 전달 |
| 서버 확장 | Redis Pub/Sub, Kafka | 여러 서버 간 실시간 이벤트 공유 |
| 부하 분산 | Sticky Session | WebSocket 연결 유지 필요 |
| 재연결 처리 | SSE 기본 지원 / WS 수동 | WS는 JS에서 재연결 로직 직접 구현 필요 |
7. WebSocket + SSE 혼합 사용 전략
대규모 시스템에서는 두 기술을 혼합해서 쓰는 경우도 많습니다.
| 시나리오 | 구조 |
| 채팅 메시지 전송 | WebSocket (양방향 통신) |
| 채팅방 알림(접속, 퇴장, 시스템 메시지) | SSE (단방향 이벤트 스트림) |
| 관리자 대시보드 로그 | SSE |
| 사용자 입력 실시간 반영 | WebSocket |
예를 들어, 채팅 앱이라면 WebSocket으로 “사용자 메시지”를 주고받고, SSE로 “공지/알림/상태 변화”를 브로드캐스트하면 성능과 유지보수 모두 효율적입니다.
8. 실무자가 꼭 알아야 할 팁
- SSE는 HTTP 기반이라 프록시, 로드밸런서, CORS 제약이 적음
- WebSocket은 프레임 단위 통신이라 전송 효율 우수하지만, 연결 유지 비용이 있음
- 모바일 네트워크에서는 연결 유지 비용이 더 크기 때문에, 단순 알림용이라면 SSE가 유리
- Kubernetes / Nginx 환경에서는 WebSocket Upgrade 헤더(
Connection: Upgrade,Upgrade: websocket) 설정이 필요함
10. 요약 및 결론
- 예시 아키텍처 비교 (시각적 요약)
[ WebSocket 구조 ]
Client <--> WS Server (양방향 실시간)
↳ 메시지/명령/입력 처리
[ SSE 구조 ]
Client <-- HTTP Stream <-- Server
↳ 알림, 브로드캐스트, 로그
- 어떤 상황에 어떤 기술을 써야 할까?
| 상황 | 추천 | 이유 |
| 사용자 상호작용(채팅, IoT, 게임) | WebSocket | 양방향 데이터 필요 |
| 서버 알림(주식, 알림, 로그) | SSE | 구현 간단, HTTP 호환 |
| 방화벽/프록시 환경 | SSE | HTTP 유지로 연결 안정 |
| 대규모 확장, 메시징 플랫폼 | WebSocket + Pub/Sub | 분산 환경 적합 |
- 두 방식은 경쟁 관계가 아니라 상황별 도구입니다.
- 실시간 앱이라면 “WebSocket + SSE 혼합 구조”로 효율성을 극대화하세요.
반응형
'Backend > Study' 카테고리의 다른 글
| [Tip] 실무에서 자주 쓰는 SQL 최적화 패턴 10가지 (0) | 2025.10.15 |
|---|---|
| [Study] 백엔드 로그 관리 전략 (ELK, Loki, Grafana) (0) | 2025.10.14 |
| [Study] Docker에서 MySQL 연결 안 될 때 해결법 (0) | 2025.10.10 |
| [Study] JWT 활용 및 예제 코드 (0) | 2025.10.03 |
| [Study] JWT 동작방식 깊게 살펴보기 (0) | 2025.10.02 |