From a1a9a26b1b393f1b42cd06fbc16fc7bdaecb57ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 22 May 2026 15:29:31 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20FcmSendRequest=20DTO=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/fcm/FcmSendRequest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java new file mode 100644 index 000000000..308a45c8d --- /dev/null +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java @@ -0,0 +1,33 @@ +package in.koreatech.koin.infrastructure.fcm; + +import in.koreatech.koin.common.model.MobileAppPath; + +public record FcmSendRequest( + String targetDeviceToken, + String title, + String content, + String imageUrl, + MobileAppPath path, + String schemeUri, + String type +) { + public static FcmSendRequest of( + String targetDeviceToken, + String title, + String content, + String imageUrl, + MobileAppPath path, + String schemeUri, + String type + ) { + return new FcmSendRequest( + targetDeviceToken, + title, + content, + imageUrl, + path, + schemeUri, + type + ); + } +} From 9a6300251b08889bc8a8a94b505b0d345e07aa88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 22 May 2026 16:16:58 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20FcmSendRequest=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcm/{FcmSendRequest.java => FcmSendCommand.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/main/java/in/koreatech/koin/infrastructure/fcm/{FcmSendRequest.java => FcmSendCommand.java} (85%) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java similarity index 85% rename from src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java rename to src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java index 308a45c8d..aece5e230 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java @@ -2,7 +2,7 @@ import in.koreatech.koin.common.model.MobileAppPath; -public record FcmSendRequest( +public record FcmSendCommand( String targetDeviceToken, String title, String content, @@ -11,7 +11,7 @@ public record FcmSendRequest( String schemeUri, String type ) { - public static FcmSendRequest of( + public static FcmSendCommand of( String targetDeviceToken, String title, String content, @@ -20,7 +20,7 @@ public static FcmSendRequest of( String schemeUri, String type ) { - return new FcmSendRequest( + return new FcmSendCommand( targetDeviceToken, title, content, From 5bc7192031a3d5be3576ba3d35726c75006f6e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 22 May 2026 16:25:39 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20sendMessages=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/infrastructure/fcm/FcmClient.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java index 776e98d5f..2b5b58db2 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java @@ -3,6 +3,7 @@ import static com.google.firebase.messaging.AndroidConfig.Priority.HIGH; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.springframework.scheduling.annotation.Async; @@ -70,6 +71,36 @@ public boolean sendMessageWithResult( } } + public void sendMessages(List commands) { + try { + List messages = commands.stream() + .map(command -> Message.builder() + .setToken(command.targetDeviceToken()) + .setApnsConfig(generateAppleConfig( + command.title(), + command.content(), + command.imageUrl(), + command.path(), + command.type(), + command.schemeUri() + )) + .setAndroidConfig(generateAndroidConfig( + command.title(), + command.content(), + command.imageUrl(), + command.schemeUri(), + command.type() + )) + .build() + ) + .toList(); + + FirebaseMessaging.getInstance().sendEach(messages); + } catch (Exception e) { + log.warn("FCM 알림 전송 실패", e); + } + } + private ApnsConfig generateAppleConfig( String title, String content, From a09422f169fd7d4654afb7ee42ac6ccb0d81a7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 22 May 2026 16:26:14 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20FcmSendCommand=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/infrastructure/fcm/FcmClient.java | 30 +++++++++---------- ...cmSendCommand.java => FcmSendRequest.java} | 6 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) rename src/main/java/in/koreatech/koin/infrastructure/fcm/{FcmSendCommand.java => FcmSendRequest.java} (85%) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java index 2b5b58db2..bb0efe49c 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java @@ -71,25 +71,25 @@ public boolean sendMessageWithResult( } } - public void sendMessages(List commands) { + public void sendMessages(List requests) { try { - List messages = commands.stream() - .map(command -> Message.builder() - .setToken(command.targetDeviceToken()) + List messages = requests.stream() + .map(request -> Message.builder() + .setToken(request.targetDeviceToken()) .setApnsConfig(generateAppleConfig( - command.title(), - command.content(), - command.imageUrl(), - command.path(), - command.type(), - command.schemeUri() + request.title(), + request.content(), + request.imageUrl(), + request.path(), + request.type(), + request.schemeUri() )) .setAndroidConfig(generateAndroidConfig( - command.title(), - command.content(), - command.imageUrl(), - command.schemeUri(), - command.type() + request.title(), + request.content(), + request.imageUrl(), + request.schemeUri(), + request.type() )) .build() ) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java similarity index 85% rename from src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java rename to src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java index aece5e230..308a45c8d 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendCommand.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmSendRequest.java @@ -2,7 +2,7 @@ import in.koreatech.koin.common.model.MobileAppPath; -public record FcmSendCommand( +public record FcmSendRequest( String targetDeviceToken, String title, String content, @@ -11,7 +11,7 @@ public record FcmSendCommand( String schemeUri, String type ) { - public static FcmSendCommand of( + public static FcmSendRequest of( String targetDeviceToken, String title, String content, @@ -20,7 +20,7 @@ public static FcmSendCommand of( String schemeUri, String type ) { - return new FcmSendCommand( + return new FcmSendRequest( targetDeviceToken, title, content, From 96c31a12e1d416e44664820649fe103c349e7bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 22 May 2026 16:41:09 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20FCM=20=EB=A1=9C=EA=B9=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/koreatech/koin/infrastructure/fcm/FcmClient.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java index bb0efe49c..d15d6698e 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java @@ -25,6 +25,8 @@ @Component public class FcmClient { + private static final int FCM_MESSAGE_BATCH_SIZE = 500; + @Async public void sendMessage( String targetDeviceToken, @@ -73,6 +75,11 @@ public boolean sendMessageWithResult( public void sendMessages(List requests) { try { + if (requests.size() > FCM_MESSAGE_BATCH_SIZE) { + log.warn("FCM 전송 최대 개수를 초과했습니다."); + return ; + } + List messages = requests.stream() .map(request -> Message.builder() .setToken(request.targetDeviceToken()) From 92347bd002b07a4857363e6a9687d78a2e0dde81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 24 May 2026 16:48:50 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=EB=B0=B0=EC=B9=98=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=A6=88=20=EB=B3=84=EB=A1=9C=20FCM=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EB=A1=9C=EC=A7=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/infrastructure/fcm/FcmClient.java | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java index d15d6698e..06c7c9c5d 100644 --- a/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java +++ b/src/main/java/in/koreatech/koin/infrastructure/fcm/FcmClient.java @@ -75,34 +75,32 @@ public boolean sendMessageWithResult( public void sendMessages(List requests) { try { - if (requests.size() > FCM_MESSAGE_BATCH_SIZE) { - log.warn("FCM 전송 최대 개수를 초과했습니다."); - return ; - } - - List messages = requests.stream() - .map(request -> Message.builder() - .setToken(request.targetDeviceToken()) - .setApnsConfig(generateAppleConfig( - request.title(), - request.content(), - request.imageUrl(), - request.path(), - request.type(), - request.schemeUri() - )) - .setAndroidConfig(generateAndroidConfig( - request.title(), - request.content(), - request.imageUrl(), - request.schemeUri(), - request.type() - )) - .build() - ) - .toList(); + for (int start = 0; start < requests.size(); start += FCM_MESSAGE_BATCH_SIZE) { + int end = Math.min(start + FCM_MESSAGE_BATCH_SIZE, requests.size()); + List messages = requests.subList(start, end).stream() + .map(request -> Message.builder() + .setToken(request.targetDeviceToken()) + .setApnsConfig(generateAppleConfig( + request.title(), + request.content(), + request.imageUrl(), + request.path(), + request.type(), + request.schemeUri() + )) + .setAndroidConfig(generateAndroidConfig( + request.title(), + request.content(), + request.imageUrl(), + request.schemeUri(), + request.type() + )) + .build() + ) + .toList(); - FirebaseMessaging.getInstance().sendEach(messages); + FirebaseMessaging.getInstance().sendEach(messages); + } } catch (Exception e) { log.warn("FCM 알림 전송 실패", e); }