Programing/JAVA

Firebase 환경 설정, 구축 및 구현 방법, 앱 푸시 메시지 보내기

리커니 2023. 4. 21.
반응형

Firebase는 Android 및 ios 에 구분 없이 알림을 전달할 수 있는 구글의 플랫폼 입니다.

Firebase 환경을 구축하고 Java 서버를 구현하여 보겠습니다.

 

아래의 Link를 클릭하여 Firebase site로 이동합니다.

 

1. Firebase 환경 설정

 

Link : https://firebase.google.com/

 

Firebase

Firebase는 고품질 앱을 빠르게 개발하고 비즈니스를 성장시키는 데 도움이 되는 Google의 모바일 플랫폼입니다.

firebase.google.com

시작하기를 클릭합니다.

프로젝트 만들기를 클릭합니다.

 

프로젝트 이름을 지정하고, 약관동의 등을 체크 후 계속 버튼을 클릭합니다.

애널리틱스 사용설정을 하고 계속을 클릭합니다.

새로운 애널리틱스를 생성합니다.

새 프로젝트가 생성이 되면 계속을 클릭합니다.

이제 생성된 프로젝트 좌측 메뉴 중 프로젝트 개요를 클릭하면 ios, android, web 등에 firebase를 추가할 수 있습니다.

원하는 OS를 선택하여 Firebase를 추가해주세요.

 

Android의 경우, 아래와 같이 앱 등록 후 구성파일을 다운로드 하여 앱에 추가해주셔야 합니다.

Firebase SDK 추가의 경우 자세한 샘플 코드가 있으니 따라하시면 됩니다. 

ios의 경우 APNs 관련 설정도 있으니 참고바랍니다.

설정이 끝난 후 콘솔로 이동하게되면 위에서 생성한 명칭의 프로젝트가 추가되어 있는 것을 확인하실 수 있습니다.

해당 프로젝트의 톱니바취나 좌측 프로젝트 개요 프로젝트의 톱니바퀴를 클릭하여 설정으로 이동합니다.

 

프로젝트 설정 메인 하단에 내 앱을 보시면 방금 설정한 Android 앱이 추가된 것을 확인하실 수 있습니다.

이제 클라우스 메시징 탭으로 이동하여 인증서를 생성합니다. 'Generate key pair'를 클릭하면 키쌍이 생성됩니다.

이제 서비스 계정 탭으로 이동하여 비공개 키를 생성합니다.

주의사항을 확인하고 '키 생성' 을 클릭합니다.

그럼 .json 파일이 생성되고 메시지를 전송할 서버에서 해당 파일을 사용해야 하니

메시지 전송서버의 특정위치에 옮겨놓습니다.

 

이제 서버를 구현해보도록 하겠습니다.

 

springboot gradle project 입니다.

 

firebase의 의존성을 주입합니다.

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

만일 proxy를 사용한다면 아래의 Link를 참고하세요.

 

Link : https://aljjabaegi.tistory.com/677

 

Firebase Proxy 등록 정보 및 라이브러리 수정 방법

특정 업체 협업을 하던 도중, 방화벽이 IP 주소만 허용이 되서, 프록시를 사용하여 도메인주소를 변경해야 했습니다. 일단 다운받은 firebase 설정 파일(json) 에는 아래 4개 값이 도메인 주소로 되어

aljjabaegi.tistory.com

이제 firebase 설정 파일을 구현합니다.

import java.io.IOException;
import java.io.InputStream;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;

@Configuration
public class FCMConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(FCMConfig.class);

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

    @PostConstruct
    private void initialFCM() throws IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = "accountKey/notification-test-firebase-adminsdk-"+firebase+".json";
        LOGGER.info("[N]Firebase Setting file : {}", path);
        try(InputStream input = classLoader.getResourceAsStream(path)){
            FirebaseOptions options = FirebaseOptions.builder()
                    .setCredentials(GoogleCredentials.fromStream(input))
                    .build();
            FirebaseApp.initializeApp(options);
            LOGGER.info("[N]Firebase init successfully.");
        }catch(IOException | IllegalStateException e){
            LOGGER.info("[N]Filebase no init. already exists");
        }
    }
}

active profiles에 따라 다른 firebase 설정파일을 가져오도록 설정되어 있습니다.

path에는 위에서 다운로드한 .json 설정 파일의 경로를 설정하면 됩니다.

