알림 기능을 구현하며..

dev-jjun·2023년 8월 13일
0

Server

목록 보기
14/33
post-thumbnail

1️⃣ 푸시 기법이란?

Push

🌱 사용자(클라이언트)의 이벤트 실행 (요청 필요 X) → 서버는 해당 이벤트에 대한 데이터를 자동으로 제공

ex. SMTP

Pull

🌱 사용자(클라이언트)가 직접 필요한 정보를 서버에 요청하여 정보를 제공받는 방식

ex. POP3, IMAP (이메일 서버에서 사용자에게 전달)

알림 기능은 사용자의 이벤트를 감지하여 서버에서 데이터를 보내주는 푸시 기법을 사용하며, 대부분 클라이언트의 요청에 대한 응답보다 서버에서 일방적으로 변경을 감지하여 보내준다.

이때 실시간으로 서버의 변경 사항을 갱신해주어야 하는데, 이 말은 즉, 알림 기능이 “실시간 통신” 의 기반 하에 구현되어야 함을 의미한다. 실시간으로 서버와 통신을 해야 하는 경우, 매번 HTTP 통신을 요청하기에는 연결의 효율성이 떨어진다.

2️⃣ 실시간 통신

서버에서 실시간 통신을 하는 방법은 무엇이 있을까?

Polling

일정 주기를 가지고 서버의 API를 호출하는 방식

이는 HTTP 통신의 기반을 유지하므로, 호환성이 좋지만 업데이트 주기를 어떻게 설정하느냐에 따라 데이터의 불일치 또는 서버 부하의 문제가 따를 수 있다.

Long-Polling

업데이트 발생 시에만 응답을 보내는 방식 (Polling과 유사)

서버로 요청이 들어올 경우, 일정 시간동안 대기했다가 요청한 데이터가 업데이트 되면 엡 브라우저에게 응답을 보낸다. 따라서 연결이 된 경우에는 실시간으로 데이터를 반영할 수 있다.

하지만, 요청이 잦아지면 트래픽이 많아져 Polling과 마찬가지로 서버 부하가 커진다는 단점이 따른다.

Streaming

요청을 보내고 응답을 보낸 후, Connection을 종료하는 것이 아니라 이를 유지한 채로 다음 응답을 계속해서 받는 방식

서버가 일정 시간동안 요청을 대기시키고, Chunked 메시지를 이용해 응답 시 연결을 계속 유지해야 하므로 클라이언트에서 서버로 데이터를 보내는 게 힘들어진다.

WebSocket

서버와 클라이언트 간에 소켓 connection을 유지하여 언제든 양방향 통신 또는 데이터 전송을 가능하게 하는 방식

웹 소켓은 기존의 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜로, 접속까지는 HTTP 프로토콜을 이용하고 그 이후의 통신은 자체 WebSocket 프로토콜로 통신한다.

웹 소켓은 한 번 연결을 맺으면 연결을 해제하기 전까지 유지되므로, 연결을 맺고 끊는 연결과정을 없앨 수 있을 뿐만 아니라, 양방향 통신이 가능하기 때문에 클라이언트가 요청을 하지 않아도 서버가 제공해야 할 데이터를 보내줄 수 있다. 웹 소켓은 한번에 주고받는 데이터의 양이 HTTP에 비해 확연히 적기 때문에 계속 데이터를 주고 받아야 하는 서비스에는 적절하지 않다. 주로 변경 사항에 빠르게 반응해야 하는 채팅이나, 리소스 상태에 대한 지속적인 업데이트가 필요한 문서 동시 편집 등의 서비스에 많이 사용된다.

웹 소켓 프로토콜인 RFC 6455는 단일 TCP 연결을 통해 클라이언트와 서버 사이에 전이중 방향 통신(2-way Communication) 채널을 설정하는 표준화된 방법을 제공한다. HTTP 환경에서, HTTP와는 다른 TCP 프로토콜이나, Port 80, 443 등을 사용해 HTTP를 통해 작동하며 기존 방화벽 규칙 및 HTTP 규격인 CORS 적용, 인증 등의 과정을 재사용할 수 있도록 설계되었다.

