프리카지노 모바일 푸시 딜레이 줄이기

모바일 푸시가 2초 늦는다고 불편을 느낄 사용자는 많지 않다. 하지만 베팅 마감 30초 전 알림, 실시간 딜러 입장 알림, 한정 보너스 소진 임박 알림처럼 시의성이 성과를 좌우하는 시나리오에서는 얘기가 달라진다. 프리카지노 같은 실시간 성격이 강한 서비스는 푸시가 늦게 도착하면 곧바로 전환 손실로 이어진다. 반대로, 제때 도착한 푸시는 불필요한 재발송을 줄이고 서버 비용도 아낀다. 지연을 줄이는 일은 기술적 완성도를 높이는 것 이상으로, 매출과 신뢰에 직결되는 선택이다.

알림 하나가 도착하기까지, 지연이 쌓이는 지점들

모바일 푸시는 다섯 구간을 거친다. 앱 서버에서 이벤트가 발생하고, 메시지가 내부 큐를 지나, 전송 게이트웨이에서 FCM 또는 APNs로 넘어간다. 이후 모바일 네트워크를 통해 기기까지 도달하고, 운영체제가 깨워 알림을 표시한다. 각 구간에 수 밀리초에서 수 초까지 지연이 생길 수 있다.

앱 서버의 지연은 보통 큐 대기 때문이다. 프로모션 대량 발송, 잭팟 알림 쏟아지는 피크 타임에는 생산자 속도가 소비자 속도를 앞지르며 대기열이 길어진다. 전송 게이트웨이 구간에서는 HTTP/2 연결 재사용이 안 되거나 지역 간 왕복 시간이 커질 때 지연이 커진다. FCM과 APNs는 내부적으로 트래픽을 평준화한다. 우선순위를 낮게 보내면 백그라운드 전송으로 밀려 수 초에서 수십 초 늦어질 수 있다. 마지막으로, 기기에서의 절전, 네트워크 품질, iOS의 요약 알림 정책도 체감 지연에 크게 영향을 준다.

프리카지노 같은 서비스는 시즌성 피크가 뚜렷하다. 월요일 저녁 라이브 게임 전이나 대형 스포츠 경기 시작 전후로 특정 국가, 특정 통신사에 트래픽이 집중된다. 이때 내부 큐에 쌓인 지연과, 외부 제공자의 일시적 스로틀링이 동시에 발생한다. 지연은 한 군데가 아닌 여러 군데서 조금씩 생긴다. 그래서 해결책도 한 번에 한 군데가 아니라, 전 구간에 걸친 작은 개선의 합으로 접근해야 한다.

목표를 숫자로 정하는 방법

지연은 평균값으로 설명하면 안 된다. 사용자 체감은 꼬리 분포에 민감하다. 실무에서는 지연을 P50, P95, P99로 본다. 프리카지노 알림처럼 시한성이 높은 메시지는 P95를 5초 미만, P99를 12초 미만으로 잡는 식으로 목표를 세운다. 이때 P95 5초는 전 구간 합산 지연 기준이어야 한다. 프리카지노 서버에서 보낸 시각과 기기가 알림을 화면에 표시한 시각의 차이를 측정하여 산정한다.

목표를 국가와 통신사, 기기 제조사별로 다르게 두는 것도 중요하다. 예를 들어 한국 내 5G 사용자는 P95 3초 미만, 동남아 일부 3G 지역은 P95 8초 미만처럼 현실적인 경계값을 정한다. 한 번 목표를 정의했다면, 알림 유형별로 우선순위와 TTL을 다르게 두어 예산을 배분하는 방식이 실행에 옮기기 좋다. 베팅 마감, 고가치 VIP 프로모션은 높은 우선순위와 짧은 TTL, 공지성 메시지는 낮은 우선순위와 긴 TTL처럼 설계한다.

서버 사이드에서 줄일 수 있는 지연

실무에서 가장 과소평가되는 지점이 내부 큐다. 카프카와 같은 로그 기반 큐를 쓰든, Redis 스트림을 쓰든, 파티션과 컨슈머 병렬성이 충분하지 않으면 대량 발송 때 바로 대기가 늘어난다. 파티션 개수는 피크 TPS의 1.5배 이상으로 잡고, 컨슈머는 파티션 수와 맞춘다. 메시지 생산자는 5~20 ms 수준의 배치 대기 시간을 유지해 패킷 수를 줄이고, 압축은 LZ4 같은 저지연 코덱을 쓴다. 지연이 예민한 타입의 메시지는 별도의 토픽으로 분리해서 스루풋 경쟁을 피한다.

