앱 푸시 알림 서버 개발(1)
06 Dec 2021수작업의 반복
현재 회사에 들어와서 처음으로 마케팅팀과 프로모션을 준비하게 되었다. 이전에도 설과 추석에 진행해서 팀원들에게 물어보면서 준비할 수 있었다. 그 중에는 약 25만명 대상자에게 앱 푸시 알림을 보내는 것도 있었다. 팀원 중 한 분이 짠 파이썬 스크립트 파일이 있어 매번 앱 푸시를 보내게 되면 그 스크립트를 이용해온 상황이었다. csv 파일을 읽어서 사용자의 광고 수신, 앱 푸신 수신 여부를 확인하고 해당 대상자의 토큰을 FCM API로 보내게 되어 있었다.
9월 프로모션은 처음으로 진행하는거라 혹시나 실수할까봐 걱정이 많았고, 중간에 deep link 부분이 문제가 있어서 시간이 좀 걸렸지만, 마케팅팀의 의도대로 매출도 잘 나왔다. 올해 프로모션은 이렇게 끝인 줄 알았는데 10월이 되어서 또 프로모션을 하게 되었다. 스크립트 파일 자체를 돌리는 건 매우 간단한 일이지만 프로모션이 아니어도 다른 스쿼드에서도 종종 앱 푸시를 보내는 일이 있었고 매번 수동으로 작업을 하고 있었다. 이전부터 관리자 페이지에서 앱 푸시를 할 수 있게 작업할 수 있는 시간을 요청했다고 했지만, 다른 업무에 밀려서 하지 못했다가 이번에 내가 있는 스쿼드에서 맡아서 앱 푸시 알림 서버를 개발하게 되었다.
앱 푸시 알림 서버 개발 시작
앱 푸시 알림 서버도 그간 익숙하게 해온 API 작업이 있긴 하지만 메인은 그게 아니다. 대상자가 많은 앱 푸시 알림을 비동기로 하는 것이 목적이었는데 처음 해보는 거라서 조금은 막막하게 느껴지기도 했다. 개발 요구 사항은 대략적으로 아래와 같다.
1. 알림 발송을 추가할 수 있다
2. 알림 대상자를 여러 타입으로 추가할 수 있다
1. CSV 파일로 추가(사용자 ID, FCM token 포함 & 1개의 사용자 ID가 1개 이상의 FCM token을 가질 수 있음)
2. DB에서 대상자 추출(전체 사용자, 혹은 특정 조건에 해당하는 모든 사용자)
3. 전체 개수와 알림 상태별 개수를 알 수 있어야 한다
1. 상태값(대기, 진행중, 완료, 실패)
4. 대상자 수, 대상 토큰 개수, 실제 발송된 토큰 개수, 실제 발송 대상자 수를 알 수 있어야 한다
1. 한 명의 사용자 계정으로 1개 이상의 토큰이 등록될 수 있다
2. 실제 발송된 토큰 개수는 알림 대상 토큰 개수보다 작거나 같다.
먼저 모든 알림 내역의 개수나 상태별 개수는 SQL에서 count 함수를 써야하는데 데이터가 많아질수록 속도가 느려질 것을 우려해 Redis
를 그리고 비동기 작업을 위해 RabbitMQ
를 사용하기로 했다. 둘 다 공부할 때만 써본터라 새로운 기술을 써보게 돼서 설레었다.
너무 느리다
앱 푸시의 대상자의 범위는 특정 조건의 사용자부터 전체 사용자이며, 그 수는 최소 10만 정도가 될거라고 예상하고 있다. 그러므로 API를 호출하고 서버에서 바로 FCM API를 호출해서 푸시를 보내게 되면 클라이언트에서는 발송이 끝날 때까지 기다려야한다. 클라이언트에서는 앱 푸시 알림을 보낸다고 서버에 요청을 보내고 서버는 바로 응답하고, 앱 푸시는 Consumer에서 하는 것이 처음 설계한 구조였다. 그런데 대상자를 CSV로 등록할 때 응답 시간이 약 1분 정도가 걸렸다. 앱 푸시에 필요한 데이터를 퍼블리싱하고 푸시 알림을 보내지 않는데도 시간이 이렇게 오래 걸리는 이유가 뭘까? 구간을 찾기 위해서 중간 중간 time()
을 찍어서 찾아보았다.
가장 시간이 오래 걸리는 구간은 CSV에서 가져온 user_id를 앱 푸시 발송 대상자로 유효한지 휴면회원, 앱 푸시 수신 여부 등을 DB에서 다시 확인하는 부분이었다. 퍼블리싱을 한 후에, 하나의 컨슈머에서만 앱 푸시를 보내도록 했는데 중간에 하나의 퍼블리셔를 더 두고 시간이 오래 걸리는 DB 조회 작업을 한 후에 다시 퍼블리싱 하는 구조에 대해 고민해보았다. 내 의도대로 하자면 이 방법을 가장 나을 것 같았는데 왠지 모를 불안감에 확신이 들지 않았고 시니어 개발자분과 얘기하면서 이렇게 구조를 바꾸기로 했다.
이미 API단에 구현한 코드를 옮기는 거라서 크게 어려운 부분은 없었다. 코드 중간 중간에 로그를 추가해서 데이터가 잘 들어 오고 있는지, 어떤 작업을 하고 있는지 확인할 수 있도록 하고 테스트를 해보았다. 괜한 불안감이었다. 내가 원하던대로 요청을 보낸 후에 바로 응답이 오고 퍼블리셔가 user_id를 다 확인하고 마지막 컨슈머가 푸시를 보내는 것까지 다 확인이 됐다. 우선은 시간에 대한 고민은 해결되었다.