이제 실제 메시지를 전송하는 Thread를 생성하겠습니다.

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.firebase.messaging.BatchResponse;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.MulticastMessage;
import com.google.firebase.messaging.Notification;
import com.google.firebase.messaging.SendResponse;

import kr.co.neighbor21.kt_api.common.CmmnVar;
import kr.co.neighbor21.kt_api.common.batch.pushNoti.vo.NotificationVO;

public class SendPushNotification implements Runnable {

    private static final Logger LOGGER = LoggerFactory.getLogger(SendPushNotification.class);
    private static final String TITLE = "제목";
    private String msg;
    private String msgDivCd;
    private List<String> pushTokens;
    List<String> successTokens = new ArrayList<>();

    public SendPushNotification(List<String> pushTokens, String msg) {
        this.msg = msg;
        this.pushTokens = pushTokens;
    }

    public List<String> getSuccessToken() {
        return successTokens;
    }

    @Override
    public void run() {
        LOGGER.info("=====================MSG SEND START==========================");
        LOGGER.info("Request message code : {}, size: {}", this.msgDivCd, this.pushTokens.size());
        if (this.pushTokens.size() > 0) {
            MulticastMessage message = MulticastMessage.builder()
                    .setNotification(Notification.builder().setTitle(TITLE).setBody(this.msg).build())
                    .putData("body",
                            CmmnVar.GSON.toJson(
                                    NotificationVO.builder().title(TITLE).msg(this.msg).build()))
                    .addAllTokens(this.pushTokens)
                    .build();
            BatchResponse response;
            try {
                response = FirebaseMessaging.getInstance().sendMulticast(message);
                List<SendResponse> responses = response.getResponses();
                for (int i = 0, n = responses.size(); i < n; i++) {
                    SendResponse sr = responses.get(i);
                    if (sr.isSuccessful()) {
                        this.successTokens.add(this.pushTokens.get(i));
                    } else {
                        LOGGER.info("=====================EXCEPTION START==========================");
                        LOGGER.info("Push Token size ({}), MsgDiv : {}", this.pushTokens.size(), this.msgDivCd);
                        LOGGER.info("Exception : {}", sr.getException().toString());
                        LOGGER.info("Exception code: {}", sr.getException().getErrorCode().toString());
                        LOGGER.info("Exception msg : {}", sr.getException().getMessage());
                        LOGGER.info("=====================EXCEPTINO END==========================");
                    }
                }
                LOGGER.info("[N]{}/{} s/t messages were sent successfully.",
                        response.getSuccessCount(), this.pushTokens.size());
            } catch (FirebaseMessagingException e) {
                LOGGER.error("[N]Fail to send push message", e);
            }
            LOGGER.info("=====================MSG SEND END==========================");
        }
    }
}

 

앱이 실행되면 앱의 push token을 DB에 저장합니다. 해당 값이 있어야 앱으로 알림전송이 가능합니다.

메시지 전송 시에는 해당 push token을 조회하여 단건의 경우 Message builder를 복수건의 경우 MulticastMessage builder를 사용하여 전송합니다.

 

기본적으로 Notification만 등록을 하여도 알림 전송이 가능합니다. 추가적으로 전달해야될 데이터가 있다면, putData 메소드로 전달해주시면 됩니다.

addAllTokens로 전달할 앱의 push token을 담아 전송합니다.

 

BatchResponse로 응답을 받을 수 있고, 성공/실패에 따라 로그 정보가 찍히게 구현되어있습니다.

이제 스레드를 실행하여 메시지를 전송합니다.

 

SendPushNotification sendThread = new SendPushNotification(pushTokens, msg);
Thread t = new Thread(sendThread);
LOGGER.info("[N]Request message send count...({})", pushTokens.size());
t.start();
t.join();
List<String> successList = sendThread.getSuccessToken();
LOGGER.info("[N]Success send mssaage count : {}", successList.size());

만일 전송에 실패한다면 로그를 확인하고 해당 오류를 수정해주시면 됩니다.

기타 내용은 아래의 링크를 참고해주세요.

 

Link : https://firebase.google.com/docs/cloud-messaging/send-message?hl=ko 

 

앱 서버 전송 요청 작성  |  Firebase 클라우드 메시징

5월 10일, Google I/O에서 Firebase가 돌아옵니다. 지금 등록하기 의견 보내기 앱 서버 전송 요청 작성 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Firebase Admin SD

firebase.google.com

 

반응형

댓글

💲 추천 글