일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- javascript
- MariaDB
- mysql
- yona
- NextJS
- nodejs
- spring3
- docker
- rocky9
- security
- PM2
- popup
- MSsql
- pwa
- Java
- Eclipse
- submit
- Push
- Maven
- git
- SpringBoot
- FCM
- centos7
- jquery
- Next.js
- node.js
- ajax
- config
- jenkins
- mybatis
- Today
- Total
ふたりで
springboot+web(jsp)+fcmSDK11.x+getToken+PWA 본문
springboot jsp 프로젝트에서 Firebase SDK(javascript버전)을 적용해 PushMessage를 수신받는 기능을
만들어 보았다.
# 환경:
- SpringBoot2.7.12
- Maven.
- PWA.
- Firebase admin V9 (CDN) javascript
- 참고 사이트:
https://firebase.google.com/docs/cloud-messaging/js/client?hl=ko
1. 기본 프로젝트를 설정한 Maven설정 파일.
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.graykang.test2</groupId>
<artifactId>spring-boot-test2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-boot-test2</name>
<description>Demo project for Spring Boot test2</description>
<properties>
<java.version>1.8</java.version>
<log4j2.version>2.17.1</log4j2.version>
<logback.version>1.2.9</logback.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- jsp config -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</project>
2. 프로젝트 구조
3. Spring Boot 애플리케이션의 기본 구조를 정의하는 Java 클래스 SpringBootTest2Application.java파일 생성.
이 클래스는 Spring Boot 애플리케이션을 설정하고 실행하는 기본 구조를 제공한다.
서블릿 구성 요소를 자동으로 스캔하고, 애플리케이션의 메인 설정을 정의하며, Java의 표준 애플리케이션 시작 방식을 제공한다.
package com.graykang.test2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@ServletComponentScan
@SpringBootApplication
public class SpringBootTest2Application extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(SpringBootTest2Application.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootTest2Application.class, args);
}
}
4. FrontController.java 파일 생성.
이 클래스는 Spring MVC를 사용하여 HTTP 요청을 처리하고, Firebase와 관련된 설정을 제공한다.
package com.graykang.test2.front.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class FrontController {
private static Logger logger = LoggerFactory.getLogger(FrontController.class);
@GetMapping(value = "/")
public String mainDashBoard(Model model, HttpServletRequest request) {
logger.info("==="+request);
return "redirect:/dashBoard";
}
@GetMapping(value = "/dashBoard")
public String mainDashBoard2(Model model, HttpServletRequest request) {
logger.info("==="+request);
return "/front/mainDashBoardV11";
}
@PostMapping(value = "/sendFcmToken.json")
public ResponseEntity<Void> sendFcmToken(@RequestParam("fcmToken") String fcmToken) {
logger.info("FCM Token: " + fcmToken);//나중에 회원 정보와 맵핑 하여 토큰을 DB에 저장
return ResponseEntity.ok().build(); // 200 OK 응답 반환
}
/*FCM AUth Config Params*/
@Value("${firebase.apiKey}")
private String apiKey;
@Value("${firebase.authDomain}")
private String authDomain;
@Value("${firebase.projectId}")
private String projectId;
@Value("${firebase.storageBucket}")
private String storageBucket;
@Value("${firebase.messagingSenderId}")
private String messagingSenderId;
@Value("${firebase.appId}")
private String appId;
@Value("${firebase.measurementId}")
private String measurementId;
@Value("${firebase.vapidKey}")
private String vapidKey;
@GetMapping(value="/firebase-config.json")
@ResponseBody
public Map<String, String> getFirebaseConfig() {
Map<String, String> config = new HashMap<>();
config.put("apiKey", apiKey);
config.put("authDomain", authDomain);
config.put("projectId", projectId);
config.put("storageBucket", storageBucket);
config.put("messagingSenderId", messagingSenderId);
config.put("appId", appId);
config.put("measurementId", measurementId);
config.put("vapidKey", vapidKey);
return config;
}
}
5. application.properties 파일 생성.
프로퍼티 파일에는 DB접속 정보와 firebase admin에서 사용될 키값(설정) 들이 명시 되어있다.
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/TEST_FCM
spring.datasource.username=user01
spring.datasource.password=********
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
##jsp
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
##FCM auth Params
firebase.apiKey=****************************************
firebase.authDomain=************************************
firebase.projectId=*************
firebase.storageBucket=********************************
firebase.messagingSenderId=**************
firebase.appId=********************************************
firebase.measurementId=*********
firebase.vapidKey=*****************************************************************************
6. mainDashBoard.jsp 파일 생성.
해당 JSP 페이지는 Spring Boot 애플리케이션에서 PWA를 구현하기 위한 기본 구조를 제공한다.
Firebase Admin의 getMessaging을 사용하여 푸시 알림 기능을 설정하고, 사용자의 FCM 토큰을 발급받아
서버에 전송하는 로직을 포함하고 있다.
그리고 서비스 워커를 등록하여 푸시 알림을 수신할 준비를 하며, 사용자에게 알림 권한을 요청한다.
주의: 운영 환경에서는 임포트 부분은 번들해서 사용 하는걸 권장한다. 아래 링크 참고.
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.2/firebase-app.js";
import { getMessaging, getToken } from "https://www.gstatic.com/firebasejs/11.0.2/firebase-messaging.js";
# 위의 두개의 라이브러리를 운영 에서 사용 하기 위한 bundle 작업.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
var ctx = "${pageContext.request.contextPath}";
</script>
<link rel="manifest" href="/manifest.json"> <!-- PWA 설치용 manifest -->
<title>Spring Boot PWA</title>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.2/firebase-app.js";
import { getMessaging, getToken } from "https://www.gstatic.com/firebasejs/11.0.2/firebase-messaging.js";
// Firebase 설정을 서버에서 가져옵니다.
fetch('/firebase-config.json',{
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
}
)
.then(response => response.json())
.then(firebaseConfig => {
// Firebase 앱 초기화
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
// 서비스워커 등록
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(ctx + 'firebase-messaging-sw.js', { type: 'module' })
.then(function (reg) {
console.log('서비스워커 등록 성공 :', reg);
// FCM 토큰 요청
return getToken(messaging, { vapidKey: '' }); // VAPID 키 추가 필요
})
.then((currentToken) => {
if (currentToken) {
console.log('FCM 토큰:', currentToken);
document.getElementById("fcmToken").value = currentToken;
// 서버에 FCM 토큰 전송
return fetch('/sendFcmToken.json', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'fcmToken': currentToken
})
});
} else {
console.log('FCM 토큰을 생성할 수 없습니다.');
}
})
.then(response => {
if (response.ok) {
console.log('FCM 토큰이 성공적으로 서버에 전송되었습니다.');
} else {
console.error('FCM 토큰 전송 실패:', response.status);
}
})
.catch(function (error) {
console.log('서비스워커 등록 또는 FCM 토큰 생성 중 오류 발생:', error);
});
}
// 알림 권한 요청
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('사용자가 알림을 허용했습니다.');
} else {
alert('브라우저 설정에서 알림을 허용해 주세요.');
}
}).catch((error) => {
console.error('알림 권한 요청 중 오류 발생:', error);
});
})
.catch(error => console.error('Firebase 설정을 가져오는 중 오류 발생:', error));
</script>
</head>
<body>
<h1>Welcome to My Spring Boot PWA</h1>
<div>
fcm-token:
</div>
<textarea style="width: 257px; height: 121px;" id="fcmToken" readonly></textarea>
</body>
</html>
7. firebase-messaging-sw.js 파일 생성.
해당 소스는 서비스워커 파일이며, FCM을 통해 푸시 알림을 수신하고, 이를 사용자에게 보여 준다.
사용자가 알림을 클릭하면 지정된 URL로 이동할 수 있도록 설정되어 있다.
// 백그라운드 메시지 수신 처리
self.addEventListener('push', (event) => {
const payload = event.data ? event.data.json() : {};
console.log('Push event received: ', payload);
const title = payload.notification.title || '알림';
const options = {
body: payload.notification.body || '새로운 메시지가 도착했습니다.',
icon: payload.notification.icon || '/path/to/default/icon.png',
data: payload.notification.click_action || '/'
};
event.waitUntil(
self.registration.showNotification(title, options)
);
});
// 알림 클릭 이벤트 처리
self.addEventListener('notificationclick', function(event) {
console.log(event.notification);
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data)
);
});
8. manifest.json 파일 생성.
사용자가 웹 애플리케이션을 설치할 때 필요한 정보를 제공하여, 네이티브 애플리케이션과 유사한 사용자 경험을 제공한다. 이 설정에 따라 앱의 이름, 시작 URL, 표시 방식, 배경색, 테마 색상, 아이콘 등이 결정된다.
{
"name": "graykang Spring Boot PWA Fcm Token",
"short_name": "GK_PWA_FCM",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
9. 서비 실행 후 최종 페이지가 로딩된 UI
10. 애플리케이션처럼 설치 됐을 때의 UI
'Spring' 카테고리의 다른 글
submit 후 브라우저 버튼에 의해 뒤로 갈 경우 입력 화면 접근 막기. (0) | 2024.10.29 |
---|---|
Http v1 FCM Admin SDK mulit tocken send message By topic (0) | 2024.06.27 |
SpringBoot2.3.3 TO SpringBoot2.7.12 upgrad (0) | 2024.03.27 |
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to ~ 관련 정보. (0) | 2024.03.14 |
Spring3 @Scheduled를 사용하기 위한 준비 (1) | 2023.12.12 |