본문 바로가기

개발기술/통신 인터페이스, 프로토콜

실시간 통신 기술의 개발 역사

실시간 통신 기술의 개발 역사 & WebSocket의 등장 배경

웹 초창기에는 클라이언트가 서버의 데이터를 가져오는 단순한 방식이었지만, 점점 더 동적인 데이터를 실시간으로 받아야 할 필요성이 커짐. 이를 해결하기 위해 Polling, Long Polling, SSE 같은 방법이 등장했고, 이후 WebSocket이 실시간 양방향 통신의 최적 솔루션으로 자리잡음.

실시간 통신 기술의 역사적 흐름

시기 기술 특징 한계
1990년대 후반 Polling 클라이언트가 일정 주기로 서버에 요청 네트워크 부하 심함, 실시간성 부족
2000년대 초반 Long Polling (Comet 기법) 서버가 응답을 지연하여 실시간성 개선 여전히 HTTP 요청-응답 방식, 서버 부하 큼
2000년대 중반 (~2009) SSE (Server-Sent Events) HTTP 기반에서 서버 → 클라이언트 단방향 푸시 양방향 통신 불가능
2008-2011 WebSocket 클라이언트와 서버가 지속적으로 데이터를 주고받는 방식 (Full-Duplex) 초기 브라우저 지원 부족
2010년대 후반~현재 gRPC Streaming, WebRTC, MQTT, AMQP P2P, 마이크로서비스, IoT 등을 위한 다양한 실시간 기술 발전 사용 목적에 따라 기술 선택 필요

 

방식 서버가 먼저 전송 가능? 실시간성 장점 단점
Polling
(주기적 요청)
❌ 요청 필요 요청 간의 공백 존재 구현이 쉬움 네트워크 부하
Long Polling
(HTTP 기반 실시간 대체)
❌ 요청 필요
(응답 지연)
응답 후 요청간의
공백 존재
구현 간단 서버 부하 증가
SSE
(Server-Sent Events,
HTTP 기반 푸시)
✅ 서버 푸시 가능
단방향 스트리밍
✅ 실시간 가능 WebSocket보다 가볍고,
연결 유지 비용이 적음.
WebSocket보다
기능 제한
WebSocket
(Full-Duplex 양방향 통신)
✅ 서버 푸시 가능 ✅ 초고속 실시간 양방향 데이터 전송 가능 연결 유지 비용 큼

 

 

       

Polling (1990년대 후반)

  • 초기 웹 애플리케이션에서는 "클라이언트가 서버의 데이터를 정기적으로 요청"하는 방식을 사용

Polling 방식 동작:

  1. 클라이언트가 일정 주기로 서버에 요청을 보냄
  2. 서버는 데이터가 있으면 응답하고, 없으면 빈 응답 반환
  3. 클라이언트는 계속해서 같은 요청을 반복
  • 하지만 Polling 방식은 **"필요한 데이터가 없더라도 요청을 계속해야 한다"**는 문제가 있었고, 불필요한 네트워크 트래픽이 많아 서버 부하

Long Polling (2000년대 초반)

Long Polling 방식 동작:

  1. 클라이언트가 서버에 요청을 보냄
  2. 서버는 새로운 데이터가 있을 때까지 응답을 보류
  3. 새로운 데이터가 생기면 서버가 응답을 반환
  4. 클라이언트는 다시 요청을 보내고 대기

SSE (Server-Sent Events, 2000년대 중반)

HTTP 기반에서 서버가 클라이언트로 데이터를 푸시할 수 있도록 등장한 기술
Polling, Long Polling보다 효율적이며, 브라우저에서 기본 지원됨

 

SSE 방식 동작:

  1. 클라이언트가 서버에 연결을 맺음
  2. 서버는 새로운 데이터가 생길 때마다 클라이언트로 데이터를 전송
  3. 클라이언트는 별도의 요청 없이 실시간 데이터를 수신

 WebSocket (2008~2011)

2000년대 후반까지 웹은 여전히 요청-응답 기반의 HTTP가 중심. 하지만 AJAX, SNS, 온라인 게임 같은 서비스가 발전하면서 실시간 양방향 통신의 필요성이 급격히 증가.  

 

