Notification Server
- mobile 기기에 Push 알림을 전송하는 서버
- FCM(Firebase Cloud Messaging) 사용 예정
Client App
- 사용자의 mobile기기에 설치된 app
- Push 알림을 받는 역할
Provider
- Client App을 위한 서버
- 필요시 Notification Server에 요청을 전송하여, Client App에 알림을 보냄
- 나의 push server
특정 topic을 구독한 여러 기기에 메시지를 보내는 방법
- 예시) 날씨와 같이 공개적으로 제공되는 정보
클라이언트인 앱에서 기존 topic을 구독하거나 새 topic을 만들 수 있음
- Firebase 프로젝트에 토픽 구독
Firebase Admin SDK
를 사용하면 서버 측에서 기본적인 topic 관리 작업을 수행할 수 있음
등록 토큰을 알고 있으면 서버 로직을 사용하여 클라이언트 앱 인스턴스를 일괄 구독하거나 구독 취소할 수 있음
속도보다 처리량을 위주로 최적화되어 있는 기능
빠르고 안전하게 전송하고 싶다면 다른 방법을 사용하라고 권고됨
단일 요청으로 기기를 최대 1,000대까지 구독하거나 구독 취소할 수 있음
그룹에 속한 기기에만 알림을 보내는 방법입니다.
기기 그룹 메시징은 앱 내에서 관리하는 것이 아니라 서버에서 기기 그룹을 관리함
예를 들어, 기기 모델에 따라서 다른 메시지를 보내려면 서버에서 알맞은 그룹에 등록/삭제하여 각 그룹에 적절한 메시지를 보냄
하지만 알림키 하나 그룹에 최대 20명까지만 속할 수 있음
즉 기기의 Token or Topic 관리를 해야 함
클라이언트 -> Token or Topic 값을 계속 등록 및 갱신해 줘야 함
서버 -> 해당 사용자의 Token or Topic을 저장해야 함
public class FCMService {
private String getAccessToken() throws IOException {
String firebaseConfigPath = "firebase/cocotalk_firebase_service_key.json";
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource(firebaseConfigPath).getInputStream())
.createScoped(List.of("https://www.googleapis.com/auth/cloud-platform"));
googleCredentials.refreshIfExpired();
return googleCredentials.getAccessToken().getTokenValue();
}
}
@Builder
@AllArgsConstructor
@Getter
public class FCMMessage {
private boolean validate_only;
private Message message;
@Builder
@AllArgsConstructor
@Getter
public static class Message {
private Notification notification; // 모든 mobile os를 아우를수 있는 Notification
private String token; // 특정 device에 알림을 보내기위해 사용
}
@Builder
@AllArgsConstructor
@Getter
public static class Notification {
private String title;
private String body;
private String image;
}
}
@Service
@RequiredArgsConstructor
@Slf4j
public class FCMService {
private String API_URL = "https://fcm.googleapis.com/v1/projects/프로젝트id/messages:send";
private final ObjectMapper objectMapper;
public void sendMessageTo(String targetToken, String title, String body) throws IOException {
String message = makeMessage(targetToken, title, body);
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(message, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url(API_URL)
.post(requestBody)
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken())
.addHeader(HttpHeaders.CONTENT_TYPE, "application/json; UTF-8")
.build();
Response response = client.newCall(request).execute();
log.info(response.body().string());
}
// 파라미터를 FCM이 요구하는 body 형태로 만들어준다.
private String makeMessage(String targetToken, String title, String body) throws JsonProcessingException {
FCMMessage fcmMessage = FCMMessage.builder()
.message(FCMMessage.Message.builder()
.token(targetToken)
.notification(FCMMessage.Notification.builder()
.title(title)
.body(body)
.image(null)
.build()
)
.build()
)
.validate_only(false)
.build();
return objectMapper.writeValueAsString(fcmMessage);
}
private String getAccessToken() throws IOException {...}
}
- 앱을 Firebase와 동기화했다면 기기들은 각각의 고유한 Instance ID(Instance ID가 FCM Token을 발행)
- Firebase 서버는 FCM Token을 통해 각각의 기기에 Push Notification을 보낼 수 있다.
FCM TOKEN이 갱신되는 시점
앱이 인스턴스 ID를 삭제
앱이 새 기기에서 복원
사용자가 앱을 제거 및 재설치
사용자가 앱 데이터를 지움
TOKEN 생성 모니터링
onTokenRefreshcallback은 새 토큰이 생성 될 때마다 발생하므로 컨텍스트에서 getToken을 호출하면 현재 사용 가능한 토큰이 등록되어있는지 확인할 수 있다.
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
[Cleint] Backend Server에 자신이 특정 채팅방에 입장하겠다는 요청을 보냅니다.
[Server]
1. [채팅 서버] 해당되는 채팅방 그룹에, 해당 사용자의 id를 등록해둡니다.
2. [푸시 서버] Device Table에서 해당 Client의 FCM Device Token을 가져옵니다.
3. [푸시 서버] 이 token을 특정 Messaging Group(동창모임)에 추가해달라는 요청을 FCM에 보냅니다.
룸 id -> token list 찾기 -> 디바이스 그룹
서버에서 토큰을 갱신하는 시점
본문 외 기타 참고
FCM TOKEN 설명
FCM을 도입할 때 고려할 것들
push notification
FCM 푸시 알림 대상