Firebase Admin SDK 또는 FCM 앱 서버 프로토콜을 사용하여 메시지 요청을 작성하고 다음과 같은 타겟 유형으로 전송할 수 있습니다.
- 주제 이름
- 조건
- 기기 등록 토큰
- 기기 그룹 이름(프로토콜만 해당)
사전 정의된 필드로 구성된 알림 페이로드 또는 사용자가 직접 정의한 필드로 구성된 데이터 페이로드와 함께 메시지를 보내거나 2가지 유형의 페이로드를 모두 포함하는 메시지를 보낼 수 있습니다. 자세한 내용은 메시지 유형을 참조하세요.
이 페이지의 예시에서는 Firebase Admin SDK ( Node, Java, Python, C#, Go 지원) 및 v1 HTTP 프로토콜을 사용하여 알림 메시지를 보내는 방법을 보여줍니다. 지원 중단된 기존 HTTP 및 XMPP 프로토콜을 통해 메시지를 보내는 방법도 알아보세요.
특정 기기에 메시지 전송
특정 기기 1개에 메시지를 보내려면 아래와 같이 기기의 등록 토큰을 전달합니다. 등록 토큰에 대한 자세한 내용은 플랫폼별 클라이언트 설정 정보를 참조하세요.
Node.js
// This registration token comes from the client FCM SDKs.
const registrationToken = 'YOUR_REGISTRATION_TOKEN';
const message = {
data: {
score: '850',
time: '2:45'
},
token: registrationToken
};
// Send a message to the device corresponding to the provided
// registration token.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
자바
// This registration token comes from the client FCM SDKs.
String registrationToken = "YOUR_REGISTRATION_TOKEN";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setToken(registrationToken)
.build();
// Send a message to the device corresponding to the provided
// registration token.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# This registration token comes from the client FCM SDKs.
registration_token = 'YOUR_REGISTRATION_TOKEN'
# See documentation on defining a message payload.
message = messaging.Message(
data={
'score': '850',
'time': '2:45',
},
token=registration_token,
)
# Send a message to the device corresponding to the provided
# registration token.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Go
// Obtain a messaging.Client from the App.
ctx := context.Background()
client, err := app.Messaging(ctx)
if err != nil {
log.Fatalf("error getting Messaging client: %v\n", err)
}
// This registration token comes from the client FCM SDKs.
registrationToken := "YOUR_REGISTRATION_TOKEN"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Token: registrationToken,
}
// Send a message to the device corresponding to the provided
// registration token.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
C#
// This registration token comes from the client FCM SDKs.
var registrationToken = "YOUR_REGISTRATION_TOKEN";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
Token = registrationToken,
};
// Send a message to the device corresponding to the provided
// registration token.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"body":"This is an FCM notification message!",
"title":"FCM Message"
}
}
}
cURL 명령어:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
"notification":{
"title":"FCM Message",
"body":"This is an FCM Message"
},
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
성공하면 각 전송 메서드가 메시지 ID를 반환합니다. Firebase Admin SDK가 projects/{project_id}/messages/{message_id}
형식으로 ID 문자열을 반환합니다.
HTTP 프로토콜 응답은 단일 JSON 키입니다.
{
"name":"projects/myproject-b5ae1/messages/0:1500415314455276%31bd1c9631bd1c96"
}
여러 기기에 메시지 전송
Admin FCM API를 사용하면 기기 등록 토큰 목록에 메시지를 멀티캐스트할 수 있습니다. 호출당 최대 500개의 기기 등록 토큰을 지정할 수 있습니다.
Node.js
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// …
'YOUR_REGISTRATION_TOKEN_N',
];
const message = {
data: {score: '850', time: '2:45'},
tokens: registrationTokens,
};
getMessaging().sendMulticast(message)
.then((response) => {
console.log(response.successCount + ' messages were sent successfully');
});
자바
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
MulticastMessage message = MulticastMessage.builder()
.putData("score", "850")
.putData("time", "2:45")
.addAllTokens(registrationTokens)
.build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");
Python
# Create a list containing up to 500 registration tokens.
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
'YOUR_REGISTRATION_TOKEN_1',
# ...
'YOUR_REGISTRATION_TOKEN_N',
]
message = messaging.MulticastMessage(
data={'score': '850', 'time': '2:45'},
tokens=registration_tokens,
)
response = messaging.send_multicast(message)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))
Go
// Create a list containing up to 500 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Tokens: registrationTokens,
}
br, err := client.SendMulticast(context.Background(), message)
if err != nil {
log.Fatalln(err)
}
// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)
C#
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
Tokens = registrationTokens,
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
};
var response = await FirebaseMessaging.DefaultInstance.SendEachForMulticastAsync(message);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");
반환 값은 입력 토큰 순서와 일치하는 토큰 목록입니다. 오류가 발생한 토큰을 확인하려는 경우에 유용합니다.
Node.js
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// …
'YOUR_REGISTRATION_TOKEN_N',
];
const message = {
data: {score: '850', time: '2:45'},
tokens: registrationTokens,
};
getMessaging().sendMulticast(message)
.then((response) => {
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(registrationTokens[idx]);
}
});
console.log('List of tokens that caused failures: ' + failedTokens);
}
});
자바
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
MulticastMessage message = MulticastMessage.builder()
.putData("score", "850")
.putData("time", "2:45")
.addAllTokens(registrationTokens)
.build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
if (response.getFailureCount() > 0) {
List<SendResponse> responses = response.getResponses();
List<String> failedTokens = new ArrayList<>();
for (int i = 0; i < responses.size(); i++) {
if (!responses.get(i).isSuccessful()) {
// The order of responses corresponds to the order of the registration tokens.
failedTokens.add(registrationTokens.get(i));
}
}
System.out.println("List of tokens that caused failures: " + failedTokens);
}
Python
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
'YOUR_REGISTRATION_TOKEN_1',
# ...
'YOUR_REGISTRATION_TOKEN_N',
]
message = messaging.MulticastMessage(
data={'score': '850', 'time': '2:45'},
tokens=registration_tokens,
)
response = messaging.send_multicast(message)
if response.failure_count > 0:
responses = response.responses
failed_tokens = []
for idx, resp in enumerate(responses):
if not resp.success:
# The order of responses corresponds to the order of the registration tokens.
failed_tokens.append(registration_tokens[idx])
print('List of tokens that caused failures: {0}'.format(failed_tokens))
Go
// Create a list containing up to 500 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Tokens: registrationTokens,
}
br, err := client.SendMulticast(context.Background(), message)
if err != nil {
log.Fatalln(err)
}
if br.FailureCount > 0 {
var failedTokens []string
for idx, resp := range br.Responses {
if !resp.Success {
// The order of responses corresponds to the order of the registration tokens.
failedTokens = append(failedTokens, registrationTokens[idx])
}
}
fmt.Printf("List of tokens that caused failures: %v\n", failedTokens)
}
C#
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
Tokens = registrationTokens,
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
};
var response = await FirebaseMessaging.DefaultInstance.SendEachForMulticastAsync(message);
if (response.FailureCount > 0)
{
var failedTokens = new List<string>();
for (var i = 0; i < response.Responses.Count; i++)
{
if (!response.Responses[i].IsSuccess)
{
// The order of responses corresponds to the order of the registration tokens.
failedTokens.Add(registrationTokens[i]);
}
}
Console.WriteLine($"List of tokens that caused failures: {failedTokens}");
}
주제로 메시지 보내기
주제를 만든 후에는 클라이언트 측의 클라이언트 앱 인스턴스에서 주제를 구독하거나 서버 API를 통해 주제에 메시지를 전송할 수 있습니다. FCM용 전송 요청을 처음 작성하는 경우 서버 환경 및 FCM 가이드에서 중요한 배경 및 설정 정보를 참조하세요.
백엔드의 전송 로직에서 아래와 같이 원하는 주제 이름을 지정합니다.
Node.js
// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';
const message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
자바
// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'
# See documentation on defining a message payload.
message = messaging.Message(
data={
'score': '850',
'time': '2:45',
},
topic=topic,
)
# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Go
// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Topic: topic,
}
// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
C#
// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic" : "foo-bar",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message"
}
}
}
cURL 명령어:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message": {
"topic" : "foo-bar",
"notification": {
"body": "This is a Firebase Cloud Messaging Topic Message!",
"title": "FCM Message"
}
}
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
여러 주제를 조합하여 메시지를 보내려면 대상 주제를 지정하는 불리언 표현식인 조건을 지정합니다. 예를 들어 다음 조건은 TopicA
와 함께 TopicB
또는 TopicC
를 구독하는 기기로 메시지를 전송합니다.
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
FCM은 괄호 안의 조건부터 모두 판정한 후 왼쪽에서 오른쪽으로 표현식을 판정합니다. 위 표현식에서 주제를 하나만 구독한 사용자는 메시지를 수신하지 않습니다. TopicA
를 구독하지 않은 사용자도 메시지를 수신하지 않습니다. 다음과 같은 조합으로 구독해야 메시지를 수신합니다.
TopicA
,TopicB
TopicA
,TopicC
조건식에 최대 5개의 주제를 포함할 수 있습니다.
조건으로 보내는 방법은 다음과 같습니다.
Node.js
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';
// See documentation on defining a message payload.
const message = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
condition: condition
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
자바
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("$GOOG up 1.43% on the day")
.setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
.build())
.setCondition(condition)
.build();
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"
# See documentation on defining a message payload.
message = messaging.Message(
notification=messaging.Notification(
title='$GOOG up 1.43% on the day',
body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
),
condition=condition,
)
# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Go
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Condition: condition,
}
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
C#
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
var message = new Message()
{
Notification = new Notification()
{
Title = "$GOOG up 1.43% on the day",
Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Condition = condition,
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"condition": "'dogs' in topics || 'cats' in topics",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
}
}
}
cURL 명령어:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"notification": {
"title": "FCM Message",
"body": "This is a Firebase Cloud Messaging Topic Message!",
},
"condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
기기 그룹에 메시지 전송
기기 그룹에 메시지를 보내려면 HTTP v1 API를 사용하세요. 현재 HTTP 또는 XMPP에 지원 중단된 기존 전송 API 또는 기존 프로토콜을 기반으로 하는 이전 버전의 Node.js용 Firebase Admin SDK를 사용하는 기기 그룹에 전송하는 경우 가능한 한 빨리 HTTP v1 API로 이전하는 것이 좋습니다. 2024년 6월에 기존 전송 API가 사용 중지 및 삭제됩니다.
기기 그룹에 메시지를 보내는 것은 개별 기기에 메시지를 보내는 것과 매우 비슷하며 전송 요청을 승인하는 동일한 방법을 사용합니다. token
필드를 그룹 알림 키로 설정합니다.
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"token":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
"data":{
"hello": "This is a Firebase Cloud Messaging device group message!"
}
}
}
cURL 명령어
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
"data":{
"hello": "This is a Firebase Cloud Messaging device group message!"
},
"token":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ"
}}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
일괄 메시지 전송
Admin SDK는 일괄 메시지 전송을 지원합니다. 최대 500개의 메시지를 일괄 항목 하나로 그룹화한 후 단일 API 호출로 전송할 수 있으며, 메시지마다 개별 HTTP 요청을 전송하는 것보다 성능이 크게 향상됩니다.
이 기능을 사용하여 맞춤설정된 메시지 모음을 만들고 주제 또는 특정 기기 등록 토큰을 비롯한 여러 수신자에게 전송할 수 있습니다. 예를 들어 메시지 본문의 내용이 약간 다른 메시지를 여러 잠재고객에게 동시에 보내야 하는 경우에 이 기능을 사용하세요.
Node.js
// Create a list containing up to 500 messages.
const messages = [];
messages.push({
notification: { title: 'Price drop', body: '5% off all electronics' },
token: registrationToken,
});
messages.push({
notification: { title: 'Price drop', body: '2% off all books' },
topic: 'readers-club',
});
getMessaging().sendAll(messages)
.then((response) => {
console.log(response.successCount + ' messages were sent successfully');
});
자바
// Create a list containing up to 500 messages.
List<Message> messages = Arrays.asList(
Message.builder()
.setNotification(Notification.builder()
.setTitle("Price drop")
.setBody("5% off all electronics")
.build())
.setToken(registrationToken)
.build(),
// ...
Message.builder()
.setNotification(Notification.builder()
.setTitle("Price drop")
.setBody("2% off all books")
.build())
.setTopic("readers-club")
.build()
);
BatchResponse response = FirebaseMessaging.getInstance().sendAll(messages);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");
Python
# Create a list containing up to 500 messages.
messages = [
messaging.Message(
notification=messaging.Notification('Price drop', '5% off all electronics'),
token=registration_token,
),
# ...
messaging.Message(
notification=messaging.Notification('Price drop', '2% off all books'),
topic='readers-club',
),
]
response = messaging.send_all(messages)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))
Go
// Create a list containing up to 500 messages.
messages := []*messaging.Message{
{
Notification: &messaging.Notification{
Title: "Price drop",
Body: "5% off all electronics",
},
Token: registrationToken,
},
{
Notification: &messaging.Notification{
Title: "Price drop",
Body: "2% off all books",
},
Topic: "readers-club",
},
}
br, err := client.SendAll(context.Background(), messages)
if err != nil {
log.Fatalln(err)
}
// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)
C#
// Create a list containing up to 500 messages.
var messages = new List<Message>()
{
new Message()
{
Notification = new Notification()
{
Title = "Price drop",
Body = "5% off all electronics",
},
Token = registrationToken,
},
new Message()
{
Notification = new Notification()
{
Title = "Price drop",
Body = "2% off all books",
},
Topic = "readers-club",
},
};
var response = await FirebaseMessaging.DefaultInstance.SendEachAsync(messages);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");
직접 부팅이 사용 설정된 메시지 전송(Android만 해당)
HTTP v1 또는 기존 HTTP API를 사용하여 직접 부팅 모드의 기기로 메시지를 보낼 수 있습니다. 직접 부팅 모드의 기기로 메시지를 보내기 전에 클라이언트 기기가 직접 부팅 모드에서 FCM 메시지를 수신하는 단계를 완료했는지 확인하세요.
FCM v1 HTTP API를 사용하여 전송
메시지 요청에는 요청 본문의 AndroidConfig
옵션에 "direct_boot_ok" : true
키를 포함해야 합니다. 예를 들면 다음과 같습니다.
https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
Content-Type:application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"token" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
"data": {
"score": "5x1",
"time": "15:10"
},
"android": {
"direct_boot_ok": true,
},
}
FCM 기존 HTTP API를 사용하여 전송
메시지 요청에는 요청 본문의 최상위 수준에 "direct_boot_ok" : true
키를 포함해야 합니다. 예를 들면 다음과 같습니다.
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
"direct_boot_ok" : true
}
요청 본문에서 이 키로 전송된 메시지는 현재 직접 부팅 모드(및 이 모드가 아닌 경우에도 해당)의 기기에 있는 앱에서 처리할 수 있습니다.
플랫폼에 맞게 메시지 맞춤설정
Firebase Admin SDK 및 FCM v1 HTTP 프로토콜을 모두 사용하면 메시지 요청을 통해 message
객체에 제공되는 모든 필드를 설정할 수 있습니다. 여기에는 다음이 포함됩니다.
- 메시지를 수신한 모든 앱 인스턴스에서 해석하는 공통 필드 모음
- 지정된 플랫폼에서 실행되는 앱 인스턴스에서만 해석되는
AndroidConfig
및WebpushConfig
와 같은 플랫폼별 필드 집합
플랫폼별 블록을 사용하면 수신 시 올바르게 처리할 수 있도록 다양한 플랫폼에 맞게 메시지를 유연하게 맞춤설정할 수 있습니다. FCM 백엔드는 지정된 모든 매개변수를 고려하여 각 플랫폼에 맞게 메시지를 맞춤설정합니다.
공통 필드를 사용해야 하는 경우
다음 작업에 공통 필드를 사용합니다.
- Apple, Android, 웹 등 모든 플랫폼의 앱 인스턴스 타겟팅
- 주제로 메시지 전송
플랫폼에 관계없이 모든 앱 인스턴스가 다음 공통 필드를 해석할 수 있습니다.
플랫폼별 필드를 사용해야 하는 경우
다음 작업을 하려면 플랫폼별 필드를 사용합니다.
- 특정 플랫폼에만 필드 전송
- 공통 필드 외에도 플랫폼별 필드 전송
특정 플랫폼에만 값을 보내려면 공통 필드를 사용하지 말고 플랫폼별 필드를 사용하세요. 예를 들어 Android를 제외한 Apple 플랫폼과 웹에만 알림을 보내려면 Apple 및 웹용으로 각각 하나씩 2개의 개별 필드 모음을 사용해야 합니다.
특정 전송 옵션으로 메시지를 보내는 경우에는 플랫폼별 필드를 사용하여 설정합니다. 원하는 경우 플랫폼별로 다른 값을 지정할 수 있지만 여러 플랫폼에 근본적으로 동일한 값을 설정하는 경우에도 플랫폼별 필드를 사용해야 합니다. 그 이유는 각 플랫폼에서 값을 약간씩 다르게 해석할 수 있기 때문입니다. 예를 들어 TTL(수명)이 Android에서는 만료 시간(초 단위)으로 설정되지만 Apple에서는 만료일로 설정됩니다.
예시: 색상 및 아이콘 옵션이 있는 알림 메시지
이 전송 요청 예시는 모든 플랫폼에 공통 알림 제목과 콘텐츠를 보내며 Android 기기에는 일부 플랫폼별 재정의도 보냅니다.
Android에서 이 요청은 Android 기기에 표시할 특수 아이콘과 색상을 설정합니다. AndroidNotification에 대한 참조에서 언급한 대로 색상은 #rrggbb 형식으로 지정되고 이미지는 Android 앱에 로컬인 드로어블 아이콘 리소스여야 합니다.
다음은 사용자 기기에 표시되는 시각 효과의 근사치입니다.
Node.js
const topicName = 'industry-tech';
const message = {
notification: {
title: '`$FooCorp` up 1.43% on the day',
body: 'FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
android: {
notification: {
icon: 'stock_ticker_update',
color: '#7e55c3'
}
},
topic: topicName,
};
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
자바
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("$GOOG up 1.43% on the day")
.setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
.build())
.setAndroidConfig(AndroidConfig.builder()
.setTtl(3600 * 1000)
.setNotification(AndroidNotification.builder()
.setIcon("stock_ticker_update")
.setColor("#f45342")
.build())
.build())
.setApnsConfig(ApnsConfig.builder()
.setAps(Aps.builder()
.setBadge(42)
.build())
.build())
.setTopic("industry-tech")
.build();
Python
message = messaging.Message(
notification=messaging.Notification(
title='$GOOG up 1.43% on the day',
body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
),
android=messaging.AndroidConfig(
ttl=datetime.timedelta(seconds=3600),
priority='normal',
notification=messaging.AndroidNotification(
icon='stock_ticker_update',
color='#f45342'
),
),
apns=messaging.APNSConfig(
payload=messaging.APNSPayload(
aps=messaging.Aps(badge=42),
),
),
topic='industry-tech',
)
Go
oneHour := time.Duration(1) * time.Hour
badge := 42
message := &messaging.Message{
Notification: &messaging.Notification{
Title: "$GOOG up 1.43% on the day",
Body: "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Android: &messaging.AndroidConfig{
TTL: &oneHour,
Notification: &messaging.AndroidNotification{
Icon: "stock_ticker_update",
Color: "#f45342",
},
},
APNS: &messaging.APNSConfig{
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
Badge: &badge,
},
},
},
Topic: "industry-tech",
}
C#
var message = new Message
{
Notification = new Notification()
{
Title = "$GOOG up 1.43% on the day",
Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Android = new AndroidConfig()
{
TimeToLive = TimeSpan.FromHours(1),
Notification = new AndroidNotification()
{
Icon = "stock_ticker_update",
Color = "#f45342",
},
},
Apns = new ApnsConfig()
{
Aps = new Aps()
{
Badge = 42,
},
},
Topic = "industry-tech",
};
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic":"industry-tech",
"notification":{
"title":"`$FooCorp` up 1.43% on the day",
"body":"FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day."
},
"android":{
"notification":{
"icon":"stock_ticker_update",
"color":"#7e55c3"
}
}
}
}
메시지 본문의 플랫폼별 블록에서 제공하는 키에 관한 자세한 내용은 HTTP v1 참조 문서를 확인하세요.
예시: 커스텀 이미지가 있는 알림 메시지
다음 전송 요청 예시는 모든 플랫폼에 공통 알림 제목을 보내지만 이미지도 보냅니다. 다음은 사용자 기기에 표시되는 시각 효과의 근사치입니다.
Node.js
const topicName = 'industry-tech';
const message = {
notification: {
title: 'Sparky says hello!'
},
android: {
notification: {
imageUrl: 'https://foo.bar.pizza-monster.png'
}
},
apns: {
payload: {
aps: {
'mutable-content': 1
}
},
fcm_options: {
image: 'https://foo.bar.pizza-monster.png'
}
},
webpush: {
headers: {
image: 'https://foo.bar.pizza-monster.png'
}
},
topic: topicName,
};
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic":"industry-tech",
"notification":{
"title":"Sparky says hello!",
},
"android":{
"notification":{
"image":"https://foo.bar/pizza-monster.png"
}
},
"apns":{
"payload":{
"aps":{
"mutable-content":1
}
},
"fcm_options": {
"image":"https://foo.bar/pizza-monster.png"
}
},
"webpush":{
"headers":{
"image":"https://foo.bar/pizza-monster.png"
}
}
}
}
메시지 본문의 플랫폼별 블록에서 제공하는 키에 관한 자세한 내용은 HTTP v1 참조 문서를 확인하세요.
예시: 연결된 클릭 작업이 있는 알림 메시지
다음 전송 요청 예시는 모든 플랫폼에 공통 알림 제목을 보내지만, 알림과 상호작용하는 사용자에 대한 응답으로 앱에서 수행할 작업도 보냅니다. 다음은 사용자 기기에 표시되는 시각 효과의 근사치입니다.
Node.js
const topicName = 'industry-tech';
const message = {
notification: {
title: 'Breaking News....'
},
android: {
notification: {
clickAction: 'news_intent'
}
},
apns: {
payload: {
aps: {
'category': 'INVITE_CATEGORY'
}
}
},
webpush: {
fcmOptions: {
link: 'breakingnews.html'
}
},
topic: topicName,
};
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic":"industry-tech",
"notification":{
"title":"Breaking News...",
},
"android":{
"notification":{
"click_action":"news_intent"
}
},
"apns":{
"payload":{
"aps":{
"category" : "INVITE_CATEGORY"
}
},
},
"webpush":{
"fcm_options":{
"link":"breakingnews.html"
}
}
}
}
메시지 본문의 플랫폼별 블록에서 제공하는 키에 관한 자세한 내용은 HTTP v1 참조 문서를 확인하세요.
예시: 현지화 옵션이 있는 알림 메시지
다음 전송 요청 예시는 현지화된 메시지를 표시하도록 클라이언트에 현지화 옵션을 보냅니다. 다음은 사용자 기기에 표시되는 시각 효과의 근사치입니다.
Node.js
var topicName = 'industry-tech';
var message = {
android: {
ttl: 3600000,
notification: {
bodyLocKey: 'STOCK_NOTIFICATION_BODY',
bodyLocArgs: ['FooCorp', '11.80', '835.67', '1.43']
}
},
apns: {
payload: {
aps: {
alert: {
locKey: 'STOCK_NOTIFICATION_BODY',
locArgs: ['FooCorp', '11.80', '835.67', '1.43']
}
}
}
},
topic: topicName,
};
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic":"Tech",
"android":{
"ttl":"3600s",
"notification":{
"body_loc_key": "STOCK_NOTIFICATION_BODY",
"body_loc_args": ["FooCorp", "11.80", "835.67", "1.43"],
},
},
"apns":{
"payload":{
"aps":{
"alert" : {
"loc-key": "STOCK_NOTIFICATION_BODY",
"loc-args": ["FooCorp", "11.80", "835.67", "1.43"],
},
},
},
},
},
}'
메시지 본문의 플랫폼별 블록에서 제공하는 키에 관한 자세한 내용은 HTTP v1 참조 문서를 확인하세요.
HTTP v1 API의 REST 오류 코드
HTTP v1 API의 HTTP 오류 응답에는 오류 코드, 오류 메시지, 오류 상태가 포함됩니다.
오류에 대한 자세한 내용이 포함된 details
배열도 포함될 수 있습니다.
다음은 두 가지 샘플 오류 응답입니다.
예시 1: 데이터 메시지에 잘못된 값이 포함된 HTTP v1 API 요청의 오류 응답
{
"error": {
"code": 400,
"message": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "message.data[0].value",
"description": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12"
}
]
}
]
}
}
예시 2: 잘못된 등록 토큰이 포함된 HTTP v1 API 요청의 오류 응답
{
"error": {
"code": 400,
"message": "The registration token is not a valid FCM registration token",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
"errorCode": "INVALID_ARGUMENT"
}
]
}
}
두 메시지의 코드와 상태는 동일하지만 세부정보 배열에는 다른 유형의 값이 포함됩니다. 첫 번째 예에는 요청 값의 오류를 나타내는 유형 type.googleapis.com/google.rpc.BadRequest
가 있습니다. 유형이 type.googleapis.com/google.firebase.fcm.v1.FcmError
인 두 번째 예시에는 FCM 관련 오류가 있습니다. 대부분의 오류의 경우 세부정보 배열에 디버그하고 해결 방법을 찾는 데 필요한 정보가 포함되어 있습니다.
다음 표에는 FCM v1 REST API 오류 코드와 설명이 나와있습니다.
오류 코드 | 설명 및 해결 단계 |
---|---|
UNSPECIFIED_ERROR 이 오류에 관한 추가 정보는 없습니다. |
없음. |
INVALID_ARGUMENT (HTTP 오류 코드 = 400) 요청 매개변수가 잘못되었습니다. 잘못된 필드를 지정하기 위해 google.rpc.BadRequest 유형의 확장 프로그램이 반환됩니다. |
잘못된 등록, 잘못된 패키지 이름, 너무 큰 메시지, 잘못된 데이터 키, 잘못된 TTL 또는 기타 잘못된 파라미터가 원인일 수 있습니다. 잘못된 등록: 서버에 전달하는 등록 토큰의 형식을 확인합니다. FCM에 등록할 때 클라이언트 앱이 수신하는 등록 토큰과 일치하는지 확인합니다. 토큰을 자르거나 다른 문자를 추가해서는 안 됩니다. 잘못된 패키지 이름: 패키지 이름이 요청에서 전달된 값과 일치하는 등록 토큰으로 메시지 주소가 지정되었는지 확인합니다. 너무 큰 메시지: 메시지에 포함된 페이로드 데이터의 총 크기가 FCM 한도를 초과하지 않는지 확인합니다. 대부분의 메시지는 4,096바이트이고 주제로 보내는 메시지의 경우는 2,048바이트입니다. 여기에는 키와 값이 모두 포함됩니다. 잘못된 데이터 키: FCM에서 내부적으로 사용하는 키(예: from, gcm, google이 앞에 붙은 값)가 페이로드 데이터에 포함되어 있지 않은지 확인합니다. 또한 페이로드 값이 FCM 값에 의해 재정의되는 경우에는 FCM에서 사용하는 collapse_key와 같은 일부 단어가 페이로드에도 허용된다는 점에 유의하세요. 잘못된 TTL: ttl에 사용된 값이 0~2,419,200초(4주) 사이의 기간을 나타내는 정수인지 확인합니다. 잘못된 파라미터: 제공된 파라미터의 이름과 유형이 올바른지 확인합니다. |
UNREGISTERED (HTTP 오류 코드 = 404) 앱 인스턴스가 FCM에서 등록 취소되었습니다. 이는 일반적으로 사용된 토큰이 더 이상 유효하지 않으며 새 토큰을 사용해야 함을 의미합니다. |
이 오류는 등록 토큰 누락 또는 등록 취소된 토큰으로 인해 발생할 수 있습니다. 등록 누락: 메시지의 타겟이 token 값인 경우 요청에 등록 토큰이 포함되어 있는지 확인합니다.등록되지 않음: 다음을 비롯한 몇몇 상황에서는 기존 등록 토큰이 더 이상 유효하지 않게 될 수 있습니다. - 클라이언트 앱이 FCM에서 등록 해제된 경우입니다. - 클라이언트 앱이 자동으로 등록 해제되었습니다. 사용자가 애플리케이션을 제거한 경우에 발생할 수 있습니다. 예를 들어 iOS에서 APNs 피드백 서비스가 APNs 토큰이 잘못되었다고 보고한 경우입니다. - 등록 토큰이 만료되었습니다. 예를 들어 Google에서 등록 토큰 새로고침을 결정한 경우이거나 APNs 토큰이 iOS 기기에서 만료된 경우입니다. - 클라이언트 앱이 업데이트되었지만 새 버전이 메시지를 수신할 수 있도록 구성되지 않았습니다. 위와 같은 경우에는 앱 서버에서 등록 토큰을 삭제하고 더 이상 메시지 전송에 이 등록 토큰을 사용하지 마세요. |
SENDER_ID_MISMATCH (HTTP 오류 코드 = 403) 인증된 발신자 ID가 등록 토큰의 발신자 ID와 다릅니다. |
등록 토큰은 특정 발신자 그룹에 연결됩니다. 클라이언트 앱을 FCM에 등록할 때 메시지를 보낼 수 있는 발신자를 지정해야 합니다. 클라이언트 앱에 메일을 보낼 때는 발신자 ID 중 하나를 사용해야 합니다. 다른 발신자로 전환하면 기존 등록 토큰이 작동하지 않습니다. |
QUOTA_EXCEEDED (HTTP 오류 코드 = 429) 메시지 타겟의 전송 한도를 초과했습니다. 초과된 할당량을 지정하기 위해 google.rpc.QuotaFailure 유형의 확장 프로그램이 반환됩니다. |
이 오류는 메시지 속도 할당량 초과, 기기 메시지 속도 할당량 초과 또는 주제 메시지 속도 할당량 초과로 인해 발생할 수 있습니다. 메시지 속도 초과: 메시지 전송 속도가 너무 높습니다. 전반적인 메시지 전송 속도를 줄여야 합니다. 최소 초기 지연 시간이 1분인 지수 백오프를 사용하여 거부된 메시지를 다시 시도합니다. 기기 메시지 속도 초과: 특정 기기로 전달되는 메시지 속도가 너무 높습니다. 단일 기기에 대한 메시지 속도 제한을 참고하세요. 이 기기로 보내는 메시지 수를 줄이고 전송을 재시도할 때 지수 백오프를 사용하세요. 주제 메시지 속도 초과: 특정 주제의 구독자에게 전달되는 메시지 속도가 너무 높습니다. 이 주제로 보내는 메시지 수를 줄이고 최소 초기 지연 시간이 1분인 지수 백오프를 사용하여 전송을 재시도하세요. |
UNAVAILABLE (HTTP 오류 코드 = 503) 서버가 과부하되었습니다. |
서버에서 시간 내에 요청을 처리하지 못했습니다. 동일한 요청을 다시 시도하되 다음을 수행해야 합니다. - FCM 연결 서버의 응답에 포함된 경우 Retry-After 헤더를 적용합니다. - 재시도 방식에서 지수 백오프를 구현합니다. (예를 들어 첫 번째 재시도 전에 1초 동안 기다렸다면 다음에는 2초, 그 다음에는 4초 동안 기다리는 식으로 대기 시간을 점차 늘립니다.) 여러 메시지를 보내는 경우 지터링을 적용하는 것이 좋습니다. 자세한 내용은 재시도 처리를 참조하세요. 문제를 유발하는 발신자는 차단될 수 있습니다. |
INTERNAL (HTTP 오류 코드 = 500) 알 수 없는 내부 오류가 발생했습니다. |
요청을 처리하려고 시도하는 중에 서버에 오류가 발생했습니다. 재시도 처리의 제안사항에 따라 동일한 요청을 다시 시도할 수 있습니다. 오류가 계속되면 Firebase 지원팀에 문의하시기 바랍니다. |
THIRD_PARTY_AUTH_ERROR (HTTP 오류 코드 = 401) APNs 인증서 또는 웹 푸시 인증 키가 잘못되거나 누락되었습니다. |
iOS 기기 또는 웹 푸시 등록을 타겟팅한 메시지를 보낼 수 없습니다. 개발 및 프로덕션 인증 정보의 유효성을 확인하세요. |
관리자 오류 코드
다음 표에는 Firebase Admin FCM API 오류 코드와 권장되는 해결 단계를 포함한 설명이 나와 있습니다.
오류 코드 | 설명 및 해결 단계 |
---|---|
messaging/invalid-argument |
FCM 메서드에 잘못된 인수가 제공되었습니다. 오류 메시지에 추가 정보가 들어 있습니다. |
messaging/invalid-recipient |
의도된 메시지 수신자가 잘못되었습니다. 오류 메시지에 추가 정보가 들어 있습니다. |
messaging/invalid-payload |
잘못된 메시지 페이로드 객체가 제공되었습니다. 오류 메시지에 추가 정보가 들어 있습니다. |
messaging/invalid-data-payload-key |
데이터 메시지 페이로드에 잘못된 키가 있습니다. 제한되는 키는 DataMessagePayload 참조 문서를 확인하세요.
|
messaging/payload-size-limit-exceeded |
제공된 메시지 페이로드가 FCM 크기 한도를 초과합니다. 대부분의 메시지는 4,096바이트로 제한됩니다. 주제로 보낸 메시지는 2,048바이트로 제한됩니다. 전체 페이로드 크기에는 키와 값이 모두 포함됩니다. |
messaging/invalid-options |
잘못된 메시지 옵션 객체가 제공되었습니다. 오류 메시지에 추가 정보가 들어 있습니다. |
messaging/invalid-registration-token |
잘못된 등록 토큰이 제공되었습니다. FCM에 등록할 때 클라이언트 앱이 수신하는 등록 토큰과 일치하는지 확인합니다. 문자를 자르거나 추가하지 마세요. |
messaging/registration-token-not-registered |
제공된 등록 토큰이 등록되지 않았습니다. 이전에 유효했던 등록 토큰이 다음을 비롯한 여러 가지 이유로 등록 취소되었을 수 있습니다.
|
messaging/invalid-package-name |
메시지를 보낼 대상으로 지정한 등록 토큰의 패키지 이름이 제공된 restrictedPackageName 옵션과 일치하지 않습니다. |
messaging/message-rate-exceeded |
특정 대상으로 전달되는 메시지 비율이 너무 높습니다. 이 기기 또는 주제로 보내는 메시지 수를 줄이세요. 이 대상으로 바로 다시 보내도록 시도해서는 안 됩니다. |
messaging/device-message-rate-exceeded |
특정 기기로 전달되는 메시지 비율이 너무 높습니다. 이 기기로 보내는 메시지 수를 줄이세요. 이 기기로 바로 다시 보내도록 시도해서는 안 됩니다. |
messaging/topics-message-rate-exceeded |
특정 주제의 구독자에게 전달되는 메시지 비율이 너무 높습니다. 이 주제로 보내는 메시지 수를 줄이세요. 바로 다시 보내도록 시도해서는 안 됩니다. |
messaging/too-many-topics |
등록 토큰에서 구독하는 주제 수가 최대값에 도달하여 더 이상 구독할 수 없습니다. |
messaging/invalid-apns-credentials |
필수 APN SSL 인증서가 업로드되지 않았거나 만료되어 Apple 기기를 대상으로 메시지를 보낼 수 없습니다. 개발 및 프로덕션 인증서의 유효성을 확인하세요. |
messaging/mismatched-credential |
이 SDK를 인증하는 데 사용된 인증 정보에, 제공된 등록 토큰에 해당하는 기기로 메시지를 보낼 권한이 없습니다. 인증 정보와 등록 토큰이 동일한 Firebase 프로젝트에 속하는지 확인하세요. Firebase Admin SDK 인증 방법에 관한 자세한 내용은 앱에 Firebase 추가를 참조하세요. |
messaging/authentication-error |
SDK에서 FCM 서버에 인증할 수 없습니다. 반드시 FCM 메시지를 전송할 수 있는 올바른 권한이 있는 사용자 인증 정보로 Firebase Admin SDK를 인증해야 합니다. Firebase Admin SDK 인증 방법에 관한 자세한 내용은 앱에 Firebase 추가를 참조하세요. |
messaging/server-unavailable |
FCM 서버에서 시간 내에 요청을 처리하지 못했습니다. 동일한 요청을 다시 시도하되 다음을 수행해야 합니다.
|
messaging/internal-error |
요청을 처리하려고 시도하는 중에 FCM 서버에 오류가 발생했습니다. 위의 messaging/server-unavailable 행에 나와 있는 요구사항에 따라 동일한 요청을 다시 시도할 수 있습니다. 오류가 계속되면 버그 신고 지원 채널에 문제를 신고하시기 바랍니다.
|
messaging/unknown-error |
알 수 없는 서버 오류가 반환되었습니다. 자세한 내용은 오류 메시지의 원시 서버 응답을 참조하세요. 이 오류가 발생하면 버그 신고 지원 채널에 전체 오류 메시지를 신고하세요. |
기존 앱 서버 프로토콜을 사용하여 메시지 전송
현재 기존 프로토콜을 사용 중인 경우 이 섹션의 안내에 따라 메시지 요청을 작성하세요. HTTP를 통해 여러 플랫폼으로 전송하는 경우 v1 프로토콜을 사용하면 메시지 요청을 크게 간소화할 수 있다는 점을 참고하시기 바랍니다.
특정 기기에 메시지 전송
특정 기기로 메시지를 보내려면 to
키를 특정 앱 인스턴스의 등록 토큰으로 설정합니다. 등록 토큰에 대한 자세한 내용은 플랫폼별
클라이언트 설정 정보를 참조하세요.
HTTP POST 요청
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
HTTP 응답
{ "multicast_id": 108, "success": 1, "failure": 0, "results": [ { "message_id": "1:08" } ] }
XMPP 메시지
<message id="">
<gcm xmlns="google:mobile:data">
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
</gcm>
</message>
XMPP 응답
<message id=""> <gcm xmlns="google:mobile:data"> { "from":"REGID", "message_id":"m-1366082849205" "message_type":"ack" } </gcm> </message>
XMPP 연결 서버는 몇 가지 다른 응답 옵션을 제공합니다. 서버 응답 형식을 참조하세요.
클라이언트 앱에 다운스트림 메시지를 보낼 때 사용할 수 있는 메시지 옵션의 전체 목록은 선택한 연결 서버 프로토콜(HTTP 또는 XMPP)의 참조 정보를 확인하세요.
주제로 메시지 전송
Firebase Cloud Messaging 주제에 메시지를 보내는 것은 개별 기기나 사용자 그룹에 메시지를 보내는 것과 매우 비슷합니다. 앱 서버는 to
키를 /topics/yourTopic
과 같은 값으로 설정합니다.
개발자는 정규 표현식 "/topics/[a-zA-Z0-9-_.~%]+"
와 일치하는 주제 이름을 선택할 수 있습니다.
여러 주제의 조합으로 전송하려면 앱 서버가 to
키 대신 condition
키를 대상 주제를 지정하는 불리언 조건으로 설정해야 합니다. 예를 들어 TopicA
와 함께 TopicB
또는 TopicC
에 구독된 기기로 메시지를 전송하려면 다음 안내를 따르세요.
'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)
FCM은 괄호 안의 조건부터 모두 판정한 후 왼쪽에서 오른쪽으로 표현식을 판정합니다. 위 표현식에서는 주제 1개를 구독한 사용자는 메시지를 수신하지 않습니다. 또한 TopicA를 구독하지 않은 사용자도 메시지를 수신하지 않습니다. 다음과 같이 조합되어야 메시지를 수신합니다.
- TopicA 및 TopicB
- TopicA 및 TopicC
조건식에 최대 5개의 주제를 포함할 수 있으며 괄호가 지원됩니다.
지원되는 연산자는 &&
, ||
입니다.
주제 HTTP POST 요청
주제 1개로 보내는 방법은 다음과 같습니다.
https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
'dogs' 또는 'cats' 주제를 구독한 기기로 보내는 방법은 다음과 같습니다.
https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
주제 HTTP 응답
// Success example: { "message_id": "1023456" } // failure example: { "error": "TopicsMessageRateExceeded" }
주제 XMPP 메시지
주제 1개로 보내는 방법은 다음과 같습니다.
<message id="">
<gcm xmlns="google:mobile:data">
</gcm>
</message>
'dogs' 또는 'cats' 주제를 구독한 기기로 보내는 방법은 다음과 같습니다.
<message id=""> <gcm xmlns="google:mobile:data"> </gcm> </message>
주제 XMPP 응답
// Success example: { "message_id": "1023456" } // failure example: { "error": "TopicsMessageRateExceeded" }
FCM 서버가 주제 전송 요청에 성공 또는 실패 응답을 반환하는 데 최대 30초의 지연이 발생할 수 있습니다. 요청에서 이 지연 시간에 맞게 앱 서버 제한 시간 값을 설정해야 합니다.
기기 그룹에 메시지 전송
지원 중단된 기존 API를 사용하여 기기 그룹에 메시지를 보내는 것은 개별 기기에 메시지를 보내는 것과 매우 비슷합니다. to
매개변수를 기기 그룹의 고유 알림 키로 설정하세요.
이 섹션의 예시에서는 기존 HTTP 및 XMPP 프로토콜로 기기 그룹에 데이터 메시지를 보내는 방법을 확인할 수 있습니다.
기기 그룹 HTTP POST 요청
https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA { "to": "aUniqueKey", "data": { "hello": "This is a Firebase Cloud Messaging Device Group Message!", } }
기기 그룹 HTTP 응답
다음은 '성공' 응답의 예시입니다. notification_key
에 연결된 등록 토큰이 2개 있으며 메시지가 두 토큰에 모두 성공적으로 전송되었습니다.
{ "success": 2, "failure": 0 }
다음은 '부분 성공' 응답의 예시입니다. notification_key
에 연결된 등록 토큰이 3개 있습니다. 메시지가 등록 토큰 1개에만 성공적으로 전송되었습니다. 메시지를 수신하지 못한 등록 토큰(registration_ids
)이 응답 메시지에 표시됩니다.
{ "success":1, "failure":2, "failed_registration_ids":[ "regId1", "regId2" ] }
메시지가 notification_key
에 연결된 등록 토큰 1개 이상에 전송되지 못하면 앱 서버에서 백오프를 두고 재시도하게 됩니다.
서버에서 메시지를 보내려는 기기 그룹에 구성원이 없는 경우 다음과 같이 응답의 성공, 실패가 모두 0입니다.
{ "success": 0, "failure": 0 }
기기 그룹 XMPP 메시지
<message id=""> <gcm xmlns="google:mobile:data"> { "to": "aUniqueKey", "message_id": "m-1366082849205" , "data": { "hello":"This is a Firebase Cloud Messaging Device Group Message!" } } </gcm> </message>
기기 그룹 XMPP 응답
그룹에 메시지가 성공적으로 전송된 기기가 있으면 XMPP 연결 서버가 ACK로 응답합니다. 모든 메시지가 그룹의 모든 기기에 전송되지 못하면 XMPP 연결 서버가 NACK로 응답합니다.
다음은 '성공' 응답의 예시입니다. notification_key
에 연결된 등록 토큰이 3개 있으며 메시지가 모든 토큰에 성공적으로 전송되었습니다.
{ "from": "aUniqueKey", "message_type": "ack", "success": 3, "failure": 0, "message_id": "m-1366082849205" }
다음은 '부분 성공' 응답의 예시입니다. notification_key
에 연결된 등록 토큰이 3개 있습니다. 메시지가 등록 토큰 1개에만 성공적으로 전송되었습니다. 메시지를 수신하지 못한 등록 토큰이 응답 메시지에 표시됩니다.
{ "from": "aUniqueKey", "message_type": "ack", "success":1, "failure":2, "failed_registration_ids":[ "regId1", "regId2" ] }
FCM 연결 서버가 그룹의 모든 기기에 전송하지 못하면 앱 서버가 NACK 응답을 수신합니다.
전체 메시지 옵션 목록은 선택한 연결 서버 프로토콜 HTTP 또는 XMPP에 대한 참조 정보를 확인하세요.
Firebase Admin SDK 기존 전송 메서드
Firebase Admin Node.js SDK는 기존 FCM 서버 API를 기반으로 (FCM) 메시지 전송 메서드를 지원합니다.
이 메서드는 send()
메서드와 허용하는 인수가 다릅니다.
가능하다면 send()
메서드를 사용해야 하고, 개인 기기 또는 기기 그룹으로 메시지를 전송할 때는 이 페이지에 설명된 메서드만 사용해야 합니다.
개별 기기로 전송
등록 토큰을 sendToDevice()
메서드에 전달하여 개별 기기로 메시지를 보낼 수 있습니다.
Node.js
// This registration token comes from the client FCM SDKs.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';
// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
data: {
score: '850',
time: '2:45'
}
};
// Send a message to the device corresponding to the provided
// registration token.
getMessaging().sendToDevice(registrationToken, payload)
.then((response) => {
// See the MessagingDevicesResponse reference documentation for
// the contents of response.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
sendToDevice()
메서드에 단 하나의 등록 토큰 대신 등록 토큰 배열을 전달하면 여러 기기로 전송되는 멀티캐스트 메시지를 보낼 수도 있습니다.
Node.js
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...',
// ...
'ecupwIfBy1w:APA91bFtuMY7MktgxA3Au_Qx7cKqnf...'
];
// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
data: {
score: '850',
time: '2:45'
}
};
// Send a message to the devices corresponding to the provided
// registration tokens.
getMessaging().sendToDevice(registrationTokens, payload)
.then((response) => {
// See the MessagingDevicesResponse reference documentation for
// the contents of response.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
sendToDevice()
메서드는 FCM의 응답이 포함된 MessagingDevicesResponse
객체로 확인되는 프로미스를 반환합니다. 반환 유형의 형식은 단일 등록 토큰 또는 등록 토큰 배열을 전달할 때와 동일합니다.
인증 오류 또는 비율 제한 등의 상황이 발생하면 전체 메시지 처리가 실패합니다. 이러한 경우 sendToDevice()
이 반환하는 프로미스가 오류와 함께 거부됩니다. 설명 및 해결 단계가 포함된 전체 오류 코드 목록은 Admin FCM API 오류를 참조하세요.
기기 그룹으로 전송
sendToDeviceGroup()
메서드를 사용하면 기기 그룹의 알림 키를 지정하여 기기 그룹에 메시지를 보낼 수 있습니다.
Node.js
// See the "Managing device groups" link above on how to generate a
// notification key.
const notificationKey = 'some-notification-key';
// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
data: {
score: '850',
time: '2:45'
}
};
// Send a message to the device group corresponding to the provided
// notification key.
getMessaging().sendToDeviceGroup(notificationKey, payload)
.then((response) => {
// See the MessagingDeviceGroupResponse reference documentation for
// the contents of response.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
sendToDeviceGroup()
메서드는 FCM의 응답이 포함된 MessagingDevicesResponse
객체로 확인되는 프로미스를 반환합니다.
인증 오류 또는 비율 제한 등의 상황이 발생하면 전체 메시지 처리가 실패합니다. 이러한 경우 sendToDeviceGroup()
이 반환하는 프로미스가 오류와 함께 거부됩니다. 설명 및 해결 단계가 포함된 전체 오류 코드 목록은 Admin FCM API 오류를 참조하세요.
메시지 페이로드 정의
FCM 기존 프로토콜을 기반으로 하는 위 메서드는 두 번째 인수로 메시지 페이로드를 허용하고 알림 및 데이터 메시지를 둘 다 지원합니다.
data
또는 notification
키가 포함된 객체를 만들어 메시지 유형 중 하나 또는 둘 모두를 지정할 수 있습니다. 예를 들어 메시지 페이로드의 서로 다른 유형을 정의하는 방법은 다음과 같습니다.
알림 메시지
const payload = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
}
};
데이터 메시지
const payload = {
data: {
score: '850',
time: '2:45'
}
};
결합된 메시지
const payload = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
data: {
stock: 'GOOG',
open: '829.62',
close: '635.67'
}
};
알림 메시지 페이로드는 유효한 속성의 사전 정의된 하위 집합을 포함하며 타겟팅하는 모바일 운영체제에 따라 조금씩 달라집니다.
전체 목록은 NotificationMessagePayload
참조 문서를 확인하세요.
데이터 메시지 페이로드는 커스텀 키-값 쌍으로 구성되며 모든 값이 문자열이어야 한다는 점을 비롯하여 몇 가지 제한사항이 있습니다. 전체 제한사항 목록은 DataMessagePayload
참조 문서를 확인하세요.
메시지 옵션 정의
FCM 기존 프로토콜을 기반으로 하는 위 메서드는 메시지 관련 옵션을 지정하는 세 번째 인수(선택사항)를 허용합니다. 예를 들어 다음은 24시간 후에 만료되며 우선순위가 높은 메시지를 기기에 보내는 예입니다.
Node.js
// This registration token comes from the client FCM SDKs.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';
// See the "Defining the message payload" section above for details
// on how to define a message payload.
const payload = {
notification: {
title: 'Urgent action needed!',
body: 'Urgent action is needed to prevent your account from being disabled!'
}
};
// Set the message as high priority and have it expire after 24 hours.
const options = {
priority: 'high',
timeToLive: 60 * 60 * 24
};
// Send a message to the device corresponding to the provided
// registration token with the provided options.
getMessaging().sendToDevice(registrationToken, payload, options)
.then((response) => {
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
사용 가능한 옵션의 전체 목록은 MessagingOptions
참조 문서를 확인하세요.