Project/FootballManager(MSA)
SpringBoot 3.1.6 FCM 적용 (2)
48965
2024. 3. 20. 12:56
저번 1편에서 User Service에 FCM 사용을 고려하여 토큰 저장 관련 로직을 작성하였다. 이번에는 Team Service 내에서 실제 FCM 서버 연동에 사용할 클래스들을 작성하고자 한다.
그림으로 보자면 1,2에 해당하는 작업은 1편에서 포스팅 하였으며, 이번 포스팅에서는 나머지 작업을 마무리해보려 한다.
1. build.gradle
// FCM
implementation group: 'com.google.firebase', name: 'firebase-admin', version: '9.2.0'
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.12.0'
먼저 프로젝트 내 FCM을 사용하기 위해 의존성을 추가시킨다.
- Firebase Admin SDK 의존성은 서버 측에서 Firebase의 다양한 기능을 제어할 수 있게 된다. 이 기능에는 사용자 인증, Firebase Cloud Messaging, Firebase Realtime Database, Firestore 등이 포함된다.
- OkHttp는 HTTP 및 HTTP/2 클라이언트를 위한 Java 라이브러리이다. 네트워크 요청을 보내고 응답을 받는 데 사용된다. Firebase Admin SDK 내부에서는 HTTP 통신을 위해 OkHttp가 사용될 수 있다.
2. FCMConfig
@Configuration
public class FCMConfig {
@Bean
public FirebaseApp firebaseApp() throws IOException {
InputStream serviceAccountStream = new ClassPathResource("firebase/firebase_service_key.json").getInputStream();
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccountStream))
.build();
return FirebaseApp.initializeApp(options);
}
@Bean
public FirebaseMessaging firebaseMessaging(FirebaseApp firebaseApp){
return FirebaseMessaging.getInstance(firebaseApp);
}
}
FCM 관련 설정 클래스이다.
- ClassPathResource를 사용하여 firebase/firebase_service_key.json 서비스 계정 키 파일을 읽고, 이를 GoogleCredentials에 전달하여 인증 정보를 생성한다.
- FirebaseOptions를 사용하여 Firebase 애플리케이션의 설정을 구성하고, 이를 사용하여 FirebaseApp을 초기화시키면, 정상적인 FCM 호출이 가능하다.
3. FCMService 로직 작성
/**
* 토큰 기반 전송 -> 특정 사용자의 디바이스에 개별적인 알림을 전송(특정 한명에게 전송)
* @param fcmToken
* @param scheduleNotificationDto
*/
public void sendNotificationToToken(String fcmToken,
ScheduleNotificationDto scheduleNotificationDto) {
Message message = Message.builder()
.setNotification(getnotification())
.setToken(fcmToken)
.putAllData(getData(scheduleNotificationDto))
.build();
try {
String response = FirebaseMessaging.getInstance().send(message);
log.info("전송 성공: " + response);
} catch (Exception e) {
log.info("전송 실패: " + e);
}
}
- SendNotificationToToken 메서드는 토큰을 통해 FCM에 메시지를 보내는 메서드이다.
- 해당 메서드에서 FCM 서버를 통해 전송할 Message 객체를 구성한다.
- 여기서 Message의 필드는 Notification, token, data로 이루어져 있으며, data의 영역은 DTO 클래스를 통해 구성한다.
private Notification getnotification(){
Notification notification = Notification.builder()
.setTitle("새로운 일정")
.setBody("일정이 생성되었습니다")
.build();
return notification;
}
- Notification 객체 구성이다.
- SendNotificationToToken 메서드의 Message를 구성하기 위한 단계로, 제목과 내용을 구성하여 넣어주면 된다.
private Map<String,String> getData(ScheduleNotificationDto scheduleNotificationDto){
Map<String, String> data = new HashMap<>();
data.put("title", scheduleNotificationDto.getTitle());
data.put("memo", scheduleNotificationDto.getMemo());
data.put("homeTeamName", scheduleNotificationDto.getHomeTeamName());
data.put("homeTeamImage", scheduleNotificationDto.getHomeTeamEmblem());
data.put("homeTeamUniqueNumber", scheduleNotificationDto.getHomeTeamUniqueNumber());
data.put("awayTeamName", scheduleNotificationDto.getAwayTeamName());
data.put("awayTeamImage", scheduleNotificationDto.getAwayTeamEmblem());
data.put("awayTeamUniqueNumber", scheduleNotificationDto.getAwayTeamUniqueNumber());
data.put("startTime", scheduleNotificationDto.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
data.put("endTime", scheduleNotificationDto.getEndTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
data.put("place", scheduleNotificationDto.getPlace());
data.put("longitude", scheduleNotificationDto.getLongitude().toString());
data.put("latitude", scheduleNotificationDto.getLatitude().toString());
return data;
}
- Data는 Dto 클래스에서 가져온 값들을 Map의 형태로 변환하여 반환시킨다.
- 마찬가지로 SendNotificationToToken 메서드의 Message를 구성하기 위한 단계로서 필요한 값들을 Map의 형태로 채워주면 된다.
4. Github Action 스크립트 수정
- name: Create Firebase Config Directory
run: |
mkdir -p src/main/resources/firebase
echo "${{ secrets.FIREBASE_SERVICE_KEY }}" | base64 --decode > src/main/resources/firebase/firebase_service_key.json
shell: bash
- src/main/resources/firbase 디렉토리 생성 후 내부에 파이어베이스 생성 시 발급한 json 키를 등록한다.
- 이 때 json의 내용이 짧지 않기에, base64로 인코딩하여 내부 시크릿에 등록해두었다. 때문에 이를 사용 시 디코딩하여 파일을 쓰는 과정을 추가해주었다.
5. ScheduleService
// feign을 통해 유저 서비스에서의 fcm 토큰 조회
String fcmToken = userServiceClient.getFcmToken(createScheduleRequestDto.getAwayTeamId());
fcmService.sendNotificationToToken(fcmToken, scheduleNotificationDto);
scheduleRepository.save(schedule);
- 일정 생성 메소드의 FCM 호출 부분이다.
- fegin을 통해 user service에서 FCM 토큰을 조회 후 fcmService의 sendNotificationToToken 메서드를 호출한다. 이때 토큰과 일정 생성을 위한 Dto 값을 파라미터로 전달한다.
6. 테스트
- 개발이 완료되고, 서버를 가동했을 때 FcmConfig는 정상적으로 실행이 완료되었다.
- 이후 일정 생성 메서드를 호출한 결과인데, FCM 서버에 토큰을 전달했을 때, FCM에 등록된 토큰이 없다는 예외를 반환받아 로그에서 확인해 볼 수 있었다. 이를 통해 FCM 서버와 정상적으로 통신이 완료된 것을 확인할 수 있었다.