Spring에 FCM 자동 푸시 서버 구현하기

안상철·2023년 1월 13일
2
post-custom-banner

드디어!!!!! 따북에 정해진 시간마다 책 구절을 보내줄 서버를 구현할 수 있게 되었다!!!!

기쁜 마음으로 포스팅을 해본다~~

참고: https://gksdudrb922.tistory.com/192

1. bundle.gradle

implementation("com.google.firebase:firebase-admin:7.1.0")

스프링에서 firebase를 사용할 수 있도록 디펜던시를 추가 해 준다.

2. ScheduledConfig

다음은 설정파일이다.

@Configuration
class ScheduledConfig {

    private val POOL_SIZE = 10

    fun scheduler(): TaskScheduler {
        val scheduler = ThreadPoolTaskScheduler()
        scheduler.poolSize = POOL_SIZE
        return scheduler
    }

}

POOL_SIZE는 한 번에 처리할 수 있는 메세지 수라고 하는데 10개로 지정 해 두었다. 사용자가 그렇게 많지 않아서 상관 없을 것 같다^^ 나중에 사용자 수가 많아지면 늘려야지..

그리고 설정파일이므로 Configuration 어노테이션을 꼭 붙여줘야한다. 경험상 이 어노테이션이 없으면 작동하지 않았다.

3. 메세지 형식 NotificationMessage

data class NotificationMessage(
     val title: String,
     val message: String
)

역시나 data class로 구현했고 제목과 메세지를 담도록 했다. 찾아보니 파이어베이스에서 보낼 수 있는 메세지 형식이 있는데 제목과 본문이 필요했다.

4. NotificationScheduler

@Service
class NotificationScheduler (

    private val bookCommandService: BookCommandService

) {

    private var instance: FirebaseMessaging? = null

    @PostConstruct
    @Throws(IOException::class)
    fun firebaseSetting() {
        val googleCredentials =
            GoogleCredentials.fromStream(ClassPathResource("firebase/어쩌구저쩌구.json").inputStream)
                .createScoped(listOf("https://www.googleapis.com/auth/firebase.messaging"))
        val secondaryAppConfig = FirebaseOptions.builder()
            .setCredentials(googleCredentials)
            .build()
        val app = FirebaseApp.initializeApp(secondaryAppConfig)
        instance = FirebaseMessaging.getInstance(app)
    }

    fun getRandomMessage(): NotificationMessage {
        val title = "${bookCommandService.getRandomBookNoAuth().title}_${bookCommandService.getRandomBookNoAuth().author}"
        val message = bookCommandService.getRandomBookNoAuth().content
        return NotificationMessage(title, message)
    }

    @Scheduled(cron = "0 0 08 * * ?")
    @Throws(FirebaseMessagingException::class)
    fun pushMorningAlarm() {
        pushAlarm(getRandomMessage())
    }

    @Scheduled(cron = "0 0 13 * * ?")
    @Throws(FirebaseMessagingException::class)
    fun pushLunchAlarm() {
        pushAlarm(getRandomMessage())
    }

    @Scheduled(cron = "0 00 19 * * ?")
    @Throws(FirebaseMessagingException::class)
    fun pushDinnerAlarm() {
        pushAlarm(getRandomMessage())
    }

    @Throws(FirebaseMessagingException::class)
    fun pushAlarm(data: NotificationMessage) {
        val message = getMessage(data)
        sendMessage(message)
    }

    fun getMessage(data: NotificationMessage): Message {
        val notification = Notification.builder().setTitle(data.title).setBody(data.message).build()
        val builder = Message.builder()
        val topic = "토픽명"
        return builder.setTopic(topic).setNotification(notification).build()
    }

    @Throws(FirebaseMessagingException::class)
    fun sendMessage(message: Message?): String? {
        return instance!!.send(message)
    }

}

대망의 파이어베이스 서비스를 구동시킬 부분이다. 서비스이므로 Service 어노테이션을 붙여준다.

Firebase 비공개 키를 생성해야 한다.

위 이미지처럼 비공개 키 파일을 생성하는데 자바로 생성 해 준다.
다음은 원하는 디렉토리에 넣어주면 되는데, 나는 API 모듈의 resource부분에 디렉토리를 따로 만들어 넣어주었다.

알림을 보내는 방식은 토큰방식과 토픽방식이 있다고 하는데 나는 참고한 포스팅처럼 토픽방식을 채택했다.

토큰방식은 db에 사용자별 토큰을 저장하고, 그 값을 불러와 비교해야하는데 로직이 복잡해지므로 토픽방식을 추천한다.

파이어베이스 토픽은 앱이 구동될 때 생성되어 알림을 보낼 때 토픽을 체크해 해당 토픽을 가진 앱이 있으면 그 앱들에게 알림을 보내는 방식으로 구현된다.

따라서 안드로이드 스튜디오 앱이 켜질 때 onCreate 하위에

FirebaseMessaging.getInstance().subscribeToTopic("토픽명");

을 기재 해 줘야한다.

위에서부터 살펴보면 GoogleCredentials.fromStream 구문을 통해 파이어베이스에 접속하고

Scheduled 어노테이션을 통해 주기적으로, 내가 cron 형식으로 정해 준 시간마다 특정 메서드를 실행하도록 한다. 물론 여기서는 푸시 알림을 보낸다.

getRandomMessage 구절은 따북 프로젝트에서 랜덤으로 책 내용을 찾아주는 기능이므로 원하는 로직을 작성 해 주면 되겠다.

5. ApiApplication

@EnableScheduling
@ConfigurationPropertiesScan
@SpringBootApplication(
    scanBasePackages = ["kr.co.book.list.domain", "kr.co.book.list.lib", "kr.co.book.list.api"]
)
class ApiApplication

fun main(args: Array<String>) {
    runApplication<ApiApplication>(*args)
}

스프링 부트를 실행할 때 @EnableScheduling 어노테이션이 필요하다. 이 어노테이션이 붙어있어야 스케줄링이 가능해진다.


이제 출근길 8시, 점심먹고 1시, 저녁먹고 7시에 다른 사람들이 작성한 예쁜 책 내용을 푸시 알림으로 받을 수 있다~~ 야호~~

profile
웹 개발자(FE / BE) anna입니다.
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 12월 1일

오 멋있습니다👍👍

답글 달기