몰?.루();

안드로이드 광고성 푸쉬 알림 구현 본문

프로그래밍/안드로이드, 코틀린

안드로이드 광고성 푸쉬 알림 구현

toonraon 2024. 1. 13. 00:52

파이어베이스를 사용하다보면 클라우드 메세징Cloud Messaing 기능을 사용하는 경우가 있습니다.

이를 통해서 앱에 푸쉬 알림을 간편하게 보낼 수 있습니다.

 

다만 한국에서는 광고성 푸쉬 알림을 보낼 때 주의해야할 사항들이 몇 가지 있습니다.

자세한 건 이 포스팅에서 다루지 않겠지만, 대충 개발자가 유의해야할 사항은 다음과 같습니다.

 

  1. 광고성 푸쉬 알림을 보내기 위해서는 사용자에게 별도로 승인 요청을 받아야하며, 광고를 허용 받았든 거부 받았든 통지해야한다.
  2. 2년마다 광고성 푸쉬 알림을 계속해서 받을지 말지 확인 받아야한다. (2년마다 확인 여부 화면을 띄워주기만 하면 되고, 사용자가 딱히 의사 표현을 하지 않았다면 그냥 계속 광고 허용한 걸로 간주해도 됨)

하지만 문제는 클라우드 메시징으로 보낸 푸쉬 알림은 우리가 작성한 코드를 전혀 거치지 않을 수도 있다는 점입니다.

 

정확히는 앱이 포그라운드에 있는 경우엔 푸쉬가 날아왔을 때 FirebaseMessagingService를 상속하는 클래스가 오버라이딩한 onMessageReceived 함수를 호출하기 때문에 프로그래머가 if문으로 분기쳐서 광고성 푸쉬 동의한 적 있는 사람만 골라서 notification을 띄우면 되지만,

앱이 백그라운드에 있으면 onMessageReceived 함수 등 어떠한 코드도 호출되지 않고 그냥 알림을 띄워버리므로 광고를 안 보겠다고 한 사람까지 전부 푸쉬 알림이 뜨게 됩니다.

 

따라서 푸쉬가 왔을 때 if문으로 구분해서 어떻게 해보겠다하는 생각은 버려야합니다.

푸쉬를 보내기 전에, 아예 푸쉬를 보낼 대상에서 제외시킬 방법을 강구해야합니다.

 

제가 찾은 방법은 4가지입니다.

 

1. 자체 서버 구현

사실 이 모든 문제는 파이어베이스 콘솔 웹을 사용할 때 생기는 문제입니다.

아예 admin sdk를 이용해서 서버 코드로 푸쉬 알림을 전송해버린다면, 그리고 푸쉬를 보낼 때 'data' 필드를 함께 보낸다면, 앱이 백그라운드에 있든 포그라운드에 있든 onMessageReceived에 잡히게 되므로 if문으로 분기를 쳐서 지지고 볶고 삶을 수 있습니다.

 

하지만 문제들이 있습니다.

  • 자체 서버를 구현해야한다는 점
  • 마케팅 팀에게 대충 CLI 환경 던져주고 알아서 하라곤 할 수 없으니 조악하게나마 웹 UI를 만들어줘야 한다는 점
  • GA를 통해 수집한 각종 정보들(사용자 언어, 구독 여부, 최초 실행 시간, 마지막 실행 시간, 앱 버전)을 전혀 사용하지 못한다는 점

 

예를 들어 마케팅쪽에서 "이번엔 3개월 이상 우리 앱을 사용하지 않은 프리미엄 구독 유저들 중에서도 한국, 미국, 일본 유저에게만 푸쉬 알림을 보내고 싶어요"라고 한다면 그 요구 사항에 맞는 서버 사이드 코드를 구축되어 있어야 합니다.

 

하지만 구축 해놓기만 한다면 가장 확실한 방법이긴 해서, 규모가 큰 회사라면 이 방법이 좋을 거 같습니다.

 

2. 안드로이드 알림 채널 사용

안드로이드 8 이상에서는 NotificationChannel이라는 개념이 들어왔습니다.

따라서 minsdk가 안드 8 이상이라면 이 방법을 사용할 수...도 있긴한데 안 쓰시는 게 좋습니다.

 

클라우드 메시징 웹에 5번 추가 옵션을 보면, Android 알림 채널을 설정할 수 있습니다.

광고 전용 NotificationChannel을 만들고 저기에 그 채널 이름(여기선 advertisement_channel)을 쓰면 되지 않을까? 싶지만 치명적인 문제들이 몇 가지 있습니다.

  • NotificationChannel은 처음에 생성할 때는 ON, OFF를 개발자가 선택할 수 있지만, 한 번 생성된 채널의 ON, OFF는 건드릴 수 없습니다. 즉, 인앱 설정창에서 광고 알림을 끄는 기능을 만들고 싶다면, 인앱 코드만으로는 불가능하므로 intent를 이용해서 시스템 설정창의 알림 카테고리로 사용자를 랜딩시켜야합니다
  • 이 경우 알림 채널 추적이 매우 어려워집니다
    • 시스템 설정이므로 우리 앱을 전혀 안 거치고도 사용자가 채널을 켜버리거나 끌 수 있습니다
    • 그러면 이 사용자가 언제 킨 건지 개발자 입장에선 알 수 없습니다
    • 2년마다 광고 동의를 다시 물어보려면 정확히 언제 광고 허용을 한 건지 알아야하는데, 시스템 설정의 알림 채널이 몇월 며칠 몇시에 켜졌는지 정확히 알 방법이 없습니다
    • 알림 ON/OFF 변경시 결과 통지를 무조건 해야하는데, 시스템 설정 화면으로 랜딩 시켜버리니까 결과 통지하기도 참 애매합니다
  • 실수로 알림 채널에 오타를 내서 없는 채널로 전송할 경우, 모든 사용자에게 푸쉬가 안 가는 게 아니라 오히려 모든 사용자에게 푸쉬가 다 가버립니다
    • 이 말은 로직을 추가하기 전 구버전 앱들에서는 무조건 푸쉬가 갈 수 밖에 없다는 뜻입니다 (사용자 세그먼트에서 앱 버전으로 필터링을 걸지 않는 이상)
  • iOS쪽과 구현이 완전히 따로 놀게 됩니다 (iOS 알림 채널 설정 같은 건 없으므로)

