이번에 우리 팀에서 기획한 프로젝트는 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을 결정~!😃
'Spring' 카테고리의 다른 글
컨트롤러 테스트에 인증/인가가 들어있는 경우 (0) | 2025.05.12 |
---|---|
FCM의 구조와 이를 구현하기 위한 고민(Feat : FCM토큰관리와 전송 메서드) (1) | 2025.05.12 |
동적쿼리와 인덱싱 적용하여 성능 개선하기 (+ Like 검색은?) (0) | 2025.04.07 |
컨트롤러 테스트 작성시 주의할 점 (1) | 2025.04.07 |
QClass 구현 안 될때 해결법 (0) | 2025.04.04 |