이번에 주요 기능이 알림이기 때문에 push알림을 위하여 FCM을 통해 프론트와 연결해야했다.
동작과정을 설명하자면
1. 프론트에서 백엔드한테 해당 디바이스의 토큰을 전달해준다.
2. 백엔드는 그 토큰을 가지고 DB에 저장해뒀다가 알림을 보내줘야할 때 그 토큰을 가지고 알림을 전송한다.
1. firebase console에 들어가서 프로젝트 추가하기
firebase console에서 프로젝트를 추가한 뒤 설정 - 서비스 계정에 들어가서 새 비공기 키를 생성해준다. 나는 Spring boot를 사용했기 때문에 자바로 생성해주었다.

2. dependency 추가하기
spring boot 프로젝트의 build.gradle에 아래와 같이 추가해준다.
implementation 'com.google.firebase:firebase-admin:9.2.0'
3. json 파일 추가하기
1번에서 받은 키를 application.yml이 들어있는 resource폴더 내부에 저장해준다. 나는 firebase 폴더를 만들어서 그 안에 넣어줬다.

그리고 application.yml에 아래와 같이 추가해준다. 들여쓰기 없이 그냥 넣어주면 된다.
fcm:
firebase:
config:
path: "firebase/{파일명}"
4. fcm 초기화 빈 생성하기
Spring Boot 서버가 시작될 때 Firebase SDK를 초기화해서 서버에서 FirebaseMessaging.getInstance().send() 같은 푸시 알림 기능을 쓸 수 있도록 하는 설정 클래스를 작성해준다.
@Slf4j
@Component
public class FcmInitializer {
@Value("${fcm.firebase.config.path}")
private String firebaseConfigPath;
@PostConstruct
public void initialize() {
try {
ClassPathResource resource = new ClassPathResource(firebaseConfigPath);
try (InputStream stream = resource.getInputStream()) {
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.fromStream(stream))
.build();
if (FirebaseApp.getApps().isEmpty()) {
FirebaseApp.initializeApp(options);
log.info("Firebase app has been initialized successfully.");
}
}
} catch (IOException e) {
log.error("Error initializing Firebase app", e);
}
}
}
5. 알림 보내기
기본틀은 이와 같다. token은 프론트에서 전달해준 fcm 토큰이다.
@Service
public class NotificationService {
public void sendPush(String token, String title, String body) {
Message message = Message.builder()
.setToken(token)
.setNotification(
Notification.builder()
.setTitle(title)
.setBody(body)
.build()
)
.build();
try {
String response = FirebaseMessaging.getInstance().send(message);
System.out.println("✅ FCM 전송 성공: " + response);
} catch (FirebaseMessagingException e) {
System.err.println("❌ FCM 전송 실패: " + e.getMessage());
}
}
}
다음은 내 프로젝트에서 이를 어떻게 사용하고 있는 지에 대해 작성하겠다.
'[AND] 사용자 정의 지표 기반 실시감 감지 및 자동매매 시스템 > 기술' 카테고리의 다른 글
| [RabbitMQ] rabbitMQ 메시지가 왔다가 안왔다가 왔다가 안왔다가... ♾️ (0) | 2025.10.28 |
|---|---|
| [Redis] private subnet에 있는 redis를 redis insight를 확인하고 싶을 때 (6) | 2025.10.25 |
| [Lazy로딩] Postman에서 INTERNAL_SERVER_ERROR만 보이고, 콘솔에는 아무 에러 로그도 안 찍힐 때 (1) | 2025.10.17 |
| [JavaBean] boolean 값이 계속해서 false가 되는 이유 (0) | 2025.10.17 |
| [JWT] Spring Boot security 와 JWT로 인증/인가 구현하기(2) - 설정 파일, 예외 처리 (0) | 2025.10.06 |