[네트워크] WebSocket vs SSE(Server-Sent Events)

이신영·2025년 2월 23일
0
post-thumbnail

웹 개발에서 실시간 통신이 필요한 순간이 많다. 예전에는 짧은 주기로 폴링(polling) 요청을 보내야 했다면, 이제는 WebSocket이나 SSE(Server-Sent Events) 같은 기술로 좀 더 효율적으로 실시간 데이터를 주고받을 수 있다.

그런데 WebSocket이랑 SSE가 뭐가 다를까 헷갈릴 수 있다. 인터넷 글을 찾아봐도 양방향 vs 단방향 이 정도만 설명되어있는 경우가 있어서 조금 더 알아보도록 하자

한줄요약

WebSocket은 양방향 통신용, SSE는 단방향(서버→클라이언트) 스트리밍용


WebSocket

“서버와 클라이언트가 양방향으로 데이터를 주고받을 수 있는 실시간 통신 프로토콜”

  • 통신 방식 : Full Duplex (클라 ↔ 서버 동시에 주고받음)
  • 프로토콜 : ws:// (또는 보안 연결 시 wss://)
  • 예시 : 실시간 채팅, 협업 툴(구글 독스처럼 동시에 문서 편집), 주식거래, 온라인 게임 등

장점

  1. 양방향 : 클라이언트 → 서버, 서버 → 클라이언트 모두 자유롭게 메시지 전송 가능
  2. 빠른 데이터 전송 : 연결 수립 후에는 오버헤드가 적은 프레임으로 데이터를 교환
  3. 이벤트 기반 : 메시지 발생 시마다 즉시 전송

단점

  1. 서버 자원 부담 : 연결마다 세션(혹은 소켓)을 지속적으로 관리해야 함
  2. 재연결 로직 필요 : 연결이 끊겼을 때 클라이언트 측에서 다시 접속 시도 코드를 작성해줘야 함
  3. 오래된 브라우저 호환성 : 대체로 최신 브라우저는 지원하지만, IE 구버전 같은 경우는 폴리필(polyfill) 필요

간단 코드 예시(Spring)

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new ChatHandler(), "/ws/chat")
                .setAllowedOrigins("*");
    }
}
public class ChatHandler extends TextWebSocketHandler {
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // 메시지를 받아서 브로드캐스팅 등 로직 처리
    }
}

SSE (Server-Sent Events)

“서버에서 클라이언트로 단방향 스트리밍을 지원하는 기술”
즉, 클라이언트는 연결을 맺은 뒤, 서버가 이벤트를 event-stream 형식으로 계속 보내주면 그걸 받기만 한다.

  • 통신 방식 : 단방향 (서버 → 클라이언트)
  • 프로토콜 : HTTP 기반 (text/event-stream)
  • 예시 : 알림(Notification), 대시보드 모니터링(서버 상태, 로그 스트리밍), 뉴스피드 등

장점

  1. 간단한 구현 : 자바스크립트에서는 EventSource 객체만 생성해주면 끝
  2. 자동 재연결 : 네트워크가 끊겨도 클라이언트에서 알아서 재연결 시도
  3. 문자열 데이터 전송에 최적 : 일반 텍스트, JSON 등을 전송하기 간편

단점

  1. 단방향 : 서버→클라만 가능. 클라에서 서버로 보내려면 AJAX 같은 걸 별도로 써야 함
  2. 바이너리 전송 제한 : SSE는 텍스트 이벤트 스트림에 더 맞춰져 있음(Base64 등으로 우회 가능)
  3. 브라우저 호환성 : IE는 지원 안 함(폴리필 또는 다른 방법 사용)

폴리필(Polyfill) : 브라우저에서 지원하지 않는 코드를 사용 가능한 코드 조각이나 플러그인으로 변환한 코드

간단 코드 예시(Spring MVC)

@RestController
@RequestMapping("/sse")
public class SseController {

    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream() {
        return Flux.interval(Duration.ofSeconds(1))
                   .map(seq -> "data: Hello SSE! seq=" + seq + "\n\n");
    }
}
// 클라이언트
const eventSource = new EventSource("/sse/stream");
eventSource.onmessage = (event) => {
  console.log("SSE 데이터:", event.data);
};

간단 비교 표

구분WebSocketSSE(Server-Sent Events)
통신 방식양방향 (Full-Duplex)단방향 (Server → Client)
프로토콜/스킴ws://, wss://HTTP (일반적으로 text/event-stream)
재연결 처리직접 구현 필요자동 (브라우저가 알아서 재연결)
사용 예채팅, 실시간 게임, 주식 거래, 협업툴실시간 알림, 로그/뉴스피드, 대시보드 모니터링 등
장점빠른 양방향 통신, 이벤트 기반간단한 설정, 자동 재연결, 텍스트 기반 스트리밍
단점서버 자원 부담, 재연결 로직 필요, 구버전 IE 문제단방향, 바이너리 전송 제약, 구버전 IE 문제
적합한 시나리오사용자 입력에 따라 즉시 서버가 응답해야 하는 경우(챗)실시간 알림/모니터링 등 서버→클라가 주도되는 경우

언제 뭘 써야 할까?

  1. 서버 ↔ 클라이언트 양방향 대화가 필요한 경우: WebSocket

    • 채팅, 공동 편집, 주식호가 등 클라에서 업데이트하면 서버가 다른 클라에게도 정보를 푸시해야 하는 경우
  2. 주로 서버에서 클라이언트로 자주 데이터가 바뀌는 경우: SSE

    • 단방향으로 계속해서 푸시하는 시나리오. 예) 실시간 알림, 서버 상태 모니터링 대시보드
  3. 구현 난이도 & 운영 비용 측면 고려

    • WebSocket은 세션이 많으면 관리가 번거롭다. 반면 SSE는 HTTP 기반이라 방화벽/로드밸런서 세팅이 편할 수 있다.
    • 반면 SSE는 대규모(수많은 접속자) 환경에서 연결 관리가 까다로울 수도 있다(하지만 대부분 WebSocket이 더 복잡하긴 함).

마무리

실시간 통신이란 말만 들으면 무조건 WebSocket만 생각하기 쉽지만, SSE도 상당히 유용해보인다. 특히 이벤트성 알림, 대시보드, 로그 모니터링 등에는 SSE가 구현이 매우 간편하니, 내 서비스는 클라이언트에서 서버로 보내는 실시간 액션이 적다~ 싶으면 SSE도 적극 고려해볼 만한것같다.

물론 요즘은 HTTP/2(멀티플렉싱) 환경에서 이벤트 스트리밍이 더 효율적으로 처리되는 케이스도 많고, 완전히 대용량 트래픽을 다루려면 배포 구조, 로드밸런싱 같은 복잡도가 따라온다.
언제나처럼 상황과 요구사항을 잘 고려해야될듯

카프카를 좀 공부해봐야겠는데?

profile
후회하지 않는 사람이 되자 🔥

0개의 댓글