728x90
개요
어떤 특정 행위에 대한 알림 기능은 유저의 요청 없이도 실시간으로 서버의 변경 사항을 웹 브라우저에 갱신해줘야 하는 서비스이다. 하지만 전통적인 Client-Server 모델의 HTTP 통신에서는 이런 기능을 구현하기가 어렵다. 클라이언트의 요청이 있어야만 서버가 응답을 할 수 있기 때문이다. HTTP 기반으로 해당 문제를 해결하려면 다음과 같은 방식들이 있다.
일단 알림 기능을 위해 사용되는 방법 4가지를 간략하게 정리해보았다.
실시간 통신의 방법
Polling
- 특징
- 일정 주기로 서버 API 호출하는 방법
- 클라이언트에서 5초마다 한 번씩 알림 목록을 호출한다면, 업데이트 내역이 5초마다 갱신되며 변경 사항을 적용할 수 있다.
- 주기가 길다면? : 데이터의 실시간성을 보장할 수 없다.
- 주기가 짧다면? : 갱신된 내용 없어도 불필요한 요청이 자꾸 들어오기 때문에 불필요한 서버 부하가 발생한다.
Long-Polling
- 특징
- Polling과 비슷하나, 업데이트 발생 시에만 응답을 보내는 방법
- 서버에 요청 들어왔으면 일정 시간 대기하다가 업데이트 된 내용이 있을 경우 웹 브라우저에 응답을 보낸다.
- 불필요한 응답을 주는 경우를 줄일 수 있다. (장)
- 연결이 되어있는 경우 실시간으로 데이터가 올 수 있다. (장)
- 데이터 업데이트가 빈번할 경우, 연결을 위한 요청이 계속 발생하기에 서버 부하 발생한다. (단)
SSE (Server-Sent Event)
- 특징
- 웹브라우저에서 서버 쪽으로 특정 이벤트를 구독하면, 서버에서 해당 이벤트 발생 시에 웹 브라우저로 이벤트를 보내주는 방법
- 따라서 한 번만 연결 요청을 보내면, 연결이 종료될 때까지 재연결 과정 없이 서버에서 웹 브라우저로 데이터를 계속해서 보낼 수 있다.
- 서버에서 웹 브라우저로만 데이터 전송 가능(단방향)
- 최대 동시 접속 횟수가 제한되어있다.
- 한번만 연결요청 보내면, 연결 종료 전까지는 재연결 없이 계속 데이터를 전송할 수 있다. (안끊김)
Web Socket
- 특징
- 서버와 웹브라우저 사이 양방향 통신이 가능한 방법이다.
- 변경 사항에 빠르게 반응해야하는 채팅이나, 리소스 상태에 대한 지속적 업데이트가 필요한 문서 동시 편집과 같은 서비스에 많이 사용되는 방식이다.
- 양방향 통신이 지속적으로 이루어진다.
- 연결을 유지하는 것 자체가 비용이 들기에, 트래픽 많으면 서버에 부담이 된다.
결론
- Polling 방식은 실시간성을 높이려면 그 주기를 짧게 해야 하는데, 트래픽이 많아질 경우 서버에 걸리는 부하가 커지기 때문에 알림 서비스에는 부적합하고 할 수 있다.
- Long-Polling 역시 마찬가지로, 트래픽이 많아지면 요청도 그만큼 많아지므로 부적합하다.
- 그렇다면 HTTP 연결 방식에 대한 부담이 적은 SSE와 WebSocket 방식이 남는데, 알림 서비스의 경우 클라이언트에서 서버로 데이터를 전송하지 않아도 되어서 단방향 통신만으로도 구현할 수 있으므로, SSE 방식을 택하는 것이 좋겠다.
해결 과정
- 알림의 경우 전통적인 client-server 모델의 http 통신에서는 구현하기 어렵다.
- 해당 방식은 클라이언트의 요청이 있어야만 서버가 응답하는데, 알림은 ‘클라이언트의 요청이 없이’ 실시간으로 서버의 변경 사항이 웹 브라우저에 갱신 되어야하기 때문이다.
- 제시된 4가지 방법 중 http 연결에 대한 부담이 적은 방식은 SSE, Web socket 이며 실시간성도 보장이 된다.
- 이 중 알림은 단방향 통신만 해도 된다. (서버 → 클라이언트) 그래서 보통 알림은 SSE 방식을 많이 채택한다.
알아보니 Spring에서 제공하는 SSE 프레임워크 사용하면 알람 기능이 쉽게 구현될 것 같아 SSE 방식의 알림 기능을 구현하기로 정했다.
크게 보면 작업은 아래와 같이 진행될 것이라 예상된다.
- 웹 브라우저와 서버 연결하기 (한번 연결하면 재연결 자주 안해도 된다.)
- 연결 관련해서 설정해주기 (연결 , 알림 전송 메소드 생성 포함)
- 생성해둔 알림 전송 메소드를 각 이벤트가 발생하는 서비스 메소드 내에 추가한다.
- 크루장 승인의 경우, 승인 메소드 내에 알림 전송 메소드 포함하여 알림 전송될 수 있도록 한다.
이 때, 고민했던 내용들
Q. SSE는 실시간 접속 중일 때만 알림을 보낼 수 있다. 사용자가 오프라인일 때는 어떻게 할지?
위의 질문에 대해 3가지 해결 방법을 생각해보았다.
A.
- 서버가 사용자의 접속여부를 파악하여서 따로 처리한다. 이 때, 지금 프로젝트는 토큰 방식으로 인증을 하기에, 서버에서 사용자의 접속 여부 알 수 없다. 따라서 접속여부 파악하는 방법?
- 접속여부 DB 생성하고, 클라이언트에서 heartbeat 5초에 한번씩 서버로 보내서 접속 여부 파악 → 주로 프론트 개발자가 해야할 일들이라서 패스
- 푸시 알람 전송하기.
SSE의 경우 오프라인일 경우 실시간 전송이 안됨. 물론 푸시 알림으로 처리할 수 있지만 이 부분은 프론트 개발자가 처리해야해서 일단 패스 - 알림함 만들기.
특정 이벤트가 발생했을 때, 아래의 a,b 두 가지를 모두 실행한다.- SSE로 실시간 알림을 전송한다 →
- 만약 오프일 경우, 그냥 알림 못받는 것으로 처리
- 온라인일 경우, 알림함 빨간 표시 + 팝업창 띄우기 정도
- 알림함 DB에 알림 내용을 저장한다. → 온, 오프 상관 없이 모두 DB에 저장하고, t/f로 읽음 여부 판단하기
- 알림함은 최초 접속 1회일 때만 조회해서 안읽은 알람 여부 판단하고, 이 후 실시간 알람 왔을 때에만 알림함 한번씩 조회하기. (실시간 알림 안왔으면 알림 조회할 이유 없으니까)
- SSE로 실시간 알림을 전송한다 →
⇒ 결론으로는 3번째 방법으로 진행하기로 했다.
참고 링크
728x90
'Spring > Spring Boot' 카테고리의 다른 글
Spring : @Transactional 이란? (사용원리) (0) | 2024.08.29 |
---|---|
Spring : 알림 기능 구현 (5) | 2024.08.28 |
Spring : S3 이미지 업로드 구현 (0) | 2024.08.23 |
Docker 및 Redis 설치/설정 (0) | 2024.08.22 |
Spring 이메일 인증 기능 구현하기 2 : 비밀번호 찾기 (0) | 2024.08.20 |