[Python/FCM] 이모지를 푸시알림에 보내기

조오닭·2024년 10월 27일
1

1. Push Notification with FCM

앱 서비스에서 푸시알림(push notification)은 필수 조건이다.
이 중 가장 레퍼런스도 많고 자료도 많은 FCM을 사용해봤는데, 설정도 편하고 굳이 APNs 서버 만들 필요도 없어서 너무 간편했다.

푸시알림을 보내기 위해선 fcm에서 SDK, http v1 api 이 두 가지 방식을 지원하는데,
나는 그냥... 편하게 sdk를 사용하였다.
이건 좀 tmi인데, 다중 전송은 SDK로 보내게되면 묶어서가 아니라 메세지 한 개씩만 쏴서 매우 비효율적이라고 한다.
따라서 나중에 광고성 알림같은 broadcast로 보낼 땐 http v1으로 보내지 않을까 싶다.

아무튼, 기초적인 틀은 다음과 같다.

from firebase_admin import messaging
from firebase_admin.exceptions import FirebaseError

def sent_to_fcm(token, title, body, deep_link):
	# 메세지 설정
    message = messaging.Message(
        notification=messaging.Notification(
            title=title,
            body=body
        ),
        token=token,
        data={"url": deep_link}
    )
    # 메세지 보내기
    try:
        response = messaging.send(message)
        return response
    # 실패하면 에러 코드 및 메세지 반환
    except FirebaseError as e:
        return {"error_code": e.code, "message": e}

우리가 흔히 보는 구성으로 생각한다면, [ title / body / token / deep_link ]가 필요하다.

title: 푸시 알림의 제목. 보통 앱 이름이 들어간다. (굵은 색 글씨)
body: 푸시 알림의 내용.
token: 어느 사용자에게 보낼 것인지에 대한 식별자
deep_link: 이 메세지를 확인했을 때 어느 링크로 가는지

이것 외에도 사진이나 우선순위(해당 내용 구글링 추천 ㅎ) 등등... 넣을 수 있다.
또한, 이대로만 하면 안드로이드에선 푸시알림이 오지 않는데, 메세지 설정 시 channel_id를 추가적으로 설정해줘야 한다.

		android=messaging.AndroidConfig(
            notification=messaging.AndroidNotification(
                priority="high",
                click_action="NOTIFICATION_CLICK",
                channel_id="channel_id"
            )
        )

2. Send emoji to FCM in python

(사실 FCM에만 해당되는 내용이 아닐 수 있다ㅎ)

이모지(emoji)가 포함된 메세지를 python으로 다루고 FCM으로 보내는 건 어렵지 않지만 귀찮은 일이었다.

A. 보내고 싶은 이모지를 UTF-16 형태로 변환

만약 🤗 이모지를 보내고 싶다면, 사용자 기기에서 읽을 수 있도록 UTF-16로 전송해야 한다.
따라서 해당 이모지를 복사하여, UTF-16로 변환해주는 아래 사이트를 이용해야 한다.
https://onlinetools.com/unicode/convert-unicode-to-utf16
Input Unicode에 이모지를 붙여놓으면 오른쪽 'Output UTF-16'에 두 단어가 보이는데,
두 단어 앞에 \u를 붙인 다음에 띄어쓰기없이 나열하면 된다.

message = "\ud83e\udd17"

B. 하지만 에러

내 경우엔 메세지를 DB에 저장하면서 FCM으로 사용자에게 보내는 로직이었는데...

UnicodeEncodeError: 'utf-8' codec can't encode characters in position 0-1: surrogates not allowed

이런 오류가 발생하였다ㅎ.

일단 surrogate가 무엇인지 알 필요가 있다.
Surrogate는 UTF-16에서 BMP를 벗어나는 문자를 표현하기 위해 사용된다.
BMP는 다국어를 지원하기 위해 체계적으로 \U0000부터 \UFFFF까지의 영역을 차지하고 있다. 자세히 알고싶다면 이 링크로^^

하지만 이모지는 다국어가 아니기 때문에 하나의 코드로 제공할 수 없기에, 두 개가 한 쌍으로 이루어 표기된다. 따라서 \UD83E와 \UDD17 이 두 개가 하나의 이모지 🤗로 표현된다.
이 때, 파이썬은 이 surrogate를 제대로 처리하지 못하지만 처리해보겠다고 아둥바둥하다 오류를 낸 것이다.

구글링 끝에 해당 에러는 다음 코드와 같이 처리하였다.

.encode('utf-16_BE','surrogatepass').decode('utf-16_BE')

생각보다 쉬웠는데, encode와 decode할 때는 utf-16으로 동일하게 하지만 encode할 때는 surrogate pass 옵션을 줬다.

Surrogate pass는 말 그대로 surrogate 처리하지 않겠다는 의미와 같은데,
만약 \UD83E\UDD17가 한 쌍으로 붙어있으면 surrogate라고 생각하지 않고 개별의 코드 두 개인 \UD83E와 \UDD17로 생각하여 인코딩하고 byte형태로 반환한다는 뜻이다.

그리고 이걸 바로 우리가 읽을 수 있는 문자열 형태로 decode 해야하는데,
내가 원했던대로 \UD83E\UDD17로 된다! (이모지 db, 사용자 기기에게 맡기는 걸로)

profile
백엔드 응애

0개의 댓글

관련 채용 정보