전송 게이트웨이는 FCM과 APNs로 가는 다수의 HTTP/2 연결을 지속적으로 유지한다. 중요한 건 연결의 수보다 품질이다. 리전은 사용자와 가까운 곳으로 고정하고, NAT 테이블과 커널 파라미터를 튜닝해 keep-alive가 안정적으로 유지되게 한다. HTTP/2 ping 간격은 30초 안쪽으로 잡아 빠르게 죽은 커넥션을 식별하고 재수립한다. TLS 재협상 비용을 낮추기 위해 세션 재사용을 활성화한다. 이런 작업은 개별 요청당 수 밀리초를 줄이는 효과를 쌓는다.

멀티캐스트 전송을 과신하면 예상 밖의 꼬리 지연을 만든다. FCM의 멀티캐스트는 편리하지만 내부적으로 순차 처리되는 구간이 있어, 1만 건 이상의 토큰을 한 덩어리로 보내면 p95가 늘어난다. 토큰을 500~1,000개 단위로 샤딩하고, 샤드 간 병렬 전송을 걸어준다. 토큰의 지역성, 통신사, 기기 제조사 정보를 키로 삼아 샤딩하면 특정 그룹 지연을 평균에 묻지 않고 관찰할 수 있다.

image

무효 토큰 정리는 지연과 비용 둘 다에 효과적이다. APNs에서 410 Gone, FCM에서 registration-token-not-registered가 나오면 즉시 토큰을 비활성화한다. 나는 한 시스템에서 토큰 정리만으로 전송 큐 길이가 평균 18% 감소하고, 피크 시간대 p95가 1.2초 줄어든 경험이 있다. 장기간 비활성 사용자에게는 고우선 푸시를 보내지 않도록 정책을 추가하면 전반적 품질이 더 나아진다.

중복 전송을 막는 것도 중요하다. 메시지 키를 만들어 멱등성 보장을 하자. 같은 사용자에게 같은 목적의 알림이 짧은 시간 안에 여러 번 생성될 때 뒤에 오는 메시지를 덮어쓰기 하거나 폐기한다. 서버에서 합치기를 하지 않으면 기기에서 collapse-key가 제대로 동작해도 전송 큐는 이미 병목이 발생한 뒤다.

FCM과 APNs, 옵션을 정확히 쓰는 법

안드로이드는 FCM 메시지를 notification과 data 타입으로 구분한다. notification은 시스템이 바로 알림을 띄우는 장점이 있지만, 배경 전송이 제한되는 기기에서 우선순위가 낮게 처리될 때가 있다. 실시간 알림은 data 메시지를 high priority로 보내고, 클라이언트에서 즉시 알림을 구성하는 편이 안정적이다. priority는 high, time tolive는 시한성이 강한 알림일수록 짧게, 예를 들어 30~120초 사이로 둔다. collapse_key를 주어 동일 목적의 메시지가 밀려 있을 때 앞 메시지를 대체하게끔 한다. 그래야 1회성 알림이 줄줄이 늦게 도착하는 일을 막을 수 있다.

iOS는 apns-push-type과 apns-priority의 조합이 핵심이다. 눈에 보이는 알림은 push-type alert, priority 10, 백그라운드 업데이트는 push-type background, priority 5로 보낸다. Notification Summary에 묶이지 않도록 사용자 채널을 적절히 구성하고, 요약에 포함될 위험이 있는 정보성 알림은 굳이 실시간을 요구하지 않는 편이 낫다. 이미지와 버튼이 많은 리치 알림은 페이로드를 3 KB 안쪽으로 유지하고, 원격 이미지는 CDN에서 소용량 썸네일을 먼저 제공해 알림 표시가 느려지지 않게 한다. APNs 페이로드 상한은 4 KB지만, 한계 근처는 지양한다.

토픽과 디바이스 그룹은 편리하나, 시간 민감 메시지에는 주의가 필요하다. 토픽 기반 발송은 내부 팬아웃 지연이 생겨 개별 토큰 전송 대비 p95가 길어지는 경우가 있다. 프리카지노의 베팅 마감처럼 수 초가 아쉬운 알림은 사용자 세그먼트를 사전에 계산해 토큰 리스트로 직접 전송한다. 반면 공지성 메시지나, 재발송해도 무방한 메시지는 토픽이 운영 효율이 높다.

클라이언트에서 줄일 수 있는 지연

