개발자는 기록이 답이다

비동기 쿠폰 발급 알림 기능에서 SSE를 선택한 이유 본문

Spring/트러블 슈팅

비동기 쿠폰 발급 알림 기능에서 SSE를 선택한 이유

slow-walker 2024. 3. 25. 10:36

프로젝트에서 비동기 쿠폰 발행시 유저에게 발급 완료 알림을 주는 기능을 구현했습니다.

실시간 알림 기능은 여러가지 방식으로 구현이 가능한데 그 중에서 제가 왜 SSE를 선택했는지 얘기해보고자 합니다.

 

비동기식으로 MQ를 활용해서 쿠폰 발급 기능을 구현하려고 하다보니, 쿠폰 발급이 즉시 이루어지지 않았습니다.

따라서 유저가 쿠폰을 발급받았는지 알림을 받으면 사용자 경험이 개선될 것이라 판단했습니다.

 

 

 

실시간 알림 방식에는 5가지 방법이 있습니다.

  • polling
  • Long polling
  • Socket
  • SSE
  • FCM

 

1. Polling

가장 기본적인 데이터 처리 방식으로, 클라이언트가 특정 주기로 http request를 서버로 계속 날려서 이벤트 내용을 전달받습니다.

 

특징

 

  1. 가장 쉬운 방법이지만, 클라이언트가 계속적으로 request를 날리기 때문에 클라이언트가 많아지면 서버의 부담이 급증하게 됩니다.
  2. http request connection을 맺고 끊는 것 자체가 부담이 많은 방식으로서, 불필요한 네트워크 호출과 요청이 많이 왔다갔다합니다.
  3. 클라이언트에서 실시간 정도의 빠른 응답을 기대하기 어렵기에 실시간 통신 애플리케이션에 적합하지 않습니다.
  4. polling은 http 오버헤드가 많이 발생한다는 단점이 있습니다.
더보기

Http Overhead란?

 

네트워크를 통해 대상에게 라우팅되는 데이터가 잘 전송되었는지 확인하기 위해, 추가 데이터를 같이 보냄으로써  대상을 정확히 찾았는지 간접적인 처리를 하는 것 입니다.

 

예시 : A를 처리하는데 3초가 걸렸을 경우, 안정성을 고려해 추가로 B를 처리는데 7초가 더 걸릴 경우 오버헤드 7초가 발생하게 된다.

 

참고 링크 : https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-HTTP-Overhead-%EB%9E%80

 

2. long-polling

Polling과 비슷한 기법이지만 실시간으로 데이터를 처리할 수 있는 방식입니다.

Long Polling은 클라이언트에서 서버로 일단 http request를 보내고 계속 기다리다가 서버에서 해당 클라이언트로 전달할 이벤트가 있으면 그 순간 response 메세지를 전달하며 연결이 종료됩니다. 즉, 서버 측에서 접속을 열어두는 시간을 길게하는 방식입니다.

 

특징

 

  1. 직접 polling에 비해 Http 오버헤드가 적게 발생합니다.
  2. 하지만 클라이언트에게 동시에 많은 메시지가 올 경우 클라이언트로 보내는 이벤트들의 시간 간격이 좁다면 polling방식과 차이가 없습니다.
  3. 다수의 클라이언트에게 동시에 이벤트가 발생될 경우 곧바로 다수의 클라이언트가 서버로 접속을 시도하게 되면서 서버의 부담이 급증합니다.
  4. long polling은 timeout이 발생해도 주기적으로 connection을 만들기 때문에 채팅 어플리케이션에서는 적합하지 않습니다.

 

 

3. Socket

클라이언트와 서버가 연결을 하는데 HTTP가 아닌 단일 TCP/IP 소켓 연결을 통해 전이중 통신(양방향 통신) 채널을 제공하는 방식입니다.

이 연결된 소켓을 통해 지속적으로 요청을 보내거나 요청을 받거나 순서 상관없이 요청을 주거나 받는 형태가 가능해집니다.

따라서 Socket방식은 서버에서 클라이언트로 비동기 업데이트를 보내는 가장 일반적인 솔루션입니다.

 

 

