알림 시스템 구축하기(하) – 웹 푸시 알림을 통해 끊을 수 없는 서비스 만들기

안녕하세요! 프론트엔드 엔지니어로 근무 중인 레오입니다 😁


LINER 개발팀에 합류하고, 하이라이트 유틸리티 툴에서 커뮤니티로 진화하는 과도기에 함께하며 항상 다양한 challenge에 부딪히고, 이를 극복하여 성장하는 경험을 해왔습니다.
이 중 처음으로 제가 사이트 밖에 발을 내딛게 해준 웹 푸시 알림 시스템에 대한 이야기를 해보려 합니다.
(‘알림 시스템 구축하기(상)’ 편에 이어서 프론트엔드에서 푸시 알림을 구성하는 과정에 대한 글입니다.)

웹 푸시 알림이 어떤건가요? 🚀

라이너에서 구현한 웹 푸시 알림

혹시 웹 서핑을 하다가 facebook, youtube와 같은 사이트에서 위와 같은 알림을 보신적 있나요??
저는 다른 웹 사이트를 보고 있거나, 다른 작업을 하고 있을 때 저런 알림이 오면 종종 눌러봤던 기억이 있는데요,
웹 푸시 알림 브라우저를 이용해 사이트 접속 여부 상관없이, 웹 푸시 알림을 보내는 것으로 강력한 마케팅 툴로 급 부상하고 있습니다.

LINER에서는 이런 웹 푸시 알림을 이용해 강력한 소셜 커뮤니티를 구성하고 있습니다.
하이라이트를 기반으로 커뮤니티를 구성함에 따라 좋아요, 유저 맨션 등 다양한 푸시 알림들이 실시간으로 유저에게 전송되며 커뮤니티 리텐션의 중요한 역할을 하고 있습니다.

프론트엔드에서 어떤 방식으로 웹 푸시 알림을 만드나요?? 🤔

프론트엔드에서 웹 푸시 알림을 구현할 때는 notificaion api, Service Worker 를 이용해서 구현하게 됩니다.
notification api는 웹 브라우저에서 푸시 알림을 보내고, 권한을 받기 위해 사용되고,
Service Worker는 백그라운드에서 푸시 알림이 작동할 수 있도록 하는 역할을 합니다.
LINER에서는 백엔드에서 사용중인 FCM을 사용하기 위해 공식문서를 참고하여 firebase (FCM서버와 통신을 위해 사용) 라이브러리를 이용해 프론트에서 웹 푸시 개발을 진행했습니다.

웹 푸시 알림을 단순하게 바라보면 서버에서 보내주는 값을 보여주기만 하면 되는 것처럼 보이지만,
유저가 기준이 되는 것이 아니라, 디바이스와 브라우저를 기준으로 하기 때문에 생각보다 신경 쓸 부분이 많답니다. 😅

웹 푸시 알림을 개발하며 제가 풀었던 방법이 정답은 아니지만, 하나의 방법으로써 재미있게 봐주시면 감사드리겠습니다.

Service Worker를 통한 백그라운드 동작 관리 🎒

웹 푸시는 크게 포그라운드(foreground) 상태와 백그라운드(background) 상태로 나누어 관리가 됩니다.
포그라운드 상태는 사용자가 현재 웹페이지(getliner.com)를 보고 있을 때를 의미하고,
백그라운드 상태는 사용자가 현재 웹페이지(getliner.com)를 보고 있지 않을 때를 의미합니다.
일반적으로 웹 개발을 할 때는 포그라운드 상태에 있는 사용자만을 고려하지만,
웹 푸시는 백그라운드 상태에 있는 사용자 또한 고려해야 하고, 이를 위해 브라우저 백그라운드에서 동작하는
Service Worker를 다루게 되었습니다.

이 이미지는 대체 속성이 비어있습니다. 그 파일 이름은 image-1024x546.jpg입니다
getliner.com 도메인에 속해있는 포그라운드 상태
이 이미지는 대체 속성이 비어있습니다. 그 파일 이름은 image-1-1024x546.jpg입니다
getliner.com 도메인을 벗어난 백그라운드 상태


