그린체리 프로젝트를 바탕으로 알림서비스에 대한 구조를 간단하게 설명하자면,

 

프론트 단에서 처음 로그인을 할 경우,

1. 알림 허용에 대한 권한에 대해 묻는다.

2. 허용을 눌렀을 경우 각 아이디당 플랫폼에 해당한 유니크한 토큰을 발급하여 회원정보와 함께 DB에 저장한다.

 

프론트 단에서 알림관련 API 호출할 경우,

1. 백엔드 단에서 알림에 관련된 API가 호출되면서 해당 내용에 대한 알림을 회원에게 보낸다.

 

 

각 프론트, 백엔드에서 FCM이 무슨 역할을 하는지 이해하는 게 중요하다

프론트에서 FCM은 알림 허용 권한, 토큰 발급의 역할을 하는 대신, 

백엔드에서 FCM은 알림을 프론트로 보내는 역할을 한다

실질적인 FCM은 백엔드에서 사용된다고 볼 수 있다

 

해당 프로젝트에선 백엔드 서버인 Java에서 알림을 구현했지만, Node.js,Python 등에서도 구현이 가능하다고 한다.

 

 

 

프로젝트에서 FCM을 사용한 이유는 간단하다

1. 플랫폼 종속성 없이 push 메시지 전송 가능

2. 사용자 기기의 배터리 및 네트워크 리소스 절약

3. 백그라운드를 통한 푸시 알림 기능

 

 

1. 플랫폼 종속성 없이 push 메시지 전송 가능

iOS,Android, Web 각 플랫폼에서 push 메시지를 보내려면 각 플랫폼별로 개발해야 하는 불편함이 있는데,

FCM을 이용하면 플랫폼에 종속되지 않고 push 메시지를 전송할 수 있다

 

 

2. 사용자 기기의 배터리 및 네트워크 리소스 절약

서버를 경유해서 실시간 push 메시지를 받으려면 사용자는 항상 서버에 접속해야하는데,

이는 사용자 기기의 배터리 및 네트워크 리소스를 크게 낭비한다

 

클라우드 메시징 서비스를 사용하면

사용자는 낮은 배터리와 네트워크의 사용만으로도 메시지를 실시간으로 송수신 처리를 할 수 있다

이와 같은 이유로 대부분의 어플리케이션 서비스들은 클라우드 메시징 서버를 경유해서,

실시간으로 유저들에게 메시지를 전송해주고 있다고 한다

 

3. 백그라운드를 통한 푸시 알림 기능

PWA의 Service Worker를 활용하여 웹 페이지와는 별개로 백그라운드 동기화나 푸시 알림 기능을 구현하기 위해 선택했다

 

 

구현 단계 정리

[Frontend] React에서 PWA 구현 단계

  1. PWA Manifest 설정하기 PWA Manifest를 설정하기 위해서는 public/manifest.json 파일을 생성합니다. 이 파일에서는 앱의 이름, 아이콘, 시작 URL 등을 정의할 수 있다
  2. Service Worker 구현하기 Service Worker는 public/service-worker.js 파일에서 구현할 수 있습니다. 이 파일에서는 Service Worker의 라이프사이클 이벤트를 처리하고, 오프라인 캐싱 등의 기능을 구현할 수 있다
  3. Push Notification을 위한 FCM 설정하기 Firebase Cloud Messaging(FCM)을 이용하여 Push Notification을 구현할 수 있다 이를 위해서는 Firebase 프로젝트를 생성하고, FCM을 설정해야 합니다. React에서는 firebase 모듈을 이용하여 FCM SDK를 사용할 수 있다
  4. 알림 목록을 가져올 API 구현하기 알림 목록을 가져오기 위한 API를 구현해야 한다. 이를 위해서는 Spring Boot Java 백엔드에서 알림을 저장하고, 필요한 API를 구현한다.
  5. React 프론트엔드에서 API 호출하기 React에서는 axios 또는 fetch 등의 라이브러리를 이용하여 API를 호출할 수 있다. 필요한 API를 호출하여 알림 목록을 가져와야 한다.
  6. 알림을 표시하는 컴포넌트 구현하기 알림 목록을 가져온 후에는 알림을 표시하는 컴포넌트를 구현해야 한다. 이를 위해서는 React에서 Notification API를 이용할 수 있다.
  7. PWA를 등록하기 PWA를 등록하기 위해서는 index.js 파일에서 serviceWorkerRegistration.register()를 호출해야 한다.

