Google Firebase 연동
FCM 아키텍처
build.gradle
implementation 'com.google.auth:google-auth-library-oauth2-http:1.19.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.7.1'
implementation 'com.google.firebase:firebase-admin:9.2.0'
비공개키 생성
https://console.firebase.google.com/u/1/project/digital-receipt-f71ef/settings/serviceaccounts/adminsdk?hl=ko
새 비공개 키 생성을 하면 json 파일이 다운로드 되어지는데, 다운로드 받은 json 파일을 프로젝트 폴더로 옮긴다.
프로젝트 ID확인
https://console.cloud.google.com/projectselector2/settings/general?authuser=1&hl=ko&pli=1
푸시 메시지를 전송하는 방법은 admin을 이용하는 방법과 구글 인증라이브러리를 사용하는 방법 두 가지가 있다.
admin 방식
String serviceAccountKeyPath = "firebase/digital-receipt-f71ef-firebase-adminsdk-v7ayu-604f77e641.json";
Resource serviceAccountResource = new ClassPathResource(serviceAccountKeyPath);
InputStream serviceAccountStream = serviceAccountResource.getInputStream();
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccountStream))
.setProjectId("프로젝트 ID")
.build();
FirebaseApp.initializeApp(options);
com.google.firebase.messaging.Message message = ...
String response = FirebaseMessaging.getInstance().send(message);
System.out.println(response);
// projects/digital-receipt-f71ef/messages/0:1695101285793698%726136130198d25a
구글 인증 라이브러리 방식
admin 방식과 다르게 Message를 커스마이징한 객체를 만들어줘야 한다. 그 이유는 resttemplate로 json을 직접 전송해야되는데 com.google.firebase.messaging.Message를 그대로 json으로 변환하면 json 형식이 맞지 않기 때문이다. 따라서 다음과 같이 메시지 클래스를 생성하여 사용한다.
@Getter
@AllArgsConstructor
@Builder
public class FcmMessage {
@JsonProperty("validate_only")
private boolean validateOnly;
private Message message;
@Getter
@AllArgsConstructor
@Builder
public static class Message {
private final String token;
private final Data data;
private final Notification notification;
private final AndroidConfig android;
private final ApnsConfig apns;
}
@Getter
@AllArgsConstructor
@Builder
public static class Data {
private final String message;
private final String time;
@JsonProperty("registration_ids")
private final String registrationIds;
private final String senderId;
}
@Getter
@AllArgsConstructor
@Builder
public static class Notification {
private final String title;
private final String body;
}
}
{
final String fcmEndPoint = "https://fcm.googleapis.com/v1/projects/프로젝트ID/messages:send";
FcmMessage fcmMessage = ...
String accessToken = getAccessToken();
final HttpHeaders httpHeaders = new HttpHeaders();
final String PREFIX_ACCESS_TOKEN = "Bearer ";
httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
httpHeaders.add(HttpHeaders.AUTHORIZATION, PREFIX_ACCESS_TOKEN + accessToken);
final HttpEntity<String> httpEntity = new HttpEntity<>(gson.toJson(fcmMessage), httpHeaders);
restTemplate.exchange(
fcmEndPoint,
HttpMethod.POST,
httpEntity,
String.class);
}
private String getAccessToken() {
try {
String serviceAccountKeyPath = "firebase/digital-receipt-f71ef-firebase-adminsdk-v7ayu-604f77e641.json";
Resource serviceAccountResource = new ClassPathResource(serviceAccountKeyPath);
InputStream serviceAccountStream = serviceAccountResource.getInputStream();
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(serviceAccountStream)
.createScoped(List.of("https://www.googleapis.com/auth/cloud-platform"));
googleCredentials.refreshIfExpired();
return googleCredentials.getAccessToken().getTokenValue();
} catch (Exception e) {
return null;
}
}
기타 참조
https://medium.com/@rajdeepify/push-notifications-using-springboot-and-firebase-cloud-messaging-ad136746c57e
https://velog.io/@komment/Spring-Boot-APNs%EA%B3%BC-FCM%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%ED%91%B8%EC%8B%9C%EC%95%8C%EB%A6%BC-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-2-an9sfu6s
댓글남기기