또한 유저의 로그인을 분기점으로 아래의 과정을 거치게 되었습니다.

1. Service Worker를 등록
2. Service Wokrer 등록한 후 반환된 디바이스 토큰 정보를 받아 서버에 등록
이 후 성공적으로 푸시 알림이 오는 것을 확인할 수 있었고, 여기까진 쉽게 푸시 알림 시스템을 구축했다고 생각했습니다.
Service Worker를 통한 웹 푸시 알림 시스템의 기준이 ‘사용자‘가 아닌 ‘브라우저‘라는 사실을 알기 전 까지는 말이죠.

등록된 Service Worker

브라우저 기준의 푸시 시스템 💻

일반적으로 웹 프론트엔드 개발할 때 대부분의 동작은 쿠키와 토큰을 통해 이루어지게 되고, 그 쿠키와 토큰은 로그아웃되는 시점에서 초기화되기 때문에 프론트엔드 개발에서 쿠키와 토큰 없이 어떠한 기능을 구현하는 일은 적습니다.

웹 푸시 알림 시스템을 구축한 후 웹 푸시를 테스트하는 과정에서 한가지 이슈를 발견하게 되는데요, 바로 로그아웃한 후에도, 이전 계정에 대한 정보로 푸시 알림이 오는 현상을 발견하게 됩니다

A계정에 등록된 Service Worker
B계정에 등록된 Service Worker, A계정에 등록된 Service Worker와 동일한 모습이다.

새 계정으로 로그인하면, A 계정과 B 계정이 다른 Service Worker를 갖게 될 것이라는 착각에서 시작된 이슈였죠.
서버 쪽에서는 디바이스 토큰을 대상으로 푸시 알림을 전송하기 때문에,
기존 Service Worker가 남아있던 B 계정에서도, A 계정에 대한 푸시 알림이 오는 것입니다.

이 사실을 깨닫고, 관점을 사용자에서 브라우저로 변경하여 바라보게 됩니다.
한 유저도 여러 개의 브라우저, 여러 개의 기기를 통해 푸시 서비스를 등록할 수 있고, 등록된 토큰 값은 반드시 해당 유저와 매핑되어야 합니다.

때문에 로그아웃이 되는 시점을 기준으로 브라우저에 설치되어 있던 Service Worker를 삭제하고,
새로운 로그인 때마다 Service Worker를 새로 설치하며 이슈를 해결할 수 있었습니다.

Notification Permission 관리

웹 푸시 알림을 유저에게 발송하기 위해서는 반드시 선행되어야 하는 작업이 있는데요, 바로 유저에게 Notification Permission 권한을 승인받는 것입니다.
웹 브라우저에서는 도메인별로 웹 푸시 알림에 대한 권한을 설정할 수 있는데요, 실제로 이 권한을 허용한 유저에게만 푸시 알림을 발송할 수 있습니다.

브라우저 알림 권한

하지만 이러한 알림 권한 값을 유저가 실제로 인지하고 설정하기에는 어려움이 있고, 코드로 마음대로 조작 가능한 값도 아닙니다.
때문에 LINER에서는 이를 UX와 getliner.com 내에서 별도의 알림 on/off 기능을 제공하여, 유저가 알림 시스템을 인지하고, 보다 쉽게 알림 권한을 변경할 수 있도록 도왔습니다.

UX를 통한 알림 권한 허용률 증대

LINER에서 푸시 알림 시스템은 커뮤니티 리텐션에 중요한 장치이기 때문에 유저의 알림 권한 허용률을 최대한 높이 끌어올리는 것이 중요했는데요, 다양한 UX로 유저에게 알림 권한 설정을 유도하며 이 문제를 해결했습니다.

getliner.com에서 유저의 알림 권한을 얻어, 권한이 denied 상태이면 다양한 UI를 보여주며 유저의 알림 활성화를 유도했습니다.

알림 권한 허용 증대 UX

또 세 개의 플랫폼 (웹, 앱, 브라우저 확장 프로그램) 에서 서비스하는 LINER의 장점을 살려 브라우저 확장 프로그램(BE)을 통한 홍보 모달로
알림 권한 허용률을 증대시킬 수 있었습니다.