따라서, HTTP 통신의 Request/Response 헤더가 불필요하게 크게 되는 문제를 해소하여 최초 접속 시에만 헤더 정보를 이용하고 그 이후부터는 더이상 보내지 않고도 처리가 가능해진다.

💬 정리하자면, 요청을 보내야 서버로부터 응답이 오는 기존의 양방향 통신 방식을 단순화하여 **하나의 HTTP 접속으로 양방향 메시지를 자유롭게 주고받을 수 있도록 구성**된 단순 API 이다.

❕ 웹 소켓은 연결 요청에 대해 HTTP를 통해 Switching 및 HandShaking이 이루어진다. 결과적으로 모든 어플리케이션 내 메세지는 한 개의 초기 연결을 위한 URL, 즉 동일한 TCP 연결을 통해 흐른다.
*클라이언트와 서버가 메세지 시맨틱에 동의하지 않으면 메세지를 라우팅하거나 처리할 수 없다.

❕ TCP는 이진 데이터만 주고받을 수 있는 반면, 웹 소켓은 바이너리와 텍스트 데이터를 모두 주고받을 수 있다.

🧐 알림 기능에서 사용한다면?

WebSocket은 양방향 통신에 적합하다.

알림 서비스는 양방향의 통신보다는 주로 알림을 받는 사람에서의 요청이 없이 서버의 응답을 단방향으로 보내기만 해주는 서비스이기 때문에, 웹 소켓을 이용하는 방식은 too much.. 비효율적이라는 것이다.

SSE(Server-Sent-Events)

서버의 특정 이벤트를 구독하여, 이벤트 발생 시마다 데이터를 보내주는 방식

→ 지속적인 스트리밍 기술

웹 소켓보다 가벼운 단방향 통신 방식의 SSE는 클라이언트가 서버로부터 데이터를 받을 수만 있다. 별도의 프로토콜 사용 없이 HTTP만 사용하여 처음 연결을 요청한 이후에, 연결된 상태를 유지하고 서버가 일방적으로 데이터를 전송하게 된다.

이때 최대 동시 접속 횟수는 제한되어 있다는 단점이 있다. (HTTP/1.1 - 브라우저 당 6개, HTTP/2 - 브라우저 당 100개)

3️⃣ 푸시 알림 구현

  1. 웹 소켓
  2. SSE
  3. FCM

위 세 가지 방식을 고려해볼 수 있는데, 1번 방식은 위에서 언급했듯 알림 기능에 최적화되지 않으므로, 2번, 3번 방식을 더 깊이 공부해보고 실습 예제를 통해 구현해보고자 한다.

SSE(Server-Sent-Events)

SSE를 이용한 실시간 알림 구현

FCM(Firebase Cloud Messaging)

FCM이란?

Android, iOS 및 웹 애플리케이션의 메시지 및 알림을 위한 크로스 플랫폼 메시징 솔루션

  • 모든 사용자에게 알림 메시지를 전송할 수도 있고, 그룹을 지어서 메시지를 전송할 수 있도록 무료 지원해준다.
  • HTTP Web Push 프로토콜인 'RFC8030 사용
  • 송수신을 위해 필요한 주요 구성 요소
    1. Firebase용 Cloud Functions 또는 앱 서버와 같이 메시지를 작성, 타겟팅, 전송할 수 있는 신뢰할 수 있는 환경 → 서버 측 구성 요소
    2. 해당 플랫폼 별 전송 서비스를 통해 메시지를 수신하는 iOS, Android 또는 웹(자바스크립트) 클라이언트 앱
        <aside>
      💫 앱 서버 → 클라이언트 앱으로 다운 스트림 메시지를 보낼 수 있을 뿐만 아니라, 클라이언트 앱 → 앱 서버로 업 스트림 메시지를 보낼 수도 있다.
        </aside>
        