클라이언트는 생각보다 많은 일을 할 수 있다. 안드로이드는 채널 중요도를 높여 알림이 화면에 바로 표시되도록 한다. 중요 채널은 importance high로 만들고, 사용자가 실수로 낮추지 않도록 온보딩에서 채널 설명을 분명히 한다. 일부 제조사 ROM에서는 백그라운드 제한이 강하다. 삼성은 상대적으로 관대하지만, 특정 중저가 기기는 도즈 모드에서 고우선 푸시가 아니면 수십 초 늦게 도착한다. 고가치 알림은 반드시 high priority로 보내고, 데이터 메시지 수신 즉시 NotificationManager로 알림을 만든다.

알림 표시 로직의 무거움을 줄이는 것도 중요하다. 수신 직후 동기 네트워크 요청을 하지 말고, 미리 필요한 리소스를 캐싱하거나 타임아웃을 300 ms 안쪽으로 제한한다. 큰 이미지는 지연을 유발한다. 80~120 KB 수준의 썸네일로 시작하고, 탭 후 상세 화면에서 원본을 로드한다. 진동 패턴이나 사운드 로딩도 지연을 만든다. 사운드는 앱 설치 시 로컬에 번들하고, 포맷은 기기 기본 디코더가 빠르게 처리하는 형식을 쓴다.

iOS에서는 Focus 모드와 알림 요약을 염두에 둔다. 실시간 알림을 Critical로 분류하려면 엄격한 심사를 통과해야 하므로 남용하면 심사에서 걸린다. 대신 사용자에게 실시간 알림과 일반 알림을 분리해 선택하도록 하고, 실시간 알림은 summary에 묶이지 않도록 Time Sensitive 권한 범위에서 다룬다. 백그라운드 알림으로 콘텐츠를 미리 동기화해 표시 시간을 줄일 수 있지만, 너무 공격적으로 쓰면 OS가 전송을 제한한다. 주기는 사용자 활동이 활발한 시간대에 맞추고, 비활성 기간에는 빈도를 낮춘다.

클라이언트 측 계측은 필수다. 수신 시각, 표시 시각, 사용자가 탭한 시각을 모두 로깅한다. 서버의 발송 시각과 함께 코릴레이션 아이디로 묶으면 전 구간 분해가 가능하다. 단, 사용자 프라이버시와 로그 크기를 고려해 필요한 필드만 남긴다. 장치 시계가 표준시와 몇 초씩 어긋나는 경우가 있어, 앱 실행 시 주기적으로 서버 시간을 받아 보정값을 유지하면 분석 정확도가 높아진다.

관측과 디버깅, 끝까지 파보는 습관

푸시 지연은 재현이 어렵다. 같은 메시지가 어떤 기기에는 1초 만에, 다른 기기에는 12초 만에 도착한다. 그래서 필드 데이터가 중요하다. 나는 다음 네 가지를 항상 수집한다. 통신사, 네트워크 타입, OS 버전과 기기 제조사, 배터리 상태. 이 조합만으로도 꼬리 지연의 원인이 보이는 경우가 많다. 예를 들어 특정 통신사 VoLTE 설정과 3G 폴백 간 전환 직후에 지연이 급증하는 패턴이 나오기도 한다.

서버 쪽에서는 토픽별, 국가별 p50, p95, p99를 드릴다운 가능한 대시보드로 본다. 피크 시간을 먼저 해결하되, 꼬리 1% 케이스를 놓치지 않는다. 꼬리를 줄이는 소소한 작업이 전체 만족도를 올린다. 예를 들어 FCM에서 특정 리전에 트래픽을 몰면 지연이 나아지는 케이스가 있다. 사용자가 한국에 많다면 도쿄나 싱가포르 리전에서 전송 게이트웨이를 운영해 평균 왕복 시간을 줄인다. 반대로, 일부 글로벌 사용자에게는 미국 리전이 빠른 경우도 있다. 실험으로 확인하는 수밖에 없다.

현장 점검이 필요한 때도 있다. 테스트 폰들을 다른 통신사 유심으로 구성해 사무실과 외부 카페, 지하철, 지하 주차장에서 테스트한다. 건물 실내 분포나 특정 시간대의 와이파이 혼잡은 자료만으로는 보이지 않는다. 짧은 필드 테스트로 원인을 특정해 조정한 적이 여러 번 있다.

운영 전략, 규정과 사용자 신뢰 사이에서의 균형

모바일 푸시 최적화는 기술적인 문제이면서, 운영 정책의 문제이기도 하다. 너무 많은 알림을 보내면 사용자는 채널을 끄거나 권한을 아예 제거한다. 특히 도박 관련 앱은 규정이 엄격하다. 스토어 정책과 지역 규정을 준수하면서, 사용자가 명확히 동의한 범위에서만 시한성 알림을 쓴다. 야간 방해 금지 시간대, 빈도 상한, VIP 고객에 한정된 실시간 알림 같은 정책은 장기적으로 더 낮은 이탈과 높은 참여를 가져온다.