기존 HTTP 방식의 문제점:

  • Polling, Long Polling은 여전히 비효율적인 HTTP 요청을 필요로 함
  • SSE는 단방향 전송만 가능
  • 클라이언트와 서버가 지속적으로 데이터를 주고받을 수 있는 방식이 필요함

반면, SSE는 기존 HTTP프로토콜을 사용하여 구현이 쉽지만 websocket은 , 새로운 전용 프로토콜(ws:// 또는 wss://)을 사용해야 하여 구현이 비교적 어려움. 그러나

 

1) 효율성 (프레임 기반 vs HTTP 헤더 오버헤드)

  • SSE는 HTTP 헤더와 함께 지속적인 이벤트 스트리밍을 사용하므로, 데이터 전송 시마다 HTTP 헤더가 포함되어 오버헤드가 증가할 수 있음.
  • WebSocket은 최초 핸드셰이크 후 가벼운 바이너리 프레임을 사용하여 오버헤드를 줄일 수 있음.
  • 따라서 빈번한 이벤트 전송이 필요한 경우 WebSocket이 더 효율적.

2) 연결 개수 제한

  • 브라우저는 도메인당 6~10개의 HTTP 연결을 제한하는데, SSE는 이 제한을 받음.
  • WebSocket은 하나의 연결에서 여러 스트림을 처리 가능하므로, 대량의 지속 연결이 필요한 서비스에 유리함

 

그러므로 클라이언트가 알림, 채팅, 실시간 데이터 갱신과 같은 여러가지 서비스를 받는다면 웹소켓을 통하는 것이 확장성 측면에서 유리하다.

 

WebSocket 이후 등장한 실시간 기술

 WebSocket이 등장한 후에도 다양한 실시간 통신 기술이 발전함
WebSocket이 모든 경우에 최적은 아니기 때문에, 이후에 더 특화된 기술들이 개발됨.

기술등장 시기 특징
WebRTC 2013년 P2P 실시간 화상 채팅, 음성 통화
gRPC Streaming 2015년 HTTP/2 기반의 실시간 서버-서버 통신
MQTT 2013년 이후 확산 IoT(사물인터넷) 전용 메시지 프로토콜
Kafka, RabbitMQ 2010년대 대규모 실시간 데이터 스트리밍

 

REST, SSE, WEBSOCKET 코드비교

REST API (HTTP) 구현

@RestController
@RequestMapping("/api")
public class RestApiController {

    @GetMapping("/message")
    public ResponseEntity<String> getMessage() {
        return ResponseEntity.ok("Hello from REST API");
    }
}

 

SSE (Server-Sent Events) 구현

MediaType.TEXT_EVENT_STREAM_VALUE을 사용하여 서버 → 클라이언트로 데이터를 지속적으로 보냄

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

    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamMessages() {
        return Flux.interval(Duration.ofSeconds(1))
                .map(i -> "SSE message " + i);
    }
}

 

 

WebSocket 구현

 

WebSocket은 특정 엔드포인트에서 HTTP → WebSocket 프로토콜로 전환(Upgrade)해야 함. 이 과정에서 Spring WebSocket을 설정하고, 메시지 브로커를 구성해야 하므로 설정이 추가됨.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic"); // 클라이언트로 메시지를 보낼 경로
        registry.setApplicationDestinationPrefixes("/app"); // 클라이언트가 메시지를 보낼 경로
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); // WebSocket 엔드포인트 등록
    }
}

 

WebSocket 메시지 핸들링

@Controller
public class WebSocketController {

    @MessageMapping("/send")
    @SendTo("/topic/messages")
    public String sendMessage(String message) {
        return "Server received: " + message;
    }
}

 

Blocking Http방식, SSE방식, Websocket방식 기술비교

  HTTP는 요청과 응답이 한 번만 발생하므로, OS 레벨에서 이벤트 루프를 사용하지 않아도 문제 없음. OS가 소켓을 감시 리스트(epoll() 등의 이벤트 루프)에 등록하는 것보다, 요청을 보낸 후 바로 애플리케이션을 Blocked 상태로 두고 인터럽트가 발생하면 깨우는 것이 더 빠르고 효율적입니다. 

  SSE/WebSocket은 지속적인 이벤트 처리가 필요하므로, OS 레벨에서 epoll(), kqueue() 같은 이벤트 루프를 사용해야 함.

 