PWA를 사용하기 위해서는 Service Worker를 등록해야 합니다. 이를 위해 아래와 같이 코드를 추가할 수 있습니다.

import { initializeApp } from 'firebase/app';
import { getMessaging, getToken, onMessage } from 'firebase/messaging';

const firebaseConfig = {
  // Firebase 설정 정보
};

// Firebase 초기화
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);

// Service Worker 등록
if ('serviceWorker' in navigator) {
  window.addEventListener('load', async () => {
    try {
      const registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js');
      messaging.useServiceWorker(registration);
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    } catch (err) {
      console.log('ServiceWorker registration failed: ', err);
    }
  });
}

// 알림 권한 요청 및 토큰 발급
async function requestPermission() {
  console.log('권한 요청 중...');

  const permission = await Notification.requestPermission();
  if (permission === 'denied') {
    console.log('알림 권한 허용 안됨');
    return;
  }

  console.log('알림 권한이 허용됨');

  const token = await getToken(messaging, {
    vapidKey: 'BBuoQiK6Hci6-fWBqgcIAn-a8Nzc7kF1XVpkCKfHINcvckb-u3sz8eSrsbtns2WjrXZ9bxs7j0DCsNtkNIiqjHc',
  });

  if (token) console.log('token: ', token);
  else console.log('Can not get Token');

  // 알림 수신 처리
  onMessage(messaging, (payload) => {
    console.log('메시지가 도착했습니다.', payload);
    // ...
  });
}

requestPermission(); 

위 코드에서 /firebase-messaging-sw.js는 Service Worker 파일이 위치한 경로를 의미한다. 이 경로는 실제 프로젝트에서 사용하는 경로에 맞게 변경해주어야 한다. 또한, vapidKey는 Web Push에서 사용되는 Public Key 값으로 변경해야 한다.

 

[Backend] Spring Boot Java 에서 알림을 구현 단계 

  1. FCM 설정하기 Firebase Console에서 프로젝트를 생성하고, FCM을 설정한다.
  2. Firebase Admin SDK 연동하기 Firebase Admin SDK를 이용하여 FCM을 사용할 수 있다. 이를 위해서는 Firebase Console에서 서비스 계정을 생성하고, 해당 계정의 인증 정보를 이용하여 Firebase Admin SDK를 초기화한다.
  3. FCM API 구현하기 Spring Boot Java 백엔드에서는 FCM API를 구현하여 Push Notification을 보낸다. 이를 위해서는 Firebase Admin SDK의 Messaging 클래스를 이용한다.
  4. 알림 목록 API 구현하기 알림 목록을 조회하고 관리하기 위해서는 백엔드에서 알림 관련 데이터를 저장하고, 필요한 API를 구현해야 한다. 예를 들어, 알림 목록을 조회하는 API를 구현하면, 프론트엔드에서 해당 API를 호출하여 알림 목록을 가져올 수 있다. 이때 백엔드에서는 데이터베이스를 이용하여 알림 정보를 저장하고, RESTful API를 구현하여 프론트엔드와 통신합니다. 또한, 알림을 클릭하면 해당 알림으로 이동할 수 있는 링크를 제공하기 위한 API도 구현할 수 있다. 이렇게 구현된 API를 이용하여, 사용자가 알림을 클릭하면 백엔드에서 해당 알림에 대한 처리를 수행하고, 필요한 화면으로 이동시키는 것이 가능한다.

 

구현 단계 자세히 보기

 

1. FCM 설정하기

 

파이어베이스 프로젝트 생성

  1. Firebase에 로그인하고 프로젝트를 연다
  2. 개요 페이지에서 앱 추가를 클릭한다
  3. 웹 앱에 Firebase 추가를 선택한다
  4. 스니펫을 복사하여 애플리케이션 HTML에 추가한다

💡 SDK 설정 및 구성 (Firebase SDK snippet) 을 잘 확인해야 한다

프로젝트 설정에서 일반탭에서 생성한 앱에 대한 정보를 확인이 가능하며, FCM은 클라우드 메시징 탭에서 확인 가능하다.

 

 