장점

  • 플랫폼 독립적으로 푸시 메시지를 전송할 수 있음
  • FCM에서 제공하는 부가 기능을 사용할 수 있음
  • 기능 구축에 필요한 시간과 비용 절약

메세지 타입

메세지 종류알림 가능 여부알림 저장 개수알림 처리 방법
알림 메시지가능여러 알림을 저장하나, OS 환경마다 다르다.앱이 백그라운드 일 때
데이터 메시지가능1개의 알림만 저장앱이 포그라운드 일 때
  • 일반적으로, 알림 메시지와 데이터 메시지를 같이 혼용하여 사용한다.
    • 휴대폰 푸시 알림 메시지 → 알림 메시지 이용
    • 알림 메시지를 클릭하여 앱 내 특정 페이지로 이동 / 특정 액션 수행 → 데이터 메시지 이용

타겟팅

종류대상 수설명
단일 기기 (특정 기기)1개하나의 기기(앱 기준)
기기 그룹 (여러 대의 기기)20개알림 키에 허용되는 그룹
특정 주제 구독 및 주제 구독자1000개등록 토큰에 구독된 기기


👨‍👩‍👧‍👦 엄빠도 어렸다 서비스에서 푸시알림이 필요한 부분!

To 부모와 자식 (2명의 유저) = 기기 그룹

  • 주기적인 일일문답 알림 (pushTime 값에 지정된 시간) → 스프링의 @Scheduled 사용

To 부모, 자식 중 상대에게 (1명의 유저) = 단일 기기

  • 알림 시간 변경
  • 일일문답에 상대방이 답변한 경우
  • 일일문답에 내가 답변 안 한 경우(후순위) — 고려 가능
  • 일일문답에 상대방이 답변 안 한 경우(후순위)

Push API 구현해보자!

FCM을 이용한 Push API 구현

🧐 FCM을 사용하지 않으면요 ?

사용자가 서버를 경유하여 실시간으로 푸시 메시지를 받게 된다.

서버를 경유해서 푸시 메시지를 받으려면, 사용자가 항상 서버에 접속해있어야 하는데 이는 리소스 낭비가 크다.

FCM으로 구현할 시, 클라우드 메시징 서버를 중간에 둠으로써 낮은 배터리와 네트워크의 사용만으로 실시간으로 메시지의 송수신 처리가 가능해진다.

또한, 플랫폼(Android, iOS, Web)에 따라 APNS(Apple Push Notification Service), GCM(Google Cloud Messaging) 의 푸시 알림 서비스를 별도로 사용하여 클라이언트가 각각 구축을 해야 한다.

Andriod

→ GCM: 서버에서 Android 디바이스의 어플리케이션으로 데이터를 전송하도록 도와주는 서비스

  1. 단말에서 GCM으로 register 요청

  2. GCM에서 register 성공 후 registration id 전송

  3. third-party server로 registration id 전송

    a. registration id 값과 알림 메시지를 GCM으로 전송

    b. 해당 registration에 맞는 단말에 알림 메시지 전송

iOS

→ APNS: 서버에서 새로운 데이터를 모니터링하며 영구적 보안 채널을 통해 APN와 공급자를 연결하고, 대상 장치에 알림을 보내는 서비스

*Apple 기기로 알림을 보내려면 APNS는 필수이며, FCM과 같이 사용하는 경우 Apple Developer에서 key를 등록하고 APN 인증키를 받아 FCM에 넣어주어야 한다. → 클라 쪽에서 설정!

  1. Provider에서 APNS로 알림 요청
    1. 앱 → APNS: 디바이스 토큰 요청
    2. APNS → 앱: 토큰을 전달
    3. 앱이 푸시 서버(provider)에게 디바이스 토큰을 보내줌 *FCM이 provider가 될 수 있음
  2. APNS에 등록된 토큰을 통해 해당 애플 기기에 알림 메시지 전송

참고 자료

http://devstory.ibksplatform.com/2017/09/gcm-apns.html

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

https://qjadud22.tistory.com/70

profile
서버 개발자를 꿈꾸며 성장하는 쭌입니다 😽

0개의 댓글