방식 요청방식 응답방식
일반 HTTP (Blocking I/O) 애플리케이션이 fetch() 또는 read()를 호출 후 Blocked 상태로 대기 OS는 accept(), read() 같은 Blocking I/O로 데이터 수신 후 인터럽트 발생
SSE (Server-Sent Events,
Event Loop 기반 단방향 스트리밍)
애플리케이션이 EventSource로 이벤트 루프 실행하여 데이터 감지 OS는 epoll(), kqueue() 같은 이벤트 루프를 통해 네트워크 이벤트 감시
WebSocket
(Event Loop 기반 양방향 통신)
애플리케이션이 onmessage 이벤트 루프를 실행하여 데이터 감지 OS는 epoll(), kqueue() 같은 이벤트 루프를 통해 지속적인 소켓 이벤트 감시

 

 

SSE (Server-Sent Events) - Event Loop 기반 단방향 스트리밍

SSE는 클라이언트가 서버와 지속적인 연결을 유지하며, 서버가 데이터를 Push하면 애플리케이션의 이벤트 루프가 이를 감지하여 처리.

const eventSource = new EventSource("/stream-updates");
eventSource.onmessage = (event) => {
        console.log("New data:", event.data);
};

 

WebSocket - Event Loop 기반 양방향 통신

HTTP 요청보다 네트워크 부하가 낮고, 실시간 데이터 교환이 가능.

📌 WebSocket은 서버와 클라이언트가 지속적으로 연결된 상태에서 양방향으로 데이터를 주고받을 수 있는 이벤트 기반 모델.

const socket = new WebSocket("wss://example.com/socket");
socket.onmessage = (event) => {
        console.log("Received:", event.data);
};
        socket.send("Hello, server!");

 

.

WebSocket - Handling With 서블릿 or Netty

 

 

OS 수준에서는 항상 네트워크 소켓을 감시하고 있고,
어플리케이션 레벨에서 그 감시 결과(데이터 도착 알림)를 어떻게 처리하느냐가 서블릿 기반이냐, Netty 기반이냐의 차이야.

 

 

OS 레벨에서는?

  • 네트워크 소켓에 데이터가 들어오면, OS 커널은 해당 소켓을 감지하고 **포트 버퍼(소켓 수신 버퍼)**에 데이터를 쌓아둬.
  • 이 감시는 리눅스라면 epoll, 윈도우라면 IOCP 같은 이벤트 기반 I/O 감시 시스템이 사용됨.
  • 이건 서블릿 기반이든, Netty 기반이든 공통이야.

즉, OS는 "누가 요청했는지와 무관하게" 감시해줌.

 

 

그 다음: 애플리케이션 레벨에서의 처리 차이

 

구분 서블릿 (Tomcat 등) Netty (WebFlux 등)
OS가 이벤트 알려줌 epoll 등에서 "데이터 있어!" 이벤트 감지 동일
애플리케이션 처리 방식 이 이벤트를 받기 위해 스레드가 소켓을 block하고 대기 중 이 이벤트를 **이벤트 루프(EventLoop)**에서 비동기로 처리
데이터 수신 처리 InputStream.read() 블로킹 호출 (스레드 점유) ChannelHandler에서 콜백으로 이벤트 처리
컨텍스트 스위칭 많음 (스레드당 연결) 적음 (NIO 기반, 스레드 소수)

다시 말해서

  • OS는 감시함 (epoll, IOCP 등) — 여긴 차이가 없음.
  • 애플리케이션이 "OS가 알려준 이벤트"를 어떻게 처리하느냐가 다름:
    • Tomcat/서블릿: 스레드 하나가 소켓에 붙어서 계속 .read()로 대기
    • Netty: 한 스레드가 수많은 소켓을 Selector.select()로 감시, 이벤트 오면 해당 Channel에 이벤트 콜백 전달

'개발기술 > 통신 인터페이스, 프로토콜' 카테고리의 다른 글

RabbitMQ 구현  (0) 2025.02.17
메시지 큐, RabbitMQ, Kafka 개념  (0) 2025.02.14
AI 영상분석과 websocket + message broker  (0) 2025.02.14
WebSocket  (0) 2025.02.13