본문 바로가기

Spring

알람 전송 구현 기술의 고민

이번에 우리 팀에서 기획한 프로젝트는 docconneting이라는 의사와의 채팅과 유료 질문이 가능한 프로젝트였다

 

알람 전송 시나리오

  • 채팅 결제가 성공하면 해당 의사에게 알람이 간다
  • 등록이 성공하면 해당 카테고리 의사에게 알람이 간다
  • 등록이 성공하면 해당 카테고리 의사에게 알람이 간다
  • 알람 조회

시나리오는 이런식이다!

여기서 나는 알람 전송 기능을 담당하게 되어서 알람을 구현하기 위해서 어떤기술을 사용해야 할지 고민을 해보게 됐다

 

알림 구현 기술들

폴링

어떤 값을 확인하거나 갱신하는 과정

  • 정기적 폴링(Regular Polling) : 일정한 간격 또는 주기적으로 데이터를 확인하거나 갱신
  • 이벤트 기반 폴링(Event-based Polling) : 특정 이벤트가 발생했을 때만 데이터를 확인하거나 갱신

 

1) 짧은 폴링(Short Polling)

  • 정기적 폴링
  • 클라이언트가 일정한 짧은 주기로 지속해서 요청을 보내고 서버에서 줄 데이터가 없는 경우엔 빈 응답, 줄 데이터가 있는 경우에는 데이터를 담은 응답을 보내주는 방식
  • 서버에서 줄 데이터가 없음에도 요청과 응답 작업을 반복하기 때문에 불필요한 트래픽이 많이 발생
  • 단순히 일정 주기로 요청과 응답이 오가기 때문에 이벤트 발생을 실시간으로 반영하지 못함

 

2) 긴 폴링(Long Polling)

  • 서버에서 클라이언트에게 줄 데이터가 없는 경우 곧바로 응답하지 않고 커넥션을 계속 유지하며 서버에서 줄 데이터가 생겼을 때 응답을 보내는 방식
  • 짧은 폴링에 비해서 이벤트의 실시간성이 잘 보장됨
  • 클라이언트와 연결을 계속 유지하는 동안 서버 자원을 지속해서 소모하고 있게 됨
    • 스프링 부트로 만든 애플리케이션과 연결 할 때 데이터베이스 커넥션 풀을 할당해주는데 100만명의 회원에게 긴 폴링 방식으로 알림을 제공하면 100만개의 커넥션 풀을 소모하게 되는 것
  • 서버를 여러개 사용한다면 문제가 발생
    • 클라이언트 A가 서버 1에 연결됨
    • 서버 1에서 Long Polling 요청을 대기 중
    • 클라이언트가 다시 요청했는데, 이번에는 서버 2로 요청이 분산됨
    • 서버 2는 이전 요청이 서버 1에서 대기 중이었는지 모름
    • 결과적으로 일관성 문제가 발생함
  • 결국 클라이언트가 요청을 보내야만 데이터를 받을 수 있음

 

3) 웹 소켓

  • 클클라이언트와 서버가 한 번 연결을 맺고 나면 그 연결이 쭉 유지되고, 이 연결을 통해서 클라이언트와 서버가 양방향을 통신할 수 있게 해줌
  • 서버에서 이벤트가 발생한 경우 서버에서 먼저 데이터를 발송하는 서버 푸시가 가능하기때문에 실시간 알림기능을 구현하기에 매우 적합한 프로토콜
  • 클라이언트와의 연결을 계속 유지하고 있다는 점에서 롱 폴링 방식이 가지고 있는 서버 자원 소모 문제점을 똑같이 가지고 있음
  •  알림은 서버에서 클라이언트로의 전송만이 필요하지 양방향 통신일 필요는 없음

 

4) 서버 전송 이벤트 (Server Sent Events)

  • 클라이언트에서 서버로 요청을 보내면 일정 시간 동안 연결을 유지하면서 서버에서 이벤트가 발생했을 때 실시간으로 클라이언트에게 데이터를 넘겨주는 서버 → 클라이언트로의 실시간 단방향 통신 방법
  • 롱 폴링은 서버에서 이벤트가 발생해 데이터를 응답하면 연결이 끊어지고 다시 연결해야 하지만 sse는 서버에서 데이터를 응답하든 말든 일정 시간 동안은 연결을 끊지 않고 계속 유지함
  • 일정 시간동안 커넥션 연결을 쭉 해주는 것이 보장됐기에 서버에서 클라이언트로 데이터나 알림을 마음껏 줄 수 있음
  • 웹소켓처럼 별도의 프로토콜을 사용하는 것이 아니라 우리에게 익숙한 http프로토콜을 사용함
  • 스프링에서 개발한다면 별도의 라이브러리없이 sse를 지원하는 도구를 제공해줌

 

5) Firebase Cloud Messaging

  • 무료로 메시지를 보낼 수 있는 교차 플랫폼 메시징 클라우드 서버
  • 운영체제마다 전자기기에 푸시 알림을 보내는 방법이 다름
    • 안드로이드는 GCM
    • 애플은 IOS
    • => FCM은 애플리케이션에서 FCM을 이용해 알림 기능을 개발해두기만 하면 디바이스별 실제 알림 발송 방법은 FCM에서 알아서 작업해 알림을 발송해 줌
  • 클라이언트가 알림 정보를 받기 위해 서버와 직접 연결하기 때문에 Long Polling, Web Socket 그리고 SSE→클라이언트와 서버가 연결을 유지하는 동안 서버의 자원을 지속해서 소모
  • 이 문제를 해결하기 위해서 클라이언트와 서버 사이에 메시지 전용 클라우드 서버를 하나 두고 클라이언트는 클라우드 서버와 연결을 유지함
  • → 서버에서는 알림 발송이 필요한 그 순간에만 fcm서버로 요청을 보내고 응답도 즉시 받는 무상태 상호작용을 함
  • → 서버 : 서버자원 고갈 문제 해결 / 클라이언트 : 최적화 기능을 제공하는 fcm클라우드 서버와 연결하기 때문에 비교적 적은 배터리와 네트워크 사용만으로 알람을 수신

 

이렇게 총 5가지의 후보들을 고민해본 결과!

내가 생각하는 기술선택의 기준은 아래와 같이 결정했다

알람의 경우 자주 호출되는 기능이고, 대량의 알람이 사용자가 유료 게시물을 올릴 때마다 전송되기 때문에 서버에서 많은 리소스를 소모할 수 밖에 없기 때문에 서버의 자원을 제일 덜 소모하는 기술을 기준으로 잡자!

 

 

최종 결정

  • 해당 서비스에서는 알람을 전송하는 경우가 총 3가지가 있고, 그 중에서 대량 알람을 전송하는 요구사항이 있었기 때문에 클라이언트와 서버가 연결을 유지하는 동안 서버의 자원을 지속해서 소모하는 Long Polling, Web Socket, SSE는 적절하지 않다고 판단
  • 또한, 환자가 유료 질문 게시물을 올리고 48시간 이내에 의사가 한명이라도 댓글을 달아주지 않는다면 환불이 되기 때문에 실시간성이 중요하므로 Short Polling은 적절하지 않다고 판단
  • 이러한 이유로, 알람 전송 기술로 FCM 채택

 

알람 전송 기술로 FCM을 결정~!😃

 


참고 자료 : https://velog.io/@idonymyeon/%EC%95%8C%EB%A6%BC-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-1-%EC%95%8C%EB%A6%BC%EC%9D%84-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EB%8B%A4%EC%96%91%ED%95%9C-%EB%B0%A9%EB%B2%95