获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

서버 환경 및 FCM

Firebase 클라우드 메시징의 서버측은 두 가지 구성요소로 구성됩니다.

  • Google에서 제공하는 FCM 백엔드 입니다.
  • Firebase용 Cloud Functions 또는 Google에서 관리하는 기타 클라우드 환경과 같이 서버 로직이 실행되는 앱 서버 또는 기타 신뢰할 수 있는 서버 환경 입니다.

앱 서버 또는 신뢰할 수 있는 서버 환경은 메시지 요청을 FCM 백엔드로 보내고 FCM 백엔드는 사용자의 기기에서 실행되는 클라이언트 앱으로 메시지를 라우팅합니다.

신뢰할 수 있는 서버 환경에 대한 요구 사항

앱 서버 환경은 다음 기준을 충족해야 합니다.

  • FCM 백엔드에 적절한 형식의 메시지 요청을 보낼 수 있습니다.
  • 지수 백오프를 사용하여 요청을 처리하고 다시 보낼 수 있습니다.
  • 서버 인증 자격 증명 및 클라이언트 등록 토큰을 안전하게 저장할 수 있습니다.
  • XMPP 프로토콜(사용되는 경우)의 경우 서버는 보내는 각 메시지를 고유하게 식별하기 위해 메시지 ID를 생성할 수 있어야 합니다(FCM HTTP 백엔드는 메시지 ID를 생성하고 응답에서 반환). XMPP 메시지 ID는 발신자 ID별로 고유해야 합니다.

서버 옵션 선택

Firebase Admin SDK 또는 원시 프로토콜을 사용하여 FCM 서버와 상호 작용하는 방법을 결정해야 합니다. 널리 사용되는 프로그래밍 언어를 지원하고 인증 및 권한 부여를 처리하는 편리한 방법으로 인해 Firebase Admin SDK가 권장되는 방법입니다.

FCM 서버와 상호 작용하기 위한 옵션에는 다음이 포함됩니다.

  • Node , Java , Python , C#Go 를 지원하는 Firebase Admin SDK.
  • 최신 프로토콜 옵션인 FCM HTTP v1 API , 더 안전한 인증 및 유연한 플랫폼 간 메시징 기능 (Firebase Admin SDK는 이 프로토콜을 기반으로 하며 모든 고유한 이점을 제공합니다). 새 기능은 일반적으로 HTTP v1 API에만 추가되므로 대부분의 사용 사례에 이 API를 사용하는 것이 좋습니다.
  • 레거시 HTTP 프로토콜. 새 프로젝트는 레거시 프로토콜 대신 FCM v1 HTTP API를 채택하는 것이 좋습니다.
  • 레거시 XMPP 서버 프로토콜. 새 프로젝트는 레거시 프로토콜 대신 FCM v1 HTTP API를 채택하는 것이 좋습니다.

FCM용 Firebase Admin SDK

Admin FCM API는 백엔드 인증을 처리하고 메시지 전송 및 주제 구독 관리를 용이하게 합니다. Firebase Admin SDK로 다음을 수행할 수 있습니다.

  • 개별 장치에 메시지 보내기
  • 하나 이상의 주제와 일치하는 주제 및 조건문에 메시지를 보냅니다.
  • 기기에서 주제 구독 및 구독 취소
  • 다양한 대상 플랫폼에 맞는 메시지 페이로드 구성

Admin Node.js SDK는 장치 그룹에 메시지를 보내는 방법을 제공합니다.

Firebase Admin SDK를 설정하려면 서버에 Firebase Admin SDK 추가 를 참조하세요. Firebase 프로젝트가 이미 있는 경우 SDK 추가 부터 시작하세요. 또한 프로젝트의 클라우드 메시징 설정 페이지 에서 클라우드 메시징 API를 활성화해야 합니다. 그런 다음 Firebase Admin SDK가 설치되면 전송 요청 을 작성하는 로직 작성을 시작할 수 있습니다.

FCM 서버 프로토콜

현재 FCM은 다음과 같은 원시 서버 프로토콜을 제공합니다.

앱 서버는 이러한 프로토콜을 개별적으로 또는 함께 사용할 수 있습니다. 여러 플랫폼에 메시지를 보내는 데 가장 유연하고 최신 상태이므로 가능한 경우 FCM HTTP v1 API를 사용하는 것이 좋습니다. 요구 사항에 장치에서 서버로의 업스트림 메시징이 포함되는 경우 XMPP 프로토콜을 구현해야 합니다.

