Spring

Spring Boot + FCM 웹 푸시 사용하기

Beekei 2021. 12. 2. 14:26
반응형
FCM란?

Firebase 클라우드 메시징(FCM)은 무료로 메시지를 안정적으로 전송할 수 있는 교차 플랫폼 메시징 솔루션이다.

간단히 말해서 무료로 웹, 앱에 푸시를 보낼 수 있는 플랫폼이다.

 

사용법

  1. Firebase console에 접속해 프로젝트를 생성한다.


  2. 프로젝트 설정 -> 서비스 계정 -> 새 비공개 키 생성


  3. 다운받은 비공개 키를 resources 하위로 이동


  4. Firebase의존성 추가
    dependencies {
    
    	...
        
    	// Firebase SDK
    	implementation 'com.google.firebase:firebase-admin:6.8.1'
        
    	...
        
    }


  5. 엔드포인트 확인
     프로젝트 설정 -> 일반에 프로젝트 ID를 확인할 수 있을것이다.
    요 프로젝트 ID를 서버 엔드포인트에 넣어줄것이다.
    https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ko
    엔드포인트는 업데이트 이후 노란색 줄이 그어진 부분에 프로젝트 ID를 넣어주면 된다.


  6. API 호출
    FCM은 API Key를 사용해서 인증을 받았지만 업데이트 후에는 Access Token을 발급받아 인증하도록 변경되었다.
    따라서 Firebase에서 Access Token을 발급받아 Push알림 요청을 보낼때 Header 첨부하여 요청한다. 참고
    @RequiredArgsConstructor
    public class FirebaseSender {
    
        private final RestTemplate restTemplate;
        // 비공개 키 경로
        private final String CONFIG_PATH = "firebase/firebase-key.json";
        // 토큰 발급 URL
        private final String AUTH_URL = "https://www.googleapis.com/auth/cloud-platform";
        // 엔드포인트 URL
        private final String SEND_URL = "https://fcm.googleapis.com/v1/projects/프로젝트ID/messages:send";
    	
        private String getAccessToken() throws IOException { // 토큰 발급
            GoogleCredentials googleCredentials = GoogleCredentials
              .fromStream(new ClassPathResource(CONFIG_PATH).getInputStream())
              .createScoped(List.of(AUTH_URL));
            googleCredentials.refreshIfExpired();
            return googleCredentials.getAccessToken().getTokenValue();
        }
        
        @Getter
        @Builder
        private static class PushPayload { // API 호출시 Body에 보낼 객체
            private boolean validate_only;
            private PushMessage message;
            
            @Getter
            @Builder
            private static class Message {
                private String token;
                private PushNotification notification;
            }
    
            @Getter
            @Builder
            private static class Notification {
                private String title;
                private String body;
                private String image;
            }
        }
    
        private PushPayload getBody(String to, String title, String body) {
            return PushPayload.builder()
                    .validate_only(false)
                    .message(PushPayload.Message.builder()
                            .token(to)
                            .notification(PushPayload.Notification.builder()
                                    .title(title)
                                    .body(body)
                                    .image(null)
                                    .build())
                            .build())
                    .build();
        }
    
        public void pushBrowserSend(String to, String title, String body) { // 발송 API 호출
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
            headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken());
    
            final HttpEntity<Object> entity = new HttpEntity<>(getBody(to, title, body), headers);
            final ResponseEntity<String> response = restTemplate.exchange(SEND_URL, HttpMethod.POST, entity, String.class);
            
            final HttpStatus status = response.getStatusCode();
            final String responseBody = response.getBody();
            if (status.equals(HttpStatus.OK)) {
            	// 발송 API 호출 성공
            } else {
            	// 발송 API 호출 실패
            }
        }
    
    }

    여기서 pushBrowserSend함수의 to 매개변수는 앱 토큰이다.
    아래에서 앱 토큰은 어떻게 발급받는지 알아보자.


  7. 앱 토큰 발급받기 
    프로젝트 개요 -> 앱 추가 -> 웹
    해당 firebaseConfig 정보를 복사해서 resources/static/firebase-message-sw.js에 설정해준다.
    Firebase에서 http://localhost:8080/firebase-message-sw 경로로 조회를 하기 때문에 resources/static 폴더 안에 넣어주어야 한다.
    // resources/static/firebase-message-sw.js
    importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
    importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');
    
    // Initialize Firebase
    var config = {
        apiKey: "***************",
        authDomain: "***************",
        projectId: "***************",
        storageBucket: "***************",
        messagingSenderId: "***************",
        appId: "***************",
        measurementId: "***************"
    };
    
    firebase.initializeApp(config);
    const messaging = firebase.messaging();
    
    messaging.setBackgroundMessageHandler(function (payload) {
        const title = "Hello World";
        const options = { body: payload.data.status };
        return self.registration.showNotification(title, options);
    });​
     

    이제 스크립트를 실행해서 토큰을 받아와야 하는데 아무 프론트 화면에 스크립트를 넣어준다.
    <!DOCTYPE html>
    <html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
            <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
            <title>Firebase get Token Example</title>
        </head>
        <body>
        </body>
    </html>
    <script src="https://www.gstatic.com/firebasejs/5.9.2/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.9.2/firebase-messaging.js"></script>
    <script>
        var config = {
            apiKey: "***************",
            authDomain: "***************",
            projectId: "***************",
            storageBucket: "***************",
            messagingSenderId: "***************",
            appId: "***************",
            measurementId: "***************"
        };
        firebase.initializeApp(config);
    
        const messaging = firebase.messaging();
    
        //token값 알아내기
        messaging.requestPermission()
            .then(function() {
                // 알람이 허용되었을 때 토큰을 반환합니다.
                // 해당 토큰을 통해 FCM 특정 사용자에게 메시지를 보낼 수 있습니다.
                return messaging.getToken();
            })
            .then(async function(token) {
                console.log(token);
                // 해당 onMessage는 데이터메시지로, 포그라운드인 상태에서
                // FCM 메시지를 전송하는 경우 콘솔에 표기하도록 작성된 코드입니다.
                messaging.onMessage(payload => {
                    console.log(payload);
    
                })
            });
    </script>
    config 변수에도 아까 위에서 firebase-message-sw.js에 설정한 값을 넣어준다.
    해당 페이지를 접속하면 콘솔에 토큰값이 나올것이다.
반응형