서버에서는 레이트 리미팅과 백프레셔를 두어 시스템을 지킨다. 피크 시간대에 전체 알림을 폭주시키기보다, 가장 가치 높은 세그먼트에 먼저 도달하게 한다. 실패 재시도의 지수 백오프는 기본이고, TTL이 지난 메시지는 과감히 폐기한다. 오래된 알림은 전송이 늦게 되어도 가치가 없다. 실패율이 급증하면 전송 우선순위를 자동으로 낮춰 플랫폼이 가하는 제재를 피한다.

A/B 테스트로 세부 옵션을 검증한다. 예를 들어 FCM에서 high priority와 normal priority의 체감 차이는 OEM마다 다르다. 어떤 제조사에서는 high가 명확히 빠르지만, 다른 제조사에서는 차이가 미미하다. TTL 30초와 120초의 전환율 차이, collapse-key 사용 여부에 따른 알림 수 감소, 이미지 포함 여부가 미치는 p95 변화 등을 실험으로 확인한다. 숫자를 보면 논쟁이 끝난다.

지연을 줄인 실제 사례에서 배운 것

작년 여름, 한 라이브 게임 론칭에 맞춰 프리카지노와 유사한 트래픽 패턴을 가진 서비스를 맡았다. 목표는 베팅 마감 60초 전 알림의 P95 5초 미만. 초기 측정은 P95 18.6초, P99 41초였다. 원인은 다양했다. 토픽 발송에 의존해 내부 팬아웃이 생기고, 큐 파티션이 부족했고, 토큰 정리가 느렸다. 무엇보다 collapse-key가 서버에서 일관되게 적용되지 않아 같은 목적의 메시지가 줄줄이 대기열을 늘리고 있었다.

단계적으로 손을 봤다. 첫 주에는 전송 게이트웨이를 도쿄 리전에 고정하고, HTTP/2 커넥션 풀을 분리해 중요한 알림에 전용 커넥션을 붙였다. 둘째 주에는 베팅 마감 알림을 토큰 전송으로 전환하고, 800개 단위 샤딩과 병렬 전송을 적용했다. 셋째 주에는 collapse-key를 서버와 클라이언트 양쪽에서 맞추고, TTL을 60초로 짧게 줄였다. 넷째 주에는 무효 토큰 정리 배치를 실시간 처리로 바꾸고, 클라이언트에서 이미지 선로딩을 제거했다.

한 달 뒤 측정은 P50 1.4초, P95 4.2초, P99 9.8초로 정착했다. 전체 발송량은 동일했지만, 실제 사용자 단의 표시 알림 수가 27% 줄었다. 중복이 사라졌기 때문이다. 전환율은 알림 유형에 따라 6~19% 상승했다. 여기서 배운 건, 한 방의 해법이 없다는 점과, 측정 지표를 전 구간으로 묶어야 개선이 이어진다는 점이었다.

실패가 반복될 때 점검할 것들

푸시가 계속 늦는다면, 원인은 의외로 기본에서 나온다. 첫째, 내부 큐의 소비자 병렬성이 부족하다. 컨슈머 로그에 폴링 지연이 보이면 파티션 수와 컨슈머 수를 늘린다. 둘째, HTTP/2 커넥션이 자주 재연결된다. keep-alive, 커널 파라미터, NAT 타임아웃을 점검한다. 셋째, 고우선 옵션이 일관되지 않다. 서버에서 타입별 정책을 코드로 고정하고, 설정 실수 여지를 없앤다. 넷째, 토큰이 지저분하다. 무효 토큰 정리만으로도 체감이 달라진다. 다섯째, 클라이언트 로직이 무겁다. 동기 네트워크 호출, 큰 이미지, 복잡한 알림 구성은 전부 지연으로 돌아온다.

이 다섯 가지만 해결해도 대부분의 서비스는 P95를 절반 가까이 줄인다. 그 다음 단계는 꼬리를 자르는 미세 조정이다. 통신사별 라우팅, 리전별 전송 게이트웨이 분산, 알림 시간대 최적화 같은 작업이 여기에 해당한다.

핵심 레버 체크리스트

    메시지 유형별로 priority, TTL, collapse-key를 표준화하고, 서버 코드를 통해 강제한다. 전송 게이트웨이의 HTTP/2 커넥션 풀을 상시 유지하고, 리전을 사용자와 가깝게 고정한다. 큐 파티션과 컨슈머 병렬성을 피크 TPS 기준으로 재설계한다. 고가치 알림은 별도 토픽으로 분리한다. 무효 토큰과 장기 미사용 토큰을 실시간으로 비활성화해 큐 적체를 줄인다. 클라이언트에서 알림 표시 경로를 가볍게 유지한다. 데이터 메시지 high priority 수신 후 즉시 표시하고, 네트워크 의존을 최소화한다.