이러한 이유 때문에 실제로 다른 앱에서도 알림 채널을 직접적으로 활용하는 곳은 없었습니다.

 

3. 주제 등록

사용자 세그먼트 대신 주제를 사용해서 필터링을 걸 수도 있습니다.

FirebaseMessaging.getInstance().subscribeToTopic("advertisement")

광고 허락한 사용자들은 위 코드로 advertisement라는 주제를 구독하게 할 수 있습니다.

반대로 광고를 안 보겠다고 한 사용자들은

FirebaseMessaging.getInstance().unsubscribeFromTopic("advertisement")

코드를 실행시켜서 주제를 구독 해제시킬 수 있습니다.

 

실험해보니 거의 즉시즉시 반영도 잘 되는 거 같았습니다.

그런데 이 방법의 치명적인 문제점이 있습니다.

  • 사용자 세그먼트를 전혀 사용할 수 없습니다.
    • 즉, 사용자를 언어로 나눌 수도 없고, 구독자로 나눌 수도 없고, 마지막 접속일로 나눌 수도 없습니다
    • 언어로 나눌 수 없기 때문에 전 세계 모든 광고 허용 사용자에게 하나의 똑같은 언어로 공평하게 푸쉬 알림이 가게 됩니다
    • 심지어 안드로이드, iOS 따로 구분할 수도 없습니다 (같은 파베를 쓰는 경우)

물론, 주제를 advertisement_android, advertisement_ios 이렇게 나눠서 구독하면 OS간 구분이 가능합니다.

그런데 언어로 구분은?

그럼 advertisement_android_kr, advertisement_android_en, ... 등등 엄청나게 경우의 수가 많아집니다.

거기에 마케팅 팀에서 구독자, 마지막 접속일로도 구분해야 한다고 하면?

여기부턴 단순히 경우의 수가 아니라 불가능의 영역에 가까워집니다.

 

따라서 이 방법은 진짜 단순하게 광고 ON, OFF만 있고 우리는 따로 언어나 OS나 프리미엄 여부 등으로는 푸쉬 광고를 따로 두지 않아! 하는 스펙이 있는 경우에는 좋지만, 그게 아니라면 사용할 수 없는 방법입니다.

물론 뭐 ON/OFF에다가 OS, 언어까지만 넣는다면 뭐 가능하긴 하지만... 그 이상은 무리입니다.

 

4. 사용자 속성

사진은 제 작은 습작 앱이라서 사용자 속성이 비활성화 되어있는데, 암튼 실제 프로젝트에선 사용자 속성을 쓸 수도 있습니다.

firebaseAnalytics.setUserProperty("advertisement", "true")

사용자 속성은 이렇게 등록할 수 있습니다. 광고 켠 사람은 "true"로 끈 사람은 "false"로 등록하면 되겠죠. (뭐 아니면 그냥 "apple", "banana"로 등록 하시든가 맘대로...;;)

 

그리고 시간이 지나서(+ 사용자들의 모수가 쌓이고 나면)

Analytics의 Custom Definitions에서

범위를 사용자로 선택하면 사용자 속성에 advertisement라고 뜰 겁니다.

그렇게 해서 새 맞춤 측정 기준을 추가합니다.

 

그러고나면 클라우드 메시징에서 위 사진의 사용자 속성에 advertisement가 추가되어있을 겁니다.

사용자 속성을 지정한 다음에 푸쉬를 날리면 이제 광고를 허용한 사람들에게만 보낼 수 있는 겁니다.

 

그리고 사용자 속성은 애초에 사용자 세그먼트 탭에 있는 기능 중 하나이기 때문에,

언어, 최초 실행, 마지막 앱 참여, 잠재 사용자 등 GA로부터 생성된 유용한 모든 세그먼트를 같이 활용할 수도 있습니다.

 

따라서 "최근 3개월 이내 접속하지 않은 프리미엄 사용자들 중 한국인 중에서 광고 허용을 한 사람들만 푸쉬를 보내겠다"는 요구사항도 아주 손쉽게 처리 가능합니다.

 

하지만 이 방법도 문제가 있습니다.

  • 아까 얘기 했듯 사용자 속성이 콘솔에서 보이려면 모수가 쌓여야 합니다
  • 모수가 쌓여서 사용자 속성이 보여도 문제인 게, 한 사용자가 광고를 ON에서 OFF로 바꿔도 실시간으로 등록이 되질 않습니다. 몇 시간에서 길게는 며칠이 걸리기도 합니다. (OFF에서 ON으로 바꾸는 경우도 마찬가지)
  • 실시간은 포기해야합니다

저희 팀에서는 그래도 이 방법을 선택하였습니다.

실제로도 보면 일부 앱들은 광고를 꺼도 서버에 반영되기까지 시간이 걸릴 수 있다는 안내를 하고 있습니다. 아마 그 팀들도 이 방식을 쓰는 게 아닐까 싶습니다.

광고 여부 변경 통지도 서버 반영 됐을 때가 아니라 일단 사용자가 클릭했을 때 통지를 하되, 시간이 좀 걸릴 수 있다고 안내를 하면 되는 거 같습니다.

Comments