일정 등록 시 ToDoList 넣기에 이어서 알림설정 및 실시간 알림 기능을 구현했다.
💡 알림 설정은 선택사항 (없어도 일정등록 가능해야 함)
💡 하나의 일정에 여러 알림 설정 가능(일, 시, 분 단위) → 테이블 따로 생성
💡 알림여부가 Y면 일정알림 테이블의 알림타입과 설정시간에 맞춰 스케줄러로 알림을 전송
ERD
일정알림이 일정ID를 가지고 있고, 해당 일정은 회원ID를 가지고 있다.
일정알림에 전송여부를 관리하여 알림이 전송되지 않은 일정만 알림 전송되게 한다.
Spring
알림 설정 기능
알림타입은 일(D), 시(H), 분(M)으로 나뉜다.
setTime이 3, alarmType이 M이면 일정시작 3분 전에 알림을 전송한다.
일정 등록 시 알림정보(alarmRequest)를 추가로 받음
required = false로 값이 존재하지 않을 경우는 null 값을 할당
String으로 받은 AlarmType을 enum 타입으로 변환해서 Alarm 테이블에 저장
postman으로 alarmRequest를 리스트로 보내면 일정 테이블과 알림 테이블에 데이터가 동시에 생성된다.
id 1은 10분 전 알림 설정, id 2는 하루 전 알림 설정이다.
SSE
이제 SSE와 스케쥴러를 사용해 설정한 시간에 알림을 전송하는 기능을 추가해보자
✅ SSE를 선택한 이유
- Polling : 실시간 통신을 위해서는 업데이트 주기를 짧게 해야 하지만, 빈번한 HTTP 요청에 의해 트래픽이 많아질 경우 서버에 부하 大
- Long-Polling : (Polling 와 동일하게) 빈번한 HTTP 요청에 의해 트래픽이 많아질 경우 서버에 부하 大
- WebSocket : 서버와 클라이언트의 양방향 통신
- SSE : 서버에서 클라이언트로의 단방향 통신
→ 알림 기능의 경우, 단방향 통신으로 충분히 구현 가능하고 배터리 소모량이 더 적은 SSE가 가장 적절하다.
참고
SseEmitter는 인메모리로 보관됨
→ 통신정보를 가지고있는 것
SseEmitter는 Spring에서 SSE 프로토콜을 지원하기 위한 클래스로, 클라이언트와의 연결 상태를 관리하고, 연결이 끊어지는 경우 재시도 등의 처리를 한다.
SSE 연결
SSE 연결을 위한 API를 생성
Emitter를 구분하기 위해 로그인한 사용자의 email을 사용한다.
→ email같은 유저정보와 함께 저장해서 get하기 쉽게 해줌
SSE 연결 시 SseEitter 객체를 만들어야 하는 데, 이 때 생성자로 만료시간을 설정할 수 있다.
→ 상단에 상수로 선언
만료시간이 되면 브라우저에서 자동으로 서버에 재연결 요청을 보낸다.
SseEmitter 객체는 이벤트가 발생했을 때, 해당 클라이언트로 이벤트를 전송하기 위해 사용되므로 서버에서 저장해야 한다.
스레드 safe한 자료구조 사용하는 이유
→ 아래 콜백 함수는 SseEmitter를 관리하는 다른 스레드에서 실행되기 때문에 thread-safe한 자료구조를 사용하지 않으면 ConcurrnetModificationException이 발생할 수 있다.
onCompletion과 onTimeout으로 비동기 요청이 완료되거나 유효 시간이 만료된 경우에 대해 자동으로 호출할 콜백함수를 등록해놓을 수 있다.
onCompletion에서 삭제하는 이유
→ 유효 시간이 만료되면 브라우저에서 재연결 요청을 보내는데, 이때 새로운 Emitter 객체를 다시 생성하기 때문에 기존의 Emitter를 제거해줌
그리고 최초 연결 후, SseEmitter의 유효 시간동안 어느 메시지도 전송되지 않으면 503 Service Unavailable 에러를 발생시키므로 이에 대한 방안으로 더미 데이터를 전송해준다.
테스트
로그인 후 /connect로 Get요청하면 더미 데이터가 전송됨을 확인할 수 있다.
⭐ 연결 성공
'Spring' 카테고리의 다른 글
[Spring] JPQL로 일정 조회하기 (0) | 2024.04.02 |
---|---|
[Spring] SSE + Scheduler로 실시간 알림 기능 구현(2) (0) | 2024.03.27 |
[Spring] 일정 등록 시 ToDoList 넣기 (0) | 2024.03.21 |