여기까지는 접속해 있는 사용자에게 밀어 주는 이야기였습니다. 그런데 동시 접속 20만 은 지금 붙어 있는 수일 뿐입니다. 전체 사용자는 그보다 훨씬 많고, 대부분은 지금 앱을 보고 있지 않습니다.
| 상태 | 무엇이 필요한가 |
|---|---|
| 접속 중 | 게이트웨이로 밀어 준다. 앞 단계에서 다뤘다 |
| 앱을 내려 둔 상태 | 푸시 알림. 그리고 다시 열 때 놓친 것 따라잡기 |
| 오래 접속하지 않음 | 알림도 쌓이지 않게. 열 때 조회로 충분하다 |
안 읽은 것을 저장하지 말고 계산한다
가장 먼저 떠오르는 방법이 사람마다 미확인 목록을 만드는 것입니다. 이 방법은 큰 채널에서 무너집니다.
최대 5만 명 채널에 공지 하나를 올리면 미확인 행 5만 명 개가 생깁니다. 대신 사람마다 채널마다 마지막 읽은 번호 하나만 두면 안 읽은 개수는 뺄셈으로 나옵니다.
안 읽은 개수 = 채널의 최신 번호 - 내가 읽은 번호
앞 단계에서 채널마다 증가하는 번호를 만들어 둔 것이 여기서 두 번째로 쓰입니다. 순서를 위해 도입한 번호가 미확인 계산까지 해결합니다.
다시 열었을 때 따라잡기
앱을 다시 열면 클라이언트가 마지막으로 받은 번호를 보냅니다. 서버는 그 뒤의 것을 보냅니다.
문제는 오래 접속하지 않은 경우입니다. 놓친 것이 수천 건이면 그것을 다 밀어 주는 것은 낭비입니다. 화면에는 최근 50건만 보이기 때문입니다.
| 놓친 양 | 어떻게 |
|---|---|
| 적을 때 | 그 뒤의 것을 그대로 보낸다 |
| 많을 때 | 개수를 제한해 보내고 나머지는 지난 대화 조회로 넘긴다 |
밀어 주기와 조회는 경쟁 관계가 아닙니다. 실시간은 밀어 주기가, 따라잡기는 조회가 맡는 편이 양쪽 모두 단순해집니다.
푸시 알림은 도착을 보장하지 않는다
푸시는 다른 회사의 서비스를 거쳐 갑니다. 지연될 수 있고 사라질 수도 있습니다. 그래서 푸시를 전달 수단으로 믿지 않습니다. 푸시는 "열어 보라" 는 신호이고, 실제 내용은 앱이 열린 뒤 서버에서 다시 가져옵니다.
| 원칙 | 이유 |
|---|---|
| 푸시에 내용을 다 담지 않는다 | 도착이 보장되지 않고 잠금 화면에 남는다 |
| 알림은 채널 단위로 묶는다 | 활발한 채널이 알림 수십 개를 만든다 |
| 안 읽은 수는 서버가 계산해 함께 보낸다 | 클라이언트가 세면 놓친 만큼 어긋난다 |
접속 중인지 보고 보내면 그 사이에 바뀐다
접속 중이면 푸시를 보내지 않는 것이 자연스러워 보입니다. 그런데 확인하는 순간과 보내는 순간 사이에 상태가 바뀝니다. 사용자가 방금 앱을 내렸다면 아무 알림도 받지 못합니다.
그래서 푸시를 조금 미뤄 둡니다. 몇 초 안에 그 사용자가 읽었다는 신호가 오면 취소하고, 오지 않으면 보냅니다. 상태를 물어보는 대신 결과를 기다리는 쪽이 확실합니다.
조용하게 만드는 것도 요구사항이다
알림을 끈 채널, 방해 금지 시간, 언급된 경우만 받기 같은 설정이 없으면 사용자는 앱을 지웁니다. 이 판단은 보내는 순간에 필요하므로 알림 설정은 자주 읽는 데이터입니다. 캐시에 두고 전달 경로에서 바로 확인합니다.