🔔 모바일 푸시 알림 사용 가이드


1. 의존성 주입

import com.akc.b2c.common.push.service.IPushNotificationService; import com.akc.b2c.common.push.dto.PushNotificationResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Slf4j @Service @RequiredArgsConstructor public class YourService { private final IPushNotificationService pushNotificationService; }

2. 푸시 전송

// 회원 ID만 알면 끝! PushNotificationResponse response = pushNotificationService.sendByMemberId( 222L, // 회원 ID "주문 확정", "주문번호 #12345가 확정되었습니다", null );

3. 결과 확인

if (response.isSuccess()) { log.info("전송 성공: {}", response.getMessageId()); }

📚 구현된 8가지 API (전체 완료!)

API 사용 시점 커버리지
#1 Token 단일 특정 디바이스 지정 전송 3%
#2 Token 다수 여러 디바이스 동시 전송 2%
#3 Token + 템플릿 템플릿 기반 단일 전송 3%
#4 Token 다수 + 템플릿 템플릿 멀티캐스트 2%
#5 회원 ID 단일 개인화 알림 (가장 많이 사용) 50%
#6 회원 ID 다수 대량 발송 (공지, 이벤트) 20%
#7 회원 ID 단일 + 템플릿 템플릿 개인화 알림 15%
#8 회원 ID 다수 + 템플릿 템플릿 대량 발송 5%

1️⃣ Token 단일 전송

Java 코드

PushNotificationRequest request = PushNotificationRequest.builder() .deviceToken("dpanRX1ZSkw...FCM_토큰") .title("주문 확정") .body("주문번호 #12345가 확정되었습니다") .data(Map.of( "orderId", "12345", "deepLink", "amano://order/12345" )) .build(); PushNotificationResponse response = pushNotificationService.send(request);

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send?memberId=222 Content-Type: application/json { "deviceToken": "dpanRX1ZSkw...FCM_토큰", "title": "주문 확정", "body": "주문번호 #12345가 확정되었습니다", "data": { "orderId": "12345", "deepLink": "amano://order/12345" } }

2️⃣ Token 다수 전송 (멀티캐스트)

Java 코드

PushNotificationRequest request = PushNotificationRequest.builder() .deviceTokens(List.of("token1", "token2", "token3")) .title("시스템 점검 안내") .body("오늘 밤 11시부터 점검이 진행됩니다") .build(); PushNotificationResponse response = pushNotificationService.send(request); log.info("성공: {}, 실패: {}", response.getSuccessCount(), response.getFailureCount());

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-multicast?memberId=222 Content-Type: application/json { "deviceTokens": ["token1", "token2", "token3"], "title": "시스템 점검 안내", "body": "오늘 밤 11시부터 점검이 진행됩니다" }

3️⃣ Token + 템플릿 전송

특징:

Java 코드