XMPP 메시징은 다음과 같은 점에서 HTTP 메시징과 다릅니다.

  • 업스트림/다운스트림 메시지
    • HTTP: 다운스트림 전용, 클라우드-디바이스.
    • XMPP: 업스트림 및 다운스트림(디바이스-클라우드, 클라우드-디바이스).
  • 메시징(동기 또는 비동기)
    • HTTP: 동기식. 앱 서버는 HTTP POST 요청으로 메시지를 보내고 응답을 기다립니다. 이 메커니즘은 동기식이며 응답이 수신될 때까지 발신자가 다른 메시지를 보내는 것을 차단합니다.
    • XMPP: 비동기식. 앱 서버는 영구 XMPP 연결을 통해 최대 회선 속도로 모든 장치와 메시지를 주고받습니다. XMPP 연결 서버는 승인 또는 실패 알림(특수 ACK 및 NACK JSON 인코딩 XMPP 메시지 형식)을 비동기적으로 보냅니다.
  • JSON
    • HTTP: HTTP POST로 전송된 JSON 메시지입니다.
    • XMPP: XMPP 메시지에 캡슐화된 JSON 메시지.
  • 일반 텍스트
    • HTTP: HTTP POST로 전송되는 일반 텍스트 메시지입니다.
    • XMPP: 지원되지 않습니다.
  • 멀티캐스트 다운스트림은 여러 등록 토큰으로 보냅니다.
    • HTTP: JSON 메시지 형식으로 지원됩니다.
    • XMPP: 지원되지 않습니다.

HTTP 서버 프로토콜 구현

메시지를 보내기 위해 앱 서버는 JSON 키 값 쌍으로 구성된 HTTP 헤더 및 HTTP 본문을 사용하여 POST 요청을 발행합니다. 헤더 및 본문 옵션에 대한 자세한 내용은 앱 서버 전송 요청 빌드 를 참조하세요.

XMPP 서버 프로토콜 구현

FCM 메시지에 대한 JSON 페이로드는 다음을 제외하고 HTTP 프로토콜과 유사합니다.

  • 여러 수신자를 지원하지 않습니다.
  • FCM은 필수 필드 message_id 를 추가합니다. 이 ID는 XMPP 연결에서 메시지를 고유하게 식별합니다. FCM의 ACK 또는 NACK은 message_id 를 사용하여 앱 서버에서 FCM으로 보낸 메시지를 식별합니다. 따라서 이 message_id 가 고유할 뿐만 아니라( 발신자 ID 별로) 항상 존재하는 것이 중요합니다.
  • XMPP는 서버 키를 사용하여 FCM에 대한 영구 연결을 승인합니다. 자세한 내용은 보내기 요청 승인 을 참조하십시오.

일반 FCM 메시지 외에도 JSON 개체의 message_type 필드로 표시되는 제어 메시지가 전송됩니다. 값은 'ack', 'nack' 또는 'control'일 수 있습니다(아래 형식 참조). 알 수 없는 message_type 이 있는 모든 FCM 메시지는 서버에서 무시할 수 있습니다.

앱 서버가 FCM에서 수신하는 각 기기 메시지에 대해 ACK 메시지를 보내야 합니다. NACK 메시지를 보낼 필요가 없습니다. 메시지에 대한 ACK를 보내지 않으면 메시지가 먼저 만료되지 않는 한 FCM은 다음에 새 XMPP 연결이 설정될 때 이를 다시 보냅니다.

FCM은 또한 각 서버 대 장치 메시지에 대해 ACK 또는 NACK을 보냅니다. 둘 중 하나를 받지 못하면 작업 도중 TCP 연결이 닫혀 서버에서 메시지를 다시 보내야 함을 의미합니다. 자세한 내용은 흐름 제어 를 참조하십시오.

모든 메시지 매개변수 목록은 프로토콜 참조 를 참조하십시오.

요청 형식

페이로드가 있는 메시지 — 알림 메시지

다음은 알림 메시지에 대한 XMPP 스탠자입니다.

<message id="">
  <gcm xmlns="google:mobile:data">
  {
     "to":"REGISTRATION_ID",  // "to" replaces "registration_ids"
     "notification": {
        "title": "Portugal vs. Denmark”,
        "body”: "5 to 1”
      },
      "time_to_live":"600"
  }
  </gcm>
</message>

페이로드가 있는 메시지 — 데이터 메시지

다음은 앱 서버에서 FCM으로 보내는 JSON 메시지를 포함하는 XMPP 스탠자입니다.

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGISTRATION_ID",  // "to" replaces "registration_ids"
      "message_id":"m-1366082849205" // new required field
      "data":
      {
          "hello":"world",
      }
      "time_to_live":"600",
  }
  </gcm>
</message>

응답 형식

FCM 응답은 세 가지 가능한 형식을 가질 수 있습니다. 첫 번째는 일반적인 'ack' 메시지입니다. 그러나 응답에 오류가 포함된 경우 아래에 설명된 대로 메시지가 취할 수 있는 두 가지 다른 형식이 있습니다.

확인 메시지

다음은 FCM에서 앱 서버로 보내는 ACK/NACK 메시지가 포함된 XMPP 스탠자입니다.

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

NACK 메시지

NACK 오류는 message_type 상태 메시지가 "nack"인 일반 XMPP 메시지입니다. NACK 메시지에는 다음이 포함됩니다.

  • NACK 오류 코드입니다.
  • NACK 오류 설명입니다.

다음은 몇 가지 예입니다.

잘못된 등록:

