백엔드 서버의 특정 상황에서 Push Notification을 위해 Firebase Message를 전송시키는 API를 작성해보자
우선 Firebase 페이지에서 JSON 키 파일을 받아 프로젝트에 첨부했다는 전제 하에 글을 써보겠다
기본적으로 Firebase Messaging을 이용하기 위해선 위의 키 파일을 받아 SDK에서 이를 가지고 구글 인증을 한 다음 인증 정보를 포함한 Firebase Instance를 조작하는 방식이다
@Configuration을 통해 서버가 시작되는 시점에 Firebase를 초기화하고 Bean을 등록하기로 했다
키 파일은 resources에 넣고 해당 파일의 이름으로 Class Path를 만들어 파일을 읽어온 다음 GoogleCredentials 객체로 만들어줬다
@Configuration
public class FirebaseMessagingConfig {
@Bean("firebaseMessaging")
public FirebaseMessaging firebaseMessaging() throws IOException {
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource("awsome-new-firebase-adminsdk-key.json").getInputStream());
}
Firebase 를 초기화 시켜줄텐데 위에서 만든 객체를 setCredentials를 통해 넣어주면 된다
credential 이외에도 Firebase 기반 다른 라이브러리들을 사용할 경우 해당 라이브러리의 정보를 입력해줄 수 있다
또한 Instance를 받아올 때 이미 해당 프로젝트의 이름으로 FirebaseApp이 생성되어 있는지 검사하는 코드도 넣어주자
FirebaseOptions firebaseOptions = FirebaseOptions
.builder()
.setCredentials(googleCredentials)
.build();
FirebaseApp app = null;
for (FirebaseApp a : FirebaseApp.getApps()) {
if (a.getName().equals("awsome-project")) {
app = a;
break;
}
}
if (app == null) {
app = FirebaseApp.initializeApp(firebaseOptions, projectId);
}
return FirebaseMessaging.getInstance(app);
}
이제 준비는 얼추 끝났다
메세지를 날리러 가보자
대충 위에서 만든 FirebaseMessaging을 의존하는 FirebaseMessagingService를 하나 만들어 주자
@RequiredArgsConstructor
@Service
public class FirebaseMessagingServiceImpl implements FirebaseMessagingService {
private final FirebaseMessaging firebaseMessaging;
@Override
public void send(String channelId, String targetToken, String title, String message, String image, Map<String, String> data) {
}
}
channelId는 메세지들을 구분하는 기준이고
targetToken은 device 측에서 token이 부여되는데 이것을 서버에서 저장하고 있다가 메세지 날릴 때 넣어주면 이 token을 가지고 해당 device에 메세지를 보내준다
우리는 Push Notification을 사용할 것이기 때문에 제일 먼저 Notification 객체를 만들어준다
private void send(String channelId, String targetToken, String title, String message, String image, Map<String, String> data) {
Notification notification = Notification.builder()
.setTitle(title)
.setBody(message)
.setImage(image)
.build();
그 다음 안드로이드와 iOS에서 해당 메세지를 수신할 수 있도록 Config 객체를 메세지에 넣어주어야 하는데 두 운영체제의 형식이 달라 따로 넣어줘야 한다
AndroidNotification androidNotification = AndroidNotification.builder()
.setChannelId(channelId)
.build();
AndroidConfig androidConfig = AndroidConfig.builder()
.setNotification(androidNotification)
.build();
ApnsConfig apnsConfig = ApnsConfig.builder()
.setAps(Aps.builder()
.putCustomData("channelId", channelId)
.build())
.build();
이제 위에서 만든 객체들을 Message 객체에 전부 담아 firebaseMessaging의 send 함수에 넣어 전송해주면 된다
Message msg;
if (data != null) {
msg = Message.builder()
.setToken(targetToken)
.setNotification(notification)
.setAndroidConfig(androidConfig)
.setApnsConfig(apnsConfig)
.putAllData(data)
.build();
} else {
msg = Message.builder()
.setToken(targetToken)
.setNotification(notification)
.setAndroidConfig(androidConfig)
.setApnsConfig(apnsConfig)
.build();
}
try {
firebaseMessaging.send(msg);
} catch (FirebaseMessagingException e) {
e.printStackTrace();
}
}