특징

 

  1. 최초 접속은 일반 http request를 통해 handshaking과정을 통해 이루어집니다.
  2. 그래서 기존의 80, 443 포트로 접속을 하므로 추가적으로 방화벽을 열지 않아도 양방향 통신이 가능합니다.
  3. HTTP polling과 같은 반이중 방식에 비해 더 낮은 부하를 사용하고 서버와 클라이언트 간의 실시간 데이터 전송을 가능하게 합니다.
  4. 클라이언트와 서버 간에 지속적으로 메세지를 주고 받는 채팅 어플리케이션에 적합합니다. ( 주식 시장 시세, Live 채팅, 멀티 플레이어 게임 등)

 

 

4. SSE (Server-Sent Events)

SSE는 단방향 통신을 통해 서버에서 클라이언트로 실시간 이벤트를 전송하는 웹 기술입니다. 클라이언트가 서버로 메세지를 보내는 것은 불가능합니다.  이를 통해 서버 측에서 이벤트를 생성하고, 클라이언트는 이벤트를 실시간으로 수신할 수 있습니다.

추가적인 설정 없어도 웹 브라우저에서 내장된 기능으로 지원됩니다. 기존의 HTTP 연결을 재사용하여 데이터를 전송하기 때문에 별도의 특별한 프로토콜이나 서버구성이 필요하지 않습니다.

 

특징

 

  1. SSE 텍스트 기반의 형식으로 데이터(Json형태)를 전송합니다.
    • 이벤트는 data, event, id, retry와 같은 필드로 구성된 텍스트 형태로 클라이언트로 전송됩니다.
  2. 기존의 HTTP 연결을 재사용하기 때문에 Authentication도 기존에 구현한거 그대로 사용하면 됩니다.
  3. 서버가 클라이언트한테 주기만 하면 되는 상황에 적합합니다. (실시간 알림, 주식 시장 업데이트)

 

5. FCM(Firebase Cloud Messaging)

Android, iOS 및 웹 애플리케이션의 메세지 및 알림을 위한 크로스 플랫폼 클라우드 솔루션입니다.

애플리케이션이 FCM서버와 통신하기 위해 Token으로 식별하고, Topic을 활용해 구독한 사용자들에게 메세지를 보낼 수 있습니다.

서버는 클라이언트(브라우저)의 요청에 대한 응답을 처리하기 위해, FCM서버와 통신해 데이터를 가져옵니다.

특징

 

  1. 크로스 메세지 플랫폼 솔루션이기 때문에 플랫폼이 종속되지 않고 Push 메세지를 전송할 수 있습니다.
  2. FCM 서버에서 알람이 성공적으로 전송되었는지 추적이 가능하고 모니터링할 수 있습니다.
  3. 푸시 발송을 위해 FCM 서버를 거쳐야 하므로, 다른 기법보다 지연시간이 발생합니다.
  4. 많은 푸시 메시지 발송이 요구된다면 병목현상이 발생할 수 있습니다.
  5. 실시간 성이 SSE에 비해 느린 편이기 때문에 연성 실시간(soft real-time)시스템에 적합합니다.

 

결론

우선 직접 폴링, 롱 폴링의 경우 클라이언트한테 주기적으로 request를 받기 때문에 http overhead 문제가 발생할 수 있어서 선택하지 않았습니다. socket은 클라이언트와 양방향으로 메세지는 주고 받는 목적이 아니기 때문에 선택하지 않았습니다.

 

그렇다면 fcm과 sse 2개 중 하나를 선택해야 했는데요! 보통 회사에서 Push 알람으로 FCM을 많이 쓰는것 같았지만, sse보다 실시간성이 느리다는 것 때문에 선택하지 않았습니다. 안정성과 크로스 플랫폼 호환성 측면에서 강점을 가지고 있지만, 이미 비동기 방식으로 일정한 시간동안(스케줄링) 쿠폰 발급이 진행되기 때문에, 여기서 더 지연 시간이 발생한다면 사용자 경험이 떨어질것이라고 생각했습니다.

 

push 알람의 안정성 측면을 고려한다면 추후에 sse에서 fcm으로 옮길 수도 있을 것 같습니다. fcm 기능도 추가적으로 더 배워보고 싶습니다 :)

 

 

참고링크

Polling / Long Polling  / Server Sent Event / WebSocket 정리

HTTP Short vs Long Polling vs WebSockets vs SSE

FCM 푸시 파헤치기

SSE vs FCM vs WebSocket