<message>
  <gcm xmlns="google:mobile:data">
  {
    "message_type":"nack",
    "message_id":"msgId1",
    "from":"SomeInvalidRegistrationToken",
    "error":"BAD_REGISTRATION",
    "error_description":"Invalid token on 'to' field: SomeInvalidRegistrationId"
  }
  </gcm>
</message>

잘못된 JSON:

<message>
 <gcm xmlns="google:mobile:data">
 {
   "message_type":"nack",
   "message_id":"msgId1",
   "from":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
   "error":"INVALID_JSON",
   "error_description":"InvalidJson: JSON_TYPE_ERROR : Field \"time_to_live\" must be a JSON java.lang.Number: abc"
 }
 </gcm>
</message>

장치 메시지 속도 초과:

<message id="...">
  <gcm xmlns="google:mobile:data">
  {
    "message_type":"nack",
    "message_id":"msgId1",
    "from":"REGID",
    "error":"DEVICE_MESSAGE_RATE_EXCEEDED",
    "error_description":"Downstream message rate exceeded for this registration id"
  }
  </gcm>
</message>

NACK 오류 코드의 전체 목록은 서버 참조 를 참조하십시오. 달리 명시되지 않는 한 NACK 메시지는 재시도해서는 안 됩니다. 예기치 않은 NACK 오류 코드는 INTERNAL_SERVER_ERROR 와 동일하게 처리되어야 합니다.

스탠자 오류

특정 경우에 스탠자 오류가 발생할 수도 있습니다. 스탠자 오류에는 다음이 포함됩니다.

  • 스탠자 오류 코드.
  • 스탠자 오류 설명(자유 텍스트).

예를 들어:

<message id="3" type="error" to="123456789@fcm.googleapis.com/ABC">
  <gcm xmlns="google:mobile:data">
     {"random": "text"}
  </gcm>
  <error code="400" type="modify">
    <bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
    <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
      InvalidJson: JSON_PARSING_ERROR : Missing Required Field: message_id\n
    </text>
  </error>
</message>

제어 메시지

주기적으로 FCM은 로드 밸런싱을 수행하기 위해 연결을 종료해야 합니다. 연결을 닫기 전에 FCM은 CONNECTION_DRAINING 메시지를 보내 연결이 소모되고 있으며 곧 닫힐 것임을 나타냅니다. "드레이닝"은 연결로 들어오는 메시지의 흐름을 차단하지만 이미 파이프라인에 있는 것은 계속하도록 허용하는 것을 말합니다. CONNECTION_DRAINING 메시지를 받으면 즉시 다른 FCM 연결로 메시지 보내기를 시작하고 필요한 경우 새 연결을 열어야 합니다. 그러나 원래 연결을 열린 상태로 유지하고 연결을 통해 올 수 있는 메시지를 계속 수신(및 ACK)해야 합니다. FCM은 준비가 되면 연결 닫기 시작을 처리합니다.

CONNECTION_DRAINING 메시지는 다음과 같습니다.

<message>
  <data:gcm xmlns:data="google:mobile:data">
  {
    "message_type":"control"
    "control_type":"CONNECTION_DRAINING"
  }
  </data:gcm>
</message>

CONNECTION_DRAINING 은 현재 지원되는 유일한 control_type 입니다.

흐름 제어

FCM으로 전송된 모든 메시지는 ACK 또는 NACK 응답을 받습니다. 이러한 응답 중 하나를 받지 못한 메시지는 보류 중인 것으로 간주됩니다. 보류 중인 메시지 수가 100에 도달하면 앱 서버는 새 메시지 전송을 중지하고 FCM이 그림 1과 같이 기존 보류 중인 메시지 중 일부를 승인할 때까지 기다려야 합니다.

FCM과 앱 서버 간의 제어 흐름에 대한 상세 다이어그램

그림 1. 메시지/ack 흐름.

반대로 앱 서버 과부하를 방지하기 위해 FCM은 승인되지 않은 메시지가 너무 많은 경우 전송을 중지합니다. 따라서 앱 서버는 FCM을 통해 클라이언트 애플리케이션에서 수신한 업스트림 메시지를 최대한 빨리 "ACK"하여 들어오는 메시지의 흐름을 일정하게 유지해야 합니다. 앞서 언급한 보류 메시지 제한은 이러한 ACK에 적용되지 않습니다. 보류 중인 메시지 수가 100에 도달하더라도 앱 서버는 새로운 업스트림 메시지의 전달을 차단하지 않도록 FCM에서 받은 메시지에 대한 ACK를 계속 보내야 합니다.

ACK는 하나의 연결 컨텍스트 내에서만 유효합니다. 메시지가 ACK 되기 전에 연결이 닫히면 앱 서버는 다시 ACK를 받기 전에 FCM이 업스트림 메시지를 다시 보낼 때까지 기다려야 합니다. 마찬가지로 연결이 닫히기 전에 FCM에서 ACK/NACK을 받지 못한 모든 보류 메시지는 다시 보내야 합니다.