From 2ea5c30c500de23f626b102198cbb5656b4b254d Mon Sep 17 00:00:00 2001 From: kanghana1 Date: Sun, 5 Jul 2026 13:42:49 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=EB=B6=80=ED=95=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9A=A9=20FCM=20=EC=9D=B8=EC=9C=84=EC=A0=81?= =?UTF-8?q?=20=EC=A7=80=EC=97=B0=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/fcm/FcmService.java | 35 +++++++++++++++++++ src/main/resources/application.yml | 4 +++ 2 files changed, 39 insertions(+) diff --git a/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java b/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java index ff1f9e71..4b73a7ce 100644 --- a/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java +++ b/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java @@ -8,6 +8,7 @@ import com.google.firebase.messaging.WebpushFcmOptions; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import umc.cockple.demo.domain.chat.enums.ChatRoomType; @@ -24,6 +25,13 @@ public class FcmService { private final MemberRepository memberRepository; private final FirebaseMessaging firebaseMessaging; + /** + * 부하테스트용 FCM 인위적 지연(ms). 스레드풀 벌크헤드 효과 측정 전용. + * 기본 0 → 평상시/운영에서는 완전히 비활성(동작 변화 없음). staging에서 env(FCM_FAKE_LATENCY_MS)로만 켠다. + */ + @Value("${fcm.fake-latency-ms:0}") + private long fakeLatencyMs; + @Transactional public void registerFcmToken(Long memberId, String fcmToken) { Member member = memberRepository.findById(memberId) @@ -33,6 +41,10 @@ public void registerFcmToken(Long memberId, String fcmToken) { } public void sendNotification(Member member, String title, String content) { + if (applyFakeLatencyAndSkip(member.getId())) { + return; + } + String fcmToken = member.getFcmToken(); if (fcmToken == null || fcmToken.isBlank()) { log.info("FCM 토큰 없음 - memberId: {}, 알림 전송 생략", member.getId()); @@ -58,6 +70,10 @@ public void sendNotification(Member member, String title, String content) { public void sendChatNotification(Member member, String title, String content, Long chatRoomId, ChatRoomType chatRoomType) { + if (applyFakeLatencyAndSkip(member.getId())) { + return; + } + String fcmToken = member.getFcmToken(); if (fcmToken == null || fcmToken.isBlank()) { log.info("FCM 토큰 없음 - memberId: {}, 채팅 알림 전송 생략", member.getId()); @@ -86,6 +102,25 @@ public void sendChatNotification(Member member, String title, String content, } } + /** + * 부하테스트용 FCM 지연 주입. + * {@code fcm.fake-latency-ms > 0} 이면 해당 시간만큼 스레드를 점유한 뒤 실제 Firebase 전송을 스킵하고 true를 반환한다. + * 토큰 유무와 무관하게 스레드를 점유해야 벌크헤드 효과가 측정되므로 토큰 가드보다 먼저 호출한다. + * 기본값 0 → 운영에서는 항상 false(동작 변화 없음). + */ + private boolean applyFakeLatencyAndSkip(Long memberId) { + if (fakeLatencyMs <= 0) { + return false; + } + try { + Thread.sleep(fakeLatencyMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + log.info("[FCM][FAKE] 지연주입 {}ms 후 실전송 스킵 - memberId: {}", fakeLatencyMs, memberId); + return true; + } + /** * 채팅 알림 클릭 시 이동할 경로(상대경로)를 생성한다. * webpush.fcm_options.link 로 전달되어 FCM이 클릭 시 네이티브로 이동시킨다. diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 258ef906..dee4c970 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -85,6 +85,10 @@ jwt: access-token-validity: 900000 refresh-token-validity: 1209600000 +fcm: + # 부하테스트용 FCM 인위적 지연(ms). 0=비활성(운영 기본). staging에서 env FCM_FAKE_LATENCY_MS 로만 켠다. + fake-latency-ms: 0 + logging: level: org.hibernate.SQL: WARN From 2e746a0dab8389024788f2594075d0dd0f1442ed Mon Sep 17 00:00:00 2001 From: kanghana1 Date: Sun, 5 Jul 2026 13:50:25 +0900 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20fcm=EC=A7=80=EC=97=B0=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cockple/demo/domain/notification/fcm/FcmService.java | 7 ------- src/main/resources/application-staging.yml | 4 ++++ src/main/resources/application.yml | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java b/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java index 4b73a7ce..30e0ab31 100644 --- a/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java +++ b/src/main/java/umc/cockple/demo/domain/notification/fcm/FcmService.java @@ -25,10 +25,6 @@ public class FcmService { private final MemberRepository memberRepository; private final FirebaseMessaging firebaseMessaging; - /** - * 부하테스트용 FCM 인위적 지연(ms). 스레드풀 벌크헤드 효과 측정 전용. - * 기본 0 → 평상시/운영에서는 완전히 비활성(동작 변화 없음). staging에서 env(FCM_FAKE_LATENCY_MS)로만 켠다. - */ @Value("${fcm.fake-latency-ms:0}") private long fakeLatencyMs; @@ -104,9 +100,6 @@ public void sendChatNotification(Member member, String title, String content, /** * 부하테스트용 FCM 지연 주입. - * {@code fcm.fake-latency-ms > 0} 이면 해당 시간만큼 스레드를 점유한 뒤 실제 Firebase 전송을 스킵하고 true를 반환한다. - * 토큰 유무와 무관하게 스레드를 점유해야 벌크헤드 효과가 측정되므로 토큰 가드보다 먼저 호출한다. - * 기본값 0 → 운영에서는 항상 false(동작 변화 없음). */ private boolean applyFakeLatencyAndSkip(Long memberId) { if (fakeLatencyMs <= 0) { diff --git a/src/main/resources/application-staging.yml b/src/main/resources/application-staging.yml index c6e986d8..cb48f814 100644 --- a/src/main/resources/application-staging.yml +++ b/src/main/resources/application-staging.yml @@ -13,3 +13,7 @@ spring: firebase: service-account-key: ${FIREBASE_SERVICE_ACCOUNT_KEY} + +# [부하테스트용] FCM 인위적 지연 주입 +fcm: + fake-latency-ms: 1000 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index dee4c970..903b6e69 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -86,7 +86,6 @@ jwt: refresh-token-validity: 1209600000 fcm: - # 부하테스트용 FCM 인위적 지연(ms). 0=비활성(운영 기본). staging에서 env FCM_FAKE_LATENCY_MS 로만 켠다. fake-latency-ms: 0 logging: From 90ca1a9feb1851c935956ff7d92b8e285d448970 Mon Sep 17 00:00:00 2001 From: kanghana1 Date: Sun, 5 Jul 2026 14:01:14 +0900 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20FCM=20=EC=A7=80=EC=97=B0=EC=A3=BC?= =?UTF-8?q?=EC=9E=85=20=EA=B0=92=EC=9D=84=20env(GitHub=20Variable)?= =?UTF-8?q?=EB=A1=9C=20=ED=86=A0=EA=B8=80=20=EA=B0=80=EB=8A=A5=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EB=B0=B0=EA=B4=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 4 +++- docker-compose.yml | 2 ++ scripts/deploy.sh | 1 + src/main/resources/application-staging.yml | 4 ---- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ebc73673..9589c8c0 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -72,7 +72,7 @@ jobs: envs: >- DB_PASSWORD,GCS_BUCKET,GCS_BACKUP_BUCKET, KAKAO_CLIENT_ID,KAKAO_CLIENT_SECRET,KAKAO_REDIRECT_URI_PROD,KAKAO_REDIRECT_URI_STAGING,KAKAO_ADMIN_KEY, - JWT_SECRET_KEY,FIREBASE_SERVICE_ACCOUNT_KEY + JWT_SECRET_KEY,FIREBASE_SERVICE_ACCOUNT_KEY,FCM_FAKE_LATENCY_MS script: | chmod +x /home/ubuntu/cockple/scripts/deploy.sh bash /home/ubuntu/cockple/scripts/deploy.sh \ @@ -89,3 +89,5 @@ jobs: KAKAO_ADMIN_KEY: ${{ secrets.KAKAO_ADMIN_KEY }} JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }} FIREBASE_SERVICE_ACCOUNT_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY }} + # [부하테스트용] FCM 지연(ms) 토글. GitHub Variable로 관리(미설정 시 빈값→deploy.sh에서 0). PR 없이 값 변경+deploy 재실행으로 on/off. + FCM_FAKE_LATENCY_MS: ${{ vars.FCM_FAKE_LATENCY_MS }} diff --git a/docker-compose.yml b/docker-compose.yml index 2a883bb6..18bb6ed4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,6 +79,8 @@ services: environment: JAVA_TOOL_OPTIONS: "-Xms128m -Xmx512m" SPRING_PROFILES_ACTIVE: staging + # [부하테스트용] FCM 인위적 지연(ms). 미설정 시 0=비활성. staging 전용. + FCM_FAKE_LATENCY_MS: ${FCM_FAKE_LATENCY_MS:-0} DB_PASSWORD: ${DB_PASSWORD} GCS_BUCKET: ${GCS_BUCKET} KAKAO_CLIENT_ID: ${KAKAO_CLIENT_ID} diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 6e9a5fa7..8502513b 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -26,6 +26,7 @@ KAKAO_REDIRECT_URI_STAGING=${KAKAO_REDIRECT_URI_STAGING} KAKAO_ADMIN_KEY=${KAKAO_ADMIN_KEY} JWT_SECRET_KEY=${JWT_SECRET_KEY} FIREBASE_SERVICE_ACCOUNT_KEY=${FIREBASE_SERVICE_ACCOUNT_KEY} +FCM_FAKE_LATENCY_MS=${FCM_FAKE_LATENCY_MS:-0} EOF echo "${FIREBASE_SERVICE_ACCOUNT_KEY}" > /home/ubuntu/cockple/firebase-service-account.json diff --git a/src/main/resources/application-staging.yml b/src/main/resources/application-staging.yml index cb48f814..c6e986d8 100644 --- a/src/main/resources/application-staging.yml +++ b/src/main/resources/application-staging.yml @@ -13,7 +13,3 @@ spring: firebase: service-account-key: ${FIREBASE_SERVICE_ACCOUNT_KEY} - -# [부하테스트용] FCM 인위적 지연 주입 -fcm: - fake-latency-ms: 1000