Map<String, String> params = Map.of( "orderNo", "20260117-001", "orderDate", "2026-01-17", "amount", "50,000" ); PushNotificationResponse response = pushNotificationService.sendByTemplate( "dpanRX1ZSkw...FCM_토큰", "PUSH0001", // 템플릿 ID params );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-by-template?memberId=222 Content-Type: application/json { "deviceToken": "dpanRX1ZSkw...FCM_토큰", "templateId": "PUSH0001", "params": { "orderNo": "20260117-001", "orderDate": "2026-01-17", "amount": "50,000" } }

템플릿 예시 (실제 데이타 아님)

템플릿 ID 제목 내용 파라미터
PUSH0001 주문 확정 주문번호 ${orderNo}가 확정되었습니다 orderNo, amount
PUSH0002 이벤트 알림 ${eventName} - ${discount} 할인! eventName, discount
PUSH0003 결제 완료 ${amount}원 결제가 완료되었습니다 amount, method

🔥 변수 치환 상세 예시

**템플릿 (PUSH0001) DB 저장 내용 **:

{ "templateId": "PUSH0001", "title": "주문 확정", "body": "주문번호 ${orderNo}가 확정되었습니다. 금액: ${amount}원", "dataKeys": { "orderId": "${orderNo}", "deepLink": "amano://order/${orderNo}", "amount": "${amount}" } }

전송 코드:

Map<String, String> params = Map.of( "orderNo", "20260117-001", "amount", "50,000" ); pushNotificationService.sendByTemplate(token, "PUSH0001", params);

실제 전송되는 메시지:

{ "title": "주문 확정", "body": "주문번호 20260117-001가 확정되었습니다. 금액: 50,000원", "data": { "orderId": "20260117-001", "deepLink": "amano://order/20260117-001", "amount": "50,000" } }

💡 중요: title, body뿐만 아니라 data 필드의 값들도 모두 변수 치환됩니다!


4️⃣ Token 다수 + 템플릿 전송

언제? 특정 디바이스 그룹에 템플릿 메시지 전송

Java 코드

List<String> deviceTokens = List.of("token1", "token2", "token3"); Map<String, String> params = Map.of( "eventName", "VIP 전용 이벤트", "discount", "30%" ); PushNotificationResponse response = pushNotificationService.sendMulticastByTemplate( deviceTokens, "PUSH0002", // 템플릿 ID params );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-multicast-by-template?memberId=222 Content-Type: application/json { "deviceTokens": ["token1", "token2", "token3"], "templateId": "PUSH0002", "params": { "eventName": "VIP 전용 이벤트", "discount": "30%" } }

5️⃣ 회원 ID 단일 전송 ⭐ (가장 많이 사용)

언제? 주문, 결제, 쿠폰 지급 등 개인화 알림

장점:

Java 코드

Map<String, String> data = Map.of( "couponId", "CP001", "deepLink", "amano://coupon/CP001" ); PushNotificationResponse response = pushNotificationService.sendByMemberId( 222L, // 회원 ID "🎁 쿠폰 지급 완료", "5,000원 할인 쿠폰이 지급되었습니다", data );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-to-all-devices?memberId=222 Content-Type: application/json { "title": "🎁 쿠폰 지급 완료", "body": "5,000원 할인 쿠폰이 지급되었습니다", "data": { "couponId": "CP001", "deepLink": "amano://coupon/CP001" } }

실전 예시

// 주문 확정 시 orderService.confirmOrder(orderId); pushNotificationService.sendByMemberId( order.getMemberId(), "주문 확정", "주문번호 #" + orderId + "가 확정되었습니다", Map.of("orderId", orderId.toString()) ); // 결제 완료 시 paymentService.completePayment(paymentId); pushNotificationService.sendByMemberId( payment.getMemberId(), "결제 완료", payment.getAmount() + "원 결제가 완료되었습니다", Map.of("paymentId", paymentId.toString()) );

6️⃣ 회원 ID 다수 전송 ⭐ (대량 발송)

언제? 공지사항, 이벤트, VIP 혜택 등 여러 회원에게 일괄 전송

Java 코드

List<Long> vipMembers = memberRepository.findVipMemberIds(); PushNotificationResponse response = pushNotificationService.sendByMemberIds( vipMembers, "💎 VIP 전용 혜택", "VIP 회원님께 특별 할인 쿠폰을 드립니다", Map.of("vipLevel", "GOLD") );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-to-multiple-users Content-Type: application/json { "memberIds": [100, 200, 300], "title": "시스템 점검 안내", "body": "금일 23:00 ~ 01:00 시스템 점검이 진행됩니다" }

실전 예시

// 이벤트 당첨자 발표 List<Long> winners = eventService.getWinners(eventId); pushNotificationService.sendByMemberIds( winners, "🎉 축하합니다! 당첨되셨습니다", "신년 이벤트 추첨 결과 당첨되셨습니다", Map.of("eventId", eventId.toString()) ); // 쿠폰 만료 알림 (만료 7일 전) List<Long> expiringMembers = couponService.getMembersWithExpiringCoupons(); pushNotificationService.sendByMemberIds( expiringMembers, "⏰ 쿠폰 만료 임박", "7일 후 쿠폰이 만료됩니다. 지금 사용하세요!", null );

7️⃣ 회원 ID 단일 + 템플릿 전송 ⭐

언제? 템플릿을 사용한 개인화 알림 (주문, 결제 등)

Java 코드

Map<String, String> params = Map.of( "orderNo", "20260117-001", "amount", "50,000" ); PushNotificationResponse response = pushNotificationService.sendByMemberIdWithTemplate( 222L, // 회원 ID "PUSH0001", // 템플릿 ID params );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-by-member-template?memberId=222 Content-Type: application/json { "templateId": "PUSH0001", "params": { "orderNo": "20260117-001", "amount": "50,000" } }

실전 예시

// 주문 확정 (템플릿 사용) Map<String, String> params = Map.of( "orderNo", order.getOrderNo(), "orderDate", order.getCreatedAt().format(DateTimeFormatter.ISO_DATE), "amount", String.valueOf(order.getTotalAmount()) ); pushNotificationService.sendByMemberIdWithTemplate( order.getMemberId(), "PUSH0001", // 주문 확정 템플릿 params );

8️⃣ 회원 ID 다수 + 템플릿 전송 ⭐

언제? 템플릿을 사용한 대량 발송 (이벤트, VIP 혜택 등)

Java 코드

List<Long> vipMembers = memberRepository.findVipMemberIds(); Map<String, String> params = Map.of( "eventName", "VIP 전용 이벤트", "discount", "30%", "endDate", "2026-01-31" ); PushNotificationResponse response = pushNotificationService.sendByMemberIdsWithTemplate( vipMembers, "PUSH0002", // 이벤트 템플릿 params );

REST API (test 용도로 사용할수 있음)

POST /api/notifications/push/send-to-multiple-users-by-template Content-Type: application/json { "memberIds": [100, 200, 300], "templateId": "PUSH0002", "params": { "eventName": "VIP 전용 이벤트", "discount": "30%", "endDate": "2026-01-31" } }

실전 예시

// 쿠폰 만료 알림 (템플릿 사용) List<Long> expiringMembers = couponService.getMembersWithExpiringCoupons(); Map<String, String> params = Map.of( "days", "7", "couponName", "신규가입 쿠폰" ); pushNotificationService.sendByMemberIdsWithTemplate( expiringMembers, "PUSH0004", // 쿠폰 만료 템플릿 params );