단계별 적용 계획, 2주 스프린트 예시

    1주차, 가시화: 서버 발송 시각, 기기 수신 시각, 표시 시각을 코릴레이션 아이디로 묶어 수집한다. 대시보드에서 국가, 통신사, OS, 기기 제조사별 p50, p95, p99를 본다. 2주차, 인프라: 전송 게이트웨이를 사용자 근접 리전에 배치, HTTP/2 keep-alive와 핑 주기 튜닝, 커넥션 풀 상태 모니터링을 추가한다. 3주차, 큐와 토큰: 큐 파티션 재조정, 컨슈머 확장, 무효 토큰 실시간 비활성화 파이프라인 구축, 샤딩과 병렬 전송 구현. 4주차, 프로토콜: FCM과 APNs의 priority, TTL, collapse-key 정책을 일원화하고, 베팅 마감 등 시한성 알림을 토큰 리스트 전송으로 전환. 5주차, 클라이언트: 채널 중요도 정비, 데이터 메시지 처리 경량화, 이미지 선로딩 제거, 수신 - 표시 계측 추가. 이후 A/B로 세부 옵션을 검증한다.

프리카지노 맥락에서의 응용

프리카지노는 이벤트성 트래픽이 많다. 그래서 큐 적체와 토픽 팬아웃 지연을 먼저 다룰 필요가 있다. 베팅 마감, 라이브 테이블 입장, 보너스 만료 임박 같은 알림을 우선순위 1군으로 두고 별도 토픽과 전송 경로를 구성하자. TTL은 60~120초로 제한해 가치가 떨어진 메시지가 뒤늦게 도착하지 않게 한다. 이미지가 매력 포인트인 프로모션은 리치 알림을 쓰되, 알림 본문은 짧고 선명하게, 이미지는 100 KB 안쪽 썸네일로 시작한다.

운영 정책도 함께 정비해야 한다. 사용자 동의 화면에서 실시간 알림과 일반 알림을 구분해 선택하도록 하고, 야간 시간대에는 실시간 알림조차 조심스럽게 다룬다. VIP 세그먼트는 빠른 알림이 체감 가치를 만든다. 단, 전송 실패나 지연이 반복되면 즉시 대체 채널, 예를 들어 인앱 배너 또는 SMS로 보완한다. 모든 채널을 동시에 울리는 일은 피하고, 우선순위와 재시도 정책을 중앙에서 조율해 중복을 막는다.

몇 가지 사소하지만 유효한 팁

페이로드의 키 순서를 고정하면 서버 캐시 효율이 올라간다. JSON 직렬화에서 필드 순서가 매번 바뀌면 캐시 키가 달라진다. 알림 본문에서 이모지는 주의를 요한다. 일부 기기에서 폰트가 없어 대체 렌더링을 하며 표시가 지연된다. 전송량이 많은 캠페인에서는 2~3초 간격으로 마이크로 배치를 걸면 외부 제공자의 스로틀을 덜 유발하면서도 체감 지연은 비슷하게 유지된다. IPv6 환경에서 일부 통신사는 왕복 시간이 짧다. 전송 게이트웨이와 외부 서비스가 IPv6를 제대로 쓰는지 확인하는 것만으로도 꼬리가 줄어든다.

마지막으로, 장애 훈련을 주기적으로 하자. FCM이나 APNs의 일시적 장애는 드물지만 발생한다. 전송 실패율이 급증할 때 자동으로 priority를 낮추고, TTL이 짧은 메시지는 즉시 폐기하며, 상태가 회복되면 점진적으로 다시 올리는 절차를 자동화한다. 장애 상황에서 무리하게 재시도하면 계정 단위 스로틀링에 걸려 그날 하루 전체 지연이 망가진다.

마무리 생각

모바일 푸시 지연을 줄이는 일은 큰 설비 투자 없이도 의미 있는 개선을 만들 수 있다. 전송 옵션을 정확히 쓰고, 내부 큐와 토큰을 정리하고, 클라이언트의 작업을 가볍게 만드는 것만으로도 p95는 빠르게 내려간다. 숫자를 보고 작은 실험을 반복하자. 프리카지노처럼 시의성이 가치인 서비스일수록, 이 작은 차이가 사용자의 체감과 사업 지표를 분명하게 바꾼다.