BE를 통한 알림 권한 허용 홍보 모달

서비스 자체 알림 on/off 설정

앞서 말씀드렸듯이 유저의 알림 권한은 개발자가 마음대로 바꿀 수 있는 영역이 아닙니다.
또한 대부분의 유저는 도메인 별로 알림 권한을 설정할 수 있다는 사실을 인지하기 어렵습니다.
때문에 웹 푸시 지원하는 다양한 서비스에서는 자체적인 알림 on/off 기능을 통해 유저에게 알림 허용 여부를 UX 적으로 더 설정하기 쉽게 풀어줍니다.
LINER에서도 이러한 문제를 풀기 위해 두 가지 방법을 생각했는데요,

  1. on/off에 따라 Service Worker 등록/제거한다.
  2. on/off에 따라 브라우저별로 유저의 디바이스 토큰을 등록/삭제한다.

첫 번째 방법을 통해 해결할 경우 백엔드의 리소스를 절약할 수 있지만, Service Worker를 설치/제거하는 메모리 비용이 크다고 판단했습니다. 글로벌 서비스인 LINER에서는 이런 비용 하나하나가 특정 나라에선 치명적일 수 있기 때문이죠.

따라서 두 번째 방법을 통해 브라우저별로 설치된 디바이스 토큰을 등록/삭제했고, 알림 on/off 토글을 통해 유저가 손쉽게 LINER에서의 알림 권한 설정을 할 수 있게 되었습니다.

알림 권한 설정 뷰

푸시 알림을 마치며…

LINER에 와서 많은 프로젝트를 진행하며 어느 하나 쉽게 진행되었던 프로젝트는 없었던 것 같습니다.
언제나 각자의 시점에 맞는 사건과 병목이 있었고, 이번 푸시는 유독 그 벽이 높아 보였던 프로젝트였습니다.

처음 해보는 영역에 들어가며 매일 함께 프로젝트에 참여하는 팀원과 페어 프로그래밍 룸에서 의논하며, 문제를 하나하나 해결했습니다. 그리고 그 벽이 점차 허물어지는 걸 눈으로 확인하며 많은 희열을 느낄 수 있었습니다.
지금도 때때로 vsCode옆에 제가 만든 푸시 알림이 올 때면 흐뭇한 미소를 짓곤 합니다. 😊
힘들었던 만큼 보람찼고, LINER에 있었기에 도전할 수 있었던 것 같습니다.

아직 LINER의 푸시 알림 시스템은 갈 길이 많이 남았습니다.
항상 시작은 두렵고, 앞으로 갈 길을 생각하면 막막한게 사실이지만, 중간중간 뒤를 돌아볼 때마다 느낄 수 있는 감정이 너무나 소중하기에 설레기도 합니다.

정이 많이 갔던 프로젝트였던 만큼, 짧은 문단으로 표현하기에는 아쉬움이 남는 것 같습니다.
이제 시작이고, LINER에서 제가 도달해야 할 목적지가 확실히 보이기에, 다음번 저의 블로그에서는, 목적지 근처에 도달한 상태로 인사드리겠습니다.
다음번 저의 이야기도 많은 관심 부탁드립니다.😁

그리고 혹시! 저와 함께 LINER에서 날아가는 경험을 하고 싶으신 분이 계신다면 자신의 이야기를 함께 남겨보는 건 어떨까요?? LINER는 언제나 열려있습니다!

이 이미지는 대체 속성이 비어있습니다. 그 파일 이름은 Untitled-1024x683.jpg입니다

저희는 실패를 두려워하지 않고, 하루하루 빠르게 나아가고 있습니다.
누구보다 성장을 즐기는 팀원들과 함께, 빠르게 날아가는 LINER와 함께 인생에서 가장 ‘하이라이트’한 경험을 함께해요!

👉 라이너 채용 페이지 바로가기

ㅁㄴㅇㅇㄴㅁㅇㅁㄴㅁㅇㄴㅇㄴㅁ