비밀 키 파일 생성

생성한 프로젝트 페이지 > 설정 > 서비스 계정 항목

 

프로젝트로 생성된 비밀키를 이동

원래 깃허브와 같이 공개된 장소에 이 파일을 같이 올리는 것은 안전하지 않다고 한다

이번 프로젝트에서는 json 파일로 생성된 비밀 키를 resources 디렉토리에 저장했다 

resources/firebase/greencherry-notice.json

{
  "type": "service_account",
  "project_id": "greencherry-notice",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-qjueq%40greencherry-notice.iam.gserviceaccount.com"
}

 

 

2. Firebase Admin SDK 연동하기

 

Dependency 설정

 

build.gradle

implementation 'com.google.firebase:firebase-admin:9.1.1'

 

application.yml

firebase:
  path: firebase/greencherry-notice.json

 

FCM 초기화

어플리케이션이 시작될 때 Firebase 프로젝트에 앱을 등록해줘야 한다.

(두 번 등록 되면 에러가 나므로 시작할 때마다 초기화 해준다)

 

commons/NoticeInitializer.java

@Slf4j
@Component
public class NoticeInitializer {

    @Value("${firebase.path}")
    private String path;

    @PostConstruct
    public void init(){
        ClassPathResource resource = new ClassPathResource(path);

        try(InputStream is = resource.getInputStream()) {
            FirebaseOptions options = FirebaseOptions.builder()
                    .setCredentials(GoogleCredentials.fromStream(is))
                    .build();

            if(FirebaseApp.getApps().isEmpty()){
                FirebaseApp.initializeApp(options);
                log.info("Firebase application init");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
    }
}

 

 

 

3. FCM API 구현하기 (메세지 보내기)

메세지를 보낼 때 필요한 요소는 2가지이다

1. 누구한테 보낼지

 토큰과 토픽 방식으로 보낼 수 있는데, 토큰을 사용했다

2. 어떤 정보를 보낼지

 

아래와 같이 Message를 보내는 별도의 서비스를 만들었다

NotificationRequest에는 받을 상대의 토큰값, 푸시될 알림 메세지와 제목을 가지고 있고

사용하진 않지만, 이미지도 지정해서 넣어줄 수 있다

 

service/NoticeService

public void sendNotice(List<String> tokens){
        for (String token : tokens) {
            Message message = Message.builder()
                    .setToken(token)
                    .putData("title", "제목")
                    .putData("body", "내용")
                    .setWebpushConfig(WebpushConfig.builder().putHeader("ttl", "1000")
                            .setNotification(new WebpushNotification("title", "body"))
                            .build())
                    .build();

            FirebaseMessaging.getInstance().sendAsync(message);
        }
    }

 

 

 

더 자세한 코드를 확인하실 분은  아래 링크 참고 부탁드립니다

https://github.com/tandamzi/GreenCherry

 

 

 

참고

 

Web Push | React + FCM 구현하기 (feat. pwa, service worker)

웹에서도 네이티브 앱처럼 푸시 알람을 받을 수 있습니다. 웹의 사용성을 네이티브 앱처럼 개선하기 위해서 나온 기술인 PWA(Progressive Web Application)을 활용하면 가능합니다.PWA는 Progressive Web Applica

velog.io

 

FCM, Spring Boot를 사용하여 웹 푸시 기능 구현하기

Firebase firebase Firebase는 웹과 모바일 개발에 필요한 기능을 제공하는 BaaS(BackEnd as a Service) 이다. 백엔드 서버의 인프라들을 제공해주고 많은 기능들을 지원한다. 머신러닝 사용자 인증 파일 저장

velog.io

 

 

📮개인 공부를 위한 공간으로 틀린 부분이 있을 수도 있습니다.📮

문제점 및 수정 사항이 있을 시, 언제든지 댓글로 피드백 주시기 바랍니다.

'TIL' 카테고리의 다른 글

Redis ?  (0) 2023.05.26
FCM(Firebase Cloud Messaging)  (0) 2023.05.26
[JPA] OSIV와 성능 최적화  (0) 2023.03.22
[JPA] API 개발 고급 정리  (1) 2023.03.21
[JPA] 페이징과 한계돌파  (0) 2023.03.20