SSA의 알림 시스템 설계: SSE + FCM
SSA는 오프라인 강의 일정 스케줄링 서비스입니다.
강사가 강의 일정을 등록하거나 수정하면, 학생은 전체 강의 목록 또는 강사 이름, 강의명을 통해 강의를 검색하고 수강 신청할 수 있습니다.
이후, 강사는 수강 신청 알림을 받게 되고, 신청을 수락 또는 거절할 수 있습니다.
이 과정에서 학생 역시 수락/거절 결과에 대한 알림을 받게 됩니다.
SSE 란 ?
Server-Sent-Event의 약자로, 서버에서 클라이언트로 실시간 이벤트를 전달하는 웹 기술입니다.
- 연결 시작:
- 클라이언트에서 HTTP 프로토콜을 통해 요청
- 서버는 text/event-stream 이라는 content-type으로 응답
- 이후 client / server 간 데이터 파이프라인이 형성되어 연결
- 서버에서 데이터 발행 때마다 데이터 반환
- 연결 종료:
- 서버는 모든 이벤트가 종료되면 연결 종료.
- 클라이언트는 서버로부터 data: [Done] 메시지를 받으면 연결 종료 확인

event-stream 이란 ?
위 그림에서 Event Response에 담겨서 전송되는 데이터가 하나의 'event'입니다.
이벤트 스트림은 여러 이벤트로 구성되며, 각 이벤트는 다음과 같은 형식을 갖고 있습니다.
- data → 이벤트의 데이터
- event → 이벤트의 이름 (옵션)
- id → 이벤트의 ID (옵션)
- retry → 재연결 시간(ms) (옵션)
왜 FCM과 SSE를 함께 사용할까?
강사와 학생은 항상 온라인 상태가 아닙니다.
따라서 접속 여부에 따라 적절한 알림 전달 방식을 선택해야 합니다.
| 상황 | 기술 | 이유 |
| 사용자가 웹 브라우저에서 사용 중일 때 | SSE | 서버와 연결 유지로 빠른 실시간 알림 제공, 즉시 알림 수신 가능 |
| 사용자가 오프라인 상태일 때 | FCM | 앱이 꺼져 있어도 푸시 전송 가능, 앱 사용자에게 놓치지 않는 알림 보장 |
- SSE(Server-Sent Events)는 클라이언트와 서버 간에 지속적인 연결을 유지하면서, 서버에서 실시간 이벤트를 클라이언트로 자동 푸시합니다.
- FCM(Firebase Cloud Messaging)은 클라이언트와의 연결 없이도 백그라운드 또는 오프라인 상태의 기기에 푸시 알림을 전송할 수 있습니다.
이 두 가지를 결합하면,
접속 중 사용자는 실시간 SSE 알림을, 미접속 사용자는 FCM 푸시를 통해 알림을 받을 수 있어 효율적인 알림 시스템을 구축할 수 있습니다.
SSE의 연결 유지 문제와 해결 방안
SSE를 사용할 때 발생할 수 있는 두 가지 주요 문제가 있습니다:
- 사용자가 접속 중인데 연결이 끊기는 문제
- 사용자가 미접속 중인데 연결이 끊기지 않는 문제
1. 접속 중인데 연결이 끊기는 문제 → Heartbeat 메시지로 해결
- 프록시, 게이트웨이, 브라우저 등은 유휴 연결을 일정 시간 후 자동으로 끊습니다.
- 예) AWS API Gateway는 30초 이상 데이터가 없으면 연결 종료
- 이를 방지하기 위해 10초마다 heartbeat 메시지를 전송하여 연결 상태를 유지합니다.
2. 미접속인데 연결이 끊기지 않는 문제 → Redis + TTL로 해결
- 클라이언트가 브라우저 탭을 닫거나, 네트워크가 끊기면 서버에서 이를 감지하기 어렵습니다.
- SSE 메시지 전송 시 예외가 발생하면, 해당 사용자의 SSE emitter를 제거하고 Redis 구독도 해지합니다.
- 추가로, Redis에 online:{memberId} 형태의 키를 TTL(예: 30초)로 저장해두고, heartbeat 전송 시 TTL을 갱신합니다.
- heartbeat나 메시지 전송 실패로 TTL이 만료되면, 사용자가 오프라인으로 판단됩니다.
알림 전략
- 사용자가 접속 중이면 (Redis 기준 online)
- SSE로 알림 전송
- 전송 실패 시 FCM으로 대체
- heartbeat를 통해 연결 유지 및 Redis TTL 갱신
- 사용자가 미접속 중이면 (Redis TTL 만료 또는 전송 실패)
- FCM을 통해 푸시 전송
- FCM 송신 실패 시 재시도 로직 수행

SSE 메시지 형식 예시
data: This is a test message.
event: custom-event
id: 12345
retry: 10000
- data: 전송할 메시지 내용
- event: 이벤트 이름 (선택)
- id: 이벤트 식별자 (선택)
- retry: 연결이 끊겼을 때 재연결 시간(ms) (선택)
최종적으로 사용자의 접속 상태에 따라 SSE와 FCM을 적절히 조합하여
- 실시간 반응성과
- 오프라인 알림 누락 방지
- 필요시에 연결 지속/해제 선택으로 네트워크 리소스 낭비 최소화
와 같은 이점을 얻을 수 있습니다.
'SSA > Back' 카테고리의 다른 글
| [SSA] 500명 알림 발송 6.4초 -> 0.27초, 카프카 컨슈머 병렬 처리 적용기 (3) | 2025.08.28 |
|---|---|
| [SSA] 수강 기능 및 알림 기능을 한 곳에서 처리하면 발생할 수 있는 문제 (1) | 2025.07.19 |
| [SSA] 서버 FCM 기능 구현 (1) | 2025.05.04 |
| [SSA] 강의 도메인 (0) | 2025.05.04 |
| [SSA] 회원 도메인 (0) | 2025.05.04 |
