Firebase는 Google이 제공하는 모바일 및 웹 애플리케이션 개발 플랫폼으로, 다음과 같은 다양한 기능을 제공합니다:
- 실시간 데이터베이스: 클라우드에서 실시간으로 데이터를 저장하고 동기화할 수 있는 NoSQL 데이터베이스입니다.
- 인증: 사용자 인증을 간편하게 처리할 수 있는 다양한 인증 방법을 지원합니다.
- 호스팅: 정적 웹 사이트 및 앱을 배포하고 호스팅할 수 있는 기능을 제공합니다.
- Analytics: 사용자 행동 분석 및 앱 성과를 측정할 수 있는 도구입니다.
- Storage: 파일을 안전하게 저장하고 관리할 수 있는 클라우드 스토리지 서비스입니다.
FCM (Firebase Cloud Messaging)은 Firebase의 일부로, 다음과 같은 기능을 제공합니다:
- 푸시 알림: 앱 사용자에게 실시간으로 푸시 알림을 전송할 수 있는 서비스입니다.
- 메시지 전송: 앱 내 메시지를 전송하고 수신할 수 있는 기능을 제공합니다.
- 안정성: Google의 인프라를 통해 안정적이고 신뢰성 높은 메시지 전송을 지원합니다.
[FCM의 동작 방식]
+ Firebase Cloud Messaging(FCM)을 사용하는 경우, 액세스 토큰 발급에 대한 과정을 별도로 처리할 필요는 없습니다. Firebase Admin SDK는 자동으로 Google Cloud Platform(GCP)의 인증 및 권한 관리를 처리합니다.
즉, FCM에서 서버가 클라이언트에게 메시지를 보내기 위해 Firebase Admin SDK를 사용할 때, Google 인증 파일(.json 파일)을 이용해 GCP와 통신을 자동으로 처리하며, 액세스 토큰 발급 및 갱신도 내부적으로 관리합니다. 따라서 명시적으로 액세스 토큰을 발급받는 로직을 작성하지 않아도 됩니다.
Firebase에 프로젝트 등록
스프링부트 Firebase 의존성 추가
build.gradle
// Firebase
implementation 'com.google.firebase:firebase-admin:9.3.0'
Firebase → 프로젝트 설정 → 서비스 계정 → Firebase Admin SDK → 새 비공개 키 생성
발급받은 key resources파일 아래에 등록
※ .gitignore에도 추가하여 git에 업로드되지 않도록 주의
FCMConfig 설정 추가
: Firebase Cloud Messaging을 사용하기 위한 Spring Boot 설정 클래스를 정의
@Configuration
public class FCMConfig {
@Bean
FirebaseMessaging firebaseMessaging() throws IOException {
ClassPathResource resource = new ClassPathResource("firebase/firebase_service_key.json");
InputStream serviceAccount = resource.getInputStream();
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();
FirebaseApp firebaseApp;
if (FirebaseApp.getApps().isEmpty()) {
firebaseApp = FirebaseApp.initializeApp(options);
} else {
firebaseApp = FirebaseApp.getInstance();
}
return FirebaseMessaging.getInstance(firebaseApp);
}
}
FCM을 통해 알림을 전송하기 위해서느 해당 타겟 유저 기기를 식별할 수 있는 토큰이 필요하다.
FCMToken
: member_id와 fcm_id로 고유 키 제약을 걸어줌
@NoArgsConstructor
@Getter
@Entity
@Table(name = "FCMToken",
uniqueConstraints = {
@UniqueConstraint(columnNames = {"member_id", "fcm_id"})
}
)
public class FCMToken {
@Id
@Column(name = "fcm_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
private String token;
private LocalDate createdAt;
public void setToken(String token) {
this.token = token;
}
@Builder
public FCMToken(Member member, String token, LocalDate createdAt) {
this.member = member;
this.token = token;
this.createdAt = createdAt;
}
}
DTO - MessagePushServiceRequest
record?
Java에서 record는 불변(immutable) 데이터 클래스를 간편하게 생성할 수 있도록 도입된 새로운 기능입니다. record는 Java 14에서 미리보기로 소개되었고, Java 16에서 정식으로 추가되었습니다.
- 간결함: record를 사용하면 필드, 생성자, 접근자(getter) 메소드, equals(), hashCode(), toString() 메소드 등을 자동으로 생성해 줍니다. 이로 인해 일반적인 데이터 클래스를 작성할 때 필요한 보일러플레이트 코드가 줄어듭니다.
- 불변성: record로 생성된 객체는 기본적으로 불변입니다. 즉, 객체를 생성한 후에는 상태를 변경할 수 없습니다. 이는 데이터의 일관성을 유지하는 데 도움이 됩니다.
- 데이터 중심 프로그래밍: record는 데이터를 중심으로 한 프로그래밍 스타일을 장려합니다. 데이터 클래스는 주로 데이터를 표현하는 역할을 하며, 이를 통해 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
- 패턴 매칭의 가능성: Java에서 record는 향후 패턴 매칭과 같은 고급 기능과 함께 사용할 수 있도록 설계되었습니다. 이는 코드를 더 간결하고 읽기 쉽게 만들어줍니다.
@Builder(access = PRIVATE)
public record MessagePushServiceRequest(
String targetToken,
String title,
String body
) {
public static MessagePushServiceRequest of(String token, String title, String body) {
return MessagePushServiceRequest.builder()
.targetToken(token)
.title(title)
.body(body)
.build();
}
}
Controller - FCM 전송 요청
@PostMapping("/send")
public ResponseEntity<String> sendNotification(@RequestBody MessagePushServiceRequest request) {
try {
// FCM 메시지 전송 요청
String response = fcmService.sendNotification(request);
return ResponseEntity.ok("Message sent successfully: " + response);
} catch (Exception e) {
return ResponseEntity.status(500).body("Message failed: " + e.getMessage());
}
}
Service - FCM 전송 요청
public String sendNotification(MessagePushServiceRequest request) {
try {
Message message = Message.builder()
.setToken(request.targetToken())
.setNotification(Notification.builder()
.setTitle(request.title())
.setBody(request.body())
.build())
.build();
// 메시지 전송
return firebaseMessaging.send(message);
} catch (Exception e) {
throw new RuntimeException("FCM 알림 전송에 실패했습니다.", e);
}
}
테스트
완료!
'개발' 카테고리의 다른 글
AWS 단일 서버 설정 (Docker) - 2편 (0) | 2024.10.07 |
---|---|
AWS 단일 서버 설정 (Load Balancer, SSL) - 1편 (0) | 2024.10.04 |
[스프링부트] 마케팅 수신 동의 멤버 조회, @Cache- (0) | 2024.10.02 |
[스프링부트] 필수 약관 - Native Query (0) | 2024.09.25 |
[스프링부트] JPA Specification 이용한 멤버 조회 구현 (0) | 2024.09.13 |