나 JAVA 봐라

[Spring Boot] SSE로 알림 기능 구현하기 본문

프로젝트

[Spring Boot] SSE로 알림 기능 구현하기

cool_code 2024. 3. 11. 17:10

크루장이 크루 신청을 승인 했을 때, 내가 쓴 게시글에 댓글이 달렸을 때,.. 등 사용자에게 알림이 가도록 하기 위해 알림 기능을 구현하려고 한다.

 

먼저 알림 기능을 위해 사용되는 방법 4가지를 간략하게 정리해보았다. 

 

1. Polling

  • 일정 주기로 서버 API 호출하는 방법
    • 주기가 길다면? : 데이터의 실시간성을 보장할 수 없다.
    • 주기가 짧다면? : 갱신된 내용 없어도 불필요한 요청이 자꾸 들어오기 때문에 불필요한 서버 부하가 발생한다.

2. Long Polling

  • 업데이트 발생 시에만 응답을 보내는 방법. 서버에 요청 들어왔으면 일정 시간 대기하다가 업데이트 된 내용이 있을 경우 웹 브라우저에 응답을 보낸다.
    • 불필요한 응답을 주는 경우를 줄일 수 있다. (장)
    • 연결이 되어있는 경우 실시간으로 데이터가 올 수 있다. (장)
    • 데이터 업데이트가 빈번할 경우, 연결을 위한 요청이 계속 발생하기에 서버 부하 발생한다. (단)

3. SSE (Server-sent Event)

  • 웹브라우저에서 서버 쪽으로 특정 이벤트를 구독하면, 서버에서 해당 이벤트 발생 시에 웹 브라우저로 이벤트를 보내주는 방법
    • 서버에서 웹 브라우저로만 데이터 전송 가능(단방향)
    • 최대 동시 접속 횟수가 제한되어있다.
    • 한번만 연결요청 보내면, 연결 종료 전까지는 재연결 없이 계속 데이터를 전송할 수 있다. (안끊김)

4. Web Socket

  • 서버와 웹브라우저 사이 양방향 통신이 가능한 방법. 변경 사항에 빠르게 반응해야하는 채팅 등에 사용된다.
    • 양방향 통신이 지속적으로 이루어진다.
    • 연결을 유지하는 것 자체가 비용이 들기에, 트래픽 많으면 서버에 부담이 된다.

 

알림의 경우 전통적인 client-server 모델의 http 통신에서는 구현하기 어렵다. 해당 방식은 클라이언트의 요청이 있어야만 서버가 응답하는데, 알림은 ‘클라이언트의 요청이 없이’ 실시간으로 서버의 변경 사항이 웹 브라우저에 갱신 되어야하기 때문이다.

제시된 4가지 방법 중 http 연결에 대한 부담이 적은 방식은 SSE, Web socket 이며 실시간성도 보장이 된다. 이 중 알림은 단방향 통신만 해도 된다. (서버 → 클라이언트) 그래서 보통 알림은 SSE 방식을 많이 채택한다.

 

알아보니 Spring에서 제공하는 SSE 프레임워크 사용하면 알람 기능이 쉽게 구현될 것 같아 SSE 방식의 알림 기능을 구현하기로 정했다.

 

크게 보면 작업은 아래와 같이 진행될 것이라 예상된다.

  1. 웹 브라우저와 서버 연결하기 (한번 연결하면 재연결 자주 안해도 된다.)
    1. 연결 관련해서 설정해주기 (연결 , 알림 전송 메소드 생성 포함)
  2. 생성해둔 알림 전송 메소드를 각 이벤트가 발생하는 서비스 메소드 내에 추가한다.
    1. 크루장 승인의 경우, 승인 메소드 내에 알림 전송 메소드 포함하여 알림 전송될 수 있도록 한다.

 

이 때, 팀에서 고민했던 내용들이 있다. 

 

Q. SSE는 실시간 접속 중일 때만 알림을 보낼 수 있다. 사용자가 오프라인일 때는 어떻게 할지?

 

 

위의 질문에 대해 3가지 해결 방법을 생각해보았다. 

 

A. 

  1. 서버가 사용자의 접속여부를 파악하여서 따로 처리한다. 이 때, 지금 프로젝트는 토큰 방식으로 인증을 하기에, 서버에서 사용자의 접속 여부 알 수 없다. 따라서 접속여부 파악하는 방법?
    1. 접속여부 DB 생성하고, 클라이언트에서 heartbeat 5초에 한번씩 서버로 보내서 접속 여부 파악 → 주로 프론트 개발자가 해야할 일들이라서 패스
  2. 푸시 알람 전송하기. SSE의 경우 오프라인일 경우 실시간 전송이 안됨. 물론 푸시 알림으로 처리할 수 있지만 이 부분은 프론트 개발자가 처리해야해서 일단 패스
  3. 알림함 만들기. 특정 이벤트가 발생했을 때, 아래의 a,b 두 가지를 모두 실행한다.
    1. SSE로 실시간 알림을 전송한다 →
      1. 만약 오프일 경우, 그냥 알림 못받는 것으로 처리
      2. 온라인일 경우, 알림함 빨간 표시 + 팝업창 띄우기 정도
    2. 알림함 DB에 알림 내용을 저장한다. → 온, 오프 상관 없이 모두 DB에 저장하고, t/f로 읽음 여부 판단하기
      1. 알림함은 최초 접속 1회일 때만 조회해서 안읽은 알람 여부 판단하고, 이 후 실시간 알람 왔을 때에만 알림함 한번씩 조회하기. (실시간 알림 안왔으면 알림 조회할 이유 없으니까)

⇒ 결론으로는 3번째 방법으로 진행하기로 했다. 

 

 


참고

https://taemham.github.io/posts/Implementing_Notification/

 

[백엔드 스프링부트] 알림 기능은 어떻게 구현하는게 좋을까?

This is a wannabe backend developer’s dev blog.

taemham.github.io

 

'프로젝트' 카테고리의 다른 글

[학부 연구] 자기지도학습을 통한 신장분할  (0) 2024.04.14
Boot-Up : 개발 전 시동 걸기  (1) 2023.12.20