cd ../
Architecture·2026-02-15·5 min read·# entry/023

이벤트 기반 통신과 분산 시스템의 이해 (SSE, WebSocket, Webhook)

RESTful API의 한계를 넘어서는 이벤트 기반 통신의 종류와 특징, 그리고 분산 시스템에서의 장단점과 멱등성에 대해 알아봅니다.

이벤트 방식의 특징

  • 상태 유지(Stateful) : 클라이언트와 서버가 연결을 유지하며 상태를 공유한다.
  • 단방향/양방향 통신 : 서버가 클라이언트에게 데이터를 푸시하는 방식(SSE)와 양쪽 모두 데이터를 주고 받는 Socket 방식으로 나뉜다.
  • 실시간성: 이벤트 발생 즉시 데이터가 전달되어, 실시간 데이터 업데이트에 적합하다.

이벤트 방식의 종류

1. SSE (Server-Sent Event)

SSE 특징

서버에서 클라이언트로 단방향 데이터 전송 방식입니다. 일반적인 HTTP 요청-응답 모델을 사용하며, API와 달리 특정 트리거가 발생하기 전까지 서버가 TCP 연결을 닫지 않고 지속적으로 데이터를 보낼 수 있습니다.

HTTP 프로토콜 위에 동일하게 구현되어 확장된 방식이라서 별도의 복잡한 프로토콜 없이 쉽게 사용할 수 있습니다.

2. WebSocket

  • 특징: 클라이언트와 서버 간에 양방향 통신 채널을 개설한다. 최초 연결시 HTTP를 통한 핸드셰이크를 거친 뒤 별도의 TCP 연결(/ws)로 업그레이드 된다
  • 연결: 초기 핸드셰이크 이후, 프로토콜 헤더가 가벼워져 효율적인 통신이 가능하다.

3. Webhook

  • 특징: 서버 간의 이벤트 통신 방식으로, 특정 이벤트가 발생했을때, 이벤트가 발생한 서버가 미리 등록된 URL로 HTTP POST 요청을 전송한다.

RESTful API의 StateLess함을 잃는 것은 아닐까?

REST API의 특징

RESTful API는 요청에 필요한 자원을 모두 명세하는, **자원 기반 구조(Resource Oriented Architecture)**를 설계하는 것이다. 클라이언트는 서버가 요구하는 모든 자원을 하나의 요청에 담아서 전송하고, 서버는 이에 대한 하나의 응답을 전달하여 단방향 일대일 연결을 사용한다.

RESTful API의 가장 큰 특징은 Statelessness로 무상태성은 서버가 클라이언트의 요청 상태를 보존하지 않는다는 것을 의미한다. 각 요청은 완전히 독립적으로 처리되며, 처리에 필요한 모든 정보를 요청 자체에서 얻기 때문에 Web환경에서 주요하게 다뤄지는 확장성을 극대화할 수 있다.

이런 장점 덕분에 RESTful API는 클라이언트가 어떤 서버 세션으로 요청을 전송하든 처리할 수 있으며 상태 정보를 관리하고 보관할 필요가 없어진다.

이벤트 기반 통신 방식은 Stateful 하여 Web에 부적절하다??

Stateless한 API 요청-응답 모델은 실시간 통신을 구현하기 어렵다는 한계를 갖고 있다. Polling 방식이 많이 사용되지만, 이는 불필요한 네트워크 비용을 늘릴 우려가 있기 때문이다.

이런 한계를 극복하기 위해 탄생한 프로토콜이 WebSocket 방식이다.

  • 클라이언트와 서버가 HandShake를 마친 뒤에는 HTTP헤더가 필요하지 않는 경량 프레임 기반의 통신을 통해 매우 낮은 오버헤드와 지연없는 실시간 통신을 제공한다.
  • 명시적으로 연결을 끊지 않으면 클라이언트-서버의 Connection을 유지하는 Stateful한 특성을 갖고 서버가 각 클라이언트의 연결을 직접 관리해줘야한다.

이는 클라이언트의 숫자가 늘어날수록 서버에 상당한 부담을 줘 최근 네트워크 트래픽이 기하급수적으로 늘어나 몇몇 개발자들은 기피하는 케이스가 발생하고 있다.


분산 시스템과 이벤트 기반 아키텍처

소프트웨어의 구조가 복잡해지고 비용을 고려하여 서비스를 보다 더 작은 단위로 모듈화하고 확장하다보니 확장성이 떨어지는 이벤트 기반 통신 방식이 중요한 패러다임으로 다가왔다.

현재는 MSA, IoT 환경에서 이벤트 기반 통신방식은 매우 중요한 역할로 부상했다.

MSA와 IoT 에서의 Pub/Sub 모델

분산시스템 아키텍처의 근간에는 Pub/Sub 모델이 있다. 이벤트 생산자(Publisher)는 특정 이벤트를 이벤트 버스, 메시지 브로커에 게시하고 이벤트의 소비자(Subscriber)는 자신이 관심있는 이벤트를 구독한다.

  • 생산자와 소비자는 서로 연결되지 않기 때문에 **느슨한 결합(Loose Coupling)**이 가능해진다.
  • **MQTT(Message Queuing Telemetry Transport)**는 사물 인터넷에 특화된 경량의 발행/구독 메시징 프로토콜이다. MQTT 브로커가 메시지 라우팅을 담당하며 Topic이라는 범주에 따라 필터링하고 전달한다.

분산 시스템 아키텍처는 RESTful API에 비해 여러 이점을 제공하지만 단점도 존재한다.

장점
  • 확장성 및 복원력: 서비스들이 서로 독립적으로 확장 및 배포될 수 있으며, 한 서비스에 장애가 발생해도 시스템이 중단되지 않는다. 이벤트 라우터는 트래픽 급증에 대한 탄력적 버퍼역할을 수행하여 안정적인 운영을 돕는다.
  • 낮은 결합도: 서비스 간 직접호출을 지양하고, 이벤트로만 통신하는 방식은 서비스간 의존성을 최소화한다.
  • 비용절감: Polling 방식을 사용하지 않게되어 네트워크 사용량이나 CPU 사용량이 줄어든다.
단점
  • 복잡성 증가: 비동기 시스템의 특성상 이벤트의 흐름을 추적하고 디버깅하는 것은 매우 어렵다. 로직이 여러 서비스에 걸쳐 분산되어있기 때문에 시스템 전체를 파악하는데 많은 인지적 부하가 발생할 수 있다.
  • 이벤트 순서 보장 및 중복처리: 메시지가 순서가 바뀌거나 중복으로 전달될 위험이 있다.

멱등성(Idempotency)

멱등성이란?

**멱등성(Idempotency)**은 동일한 작업을 여러번 시도하더라도 한번만 실행한 것 처럼 동일한 결과를 보장하는 속성을 의미한다.

EDA(분산 시스템 아키텍처) 환경에서 네트워크 불안정으로 인해 다음과 같은 상황이 발생할 수 있다.

  1. 요청은 성공했지만, 응답을 받지 못했을 때
  2. 요청은 성공했지만 응답이 지연될 때

이런 경우 클라이언트가 요청이 실패했다 판단하고, 동일한 요청을 다시 보내게 되는 경우를 고려해야 한다. 멱등성이 보장되지 않을 경우 서버의 상태가 여러번 변경되어 데이터 불일치가 발생할 수 있다.

일반적으로 멱등성은 Key를 가지고 구현한다. 클라이언트가 생성하여 요청에 포함한 뒤, 서버의 MQ나 캐시 저장소에 요청과 함께 저장한다. 그리고 동일한 요청을 다시보내게 되었을때. 이미 해당하는 Key가 저장소에 존재하면 이전 요청의 성공 결과를 반환하는 방식이다.