모두를 위한 알림 경험 만들기
안녕하세요! 당근 알림 경험팀에서 백엔드 엔지니어로 일하고 있는 데이(Daey)라고 해요. 알림 경험팀은 일반적인 플랫폼 조직이 아닌, 모든 유저의 알림 경험을 고민하는 서비스 조직이기도 해요. 알림 기능을 개발하다 보면 아래와 같은 말을 자주 듣곤 하는데요.
“알림은 그냥 보내달라는 대로 보내면 되는 거 아닌가요?”
네, 그냥 보내달라는 대로 보내면 되는 게 아니에요. 알림은 먼저 사용자에게 접근할 수 있는 강력한 수단이지만, 사용하기에 따라 긍정적 경험뿐만 아니라 부정적 경험도 줄 수 있는 양날의 검이에요. 따라서 알림 경험팀은 단순히 알림을 잘 보내기 위한 플랫폼만 만드는 게 아니라, 유저가 알림을 통해 어떤 경험을 얻어갈지도 치밀하게 고민하고 있어요.
그런데 알림 경험팀에서 생각하는 모든 유저에는 단순히 당근 앱 사용자만 포함되지 않아요. 알림을 발송하는 당근의 구성원들까지도 포함하죠. 이는 알림을 발송하는 당근 구성원들의 긍정적 알림 경험이 장기적으로 당근 앱 사용자들의 긍정적 알림 경험에 기여한다고 믿기 때문이에요.
이번 글에서는 알림을 받는 사용자뿐만 아니라 알림을 발송하는 당근 구성원들의 경험도 효과적으로 개선한 ‘알림 신호등 프로젝트’를 소개하려 해요. 사용자의 알림 경험을 개선하기 위한 모니터링 기준을 마련하고, 챙겨야 하는 알림들이 모니터링 결과와 함께 담당자를 직접 찾아가는 시스템을 개발한 프로젝트죠. 사용자의 경험을 개선하기 위한 알림 경험팀의 치열한 고민과 해결 방법을 공유해 드릴게요.
알림 경험팀이 발견한 문제 상황
저희 팀에서는 먼저 당근 앱 사용자들과 당근 구성원들의 알림 경험에 부정적인 영향을 주는 요소들을 면밀히 파악했어요. 크게 세 가지 문제점을 도출했는데요. 각 문제점이 당근 앱 사용자와 당근 구성원 각자에게 어떤 영향을 미치는지 구체적으로 설명해 드릴게요.
1. 방치된 알림
더 이상 발송하지 않는 알림이 발송 가능한 상태로 남아있는 경우를 생각해 보세요. 이렇게 방치된 알림들은 당근 사용자들의 알림 경험에 어떤 영향을 미칠까요? 예를 들어 22대 국회의원 선거 알림이 지금 발송된다면 어떨까요? 왜 이 알림이 지금 발송됐는지 의아해하며 부정적인 알림 경험이 쌓일 거예요.
이런 경우도 한번 생각해 봅시다. 최근 당근 알림함은 스레드 알림 형태로 변경되었는데요.
스레드 알림에는 알림들을 스레드의 형태로 묶어줄 스레드 제목이 필요해요. 예를 들어 사진 속 알림의 스레드 제목은 ‘동네생활’이고, 알림 내용은 ‘구미동 인기글 확인하실 daeung님 구해요’인 것처럼 말이에요. 그런데 만약 스레드 설정이 되어 있지 않은 알림이 스레드 알림함에 노출된다면 어떨까요? 일반 알림에는 이런 정보들이 입력되어 있지 않기 때문에, 이런 알림이 스레드 알림함에 노출된다면 알림 내용이나 제목이 누락될 수 있어요.
이런 상황을 방지하기 위해서는 당근 구성원들이 기존에 설정해 둔 알림들을 주기적으로 살펴봐야 해요. 불필요해진 알림을 제거하거나 내용 업데이트가 필요한 알림들을 수정해야 하죠. 그런데 현실적으로 다른 업무들을 살피다 보면 알림을 일일이 확인하는 작업을 놓치게 되어, 위에서 살펴본 상황들이 종종 발생하곤 해요.
2. 알림 오픈율 분석
오픈율은 매우 중요한 지표예요. 사용자들에게 해당 알림이 필요했는지 가장 명확하게 보여주기 때문이죠. 만약 사용자에게 필요한 알림이었다면 사용자들은 알림을 오픈해 내용을 확인했을 거예요. 반대로 필요하지 않았다면 굳이 알림을 오픈하지 않겠죠. 따라서 사용자의 알림 경험 향상을 위해선 오픈율이 낮은 알림의 원인을 파악하고 개선하는 작업이 매우 중요해요.
하지만 단일 알림의 오픈율만으로는 그 수치가 높은지 낮은지 판단하기가 어려워요. 예를 들어 한 사용자가 인테리어 업체에 댓글로 문의 사항을 남겼다고 가정해 볼까요? 거기에 답글이 달렸다는 알림이 뜬다면, 대부분의 사용자는 확인하는 즉시 곧바로 열어볼 거예요. 사용자가 궁금해하는 중요한 정보가 담겨 있으니까요. 본인 댓글에 대한 답글 알림은 상대적으로 오픈율이 높을 수밖에 없죠. 반면 할인 쿠폰을 사용해 보라는 등의 광고성 알림은 대체로 오픈율이 낮을 거예요.
알림 경험팀에서는 비슷한 발송 맥락을 가진 알림들을 묶어 알림 카테고리라는 정보를 제공하고 있어요. 카테고리가 동일한 알림들의 오픈율을 분석하면, 관리하고 있는 개별 알림의 오픈율이 높은지 낮은지를 알 수 있을 거예요. 하지만 여기에도 한계는 있어요. 당근의 개별 구성원들은 어떠한 방식으로 알림 카테고리가 구성되는지 그 맥락을 모두 알기 힘들기 때문이에요. 만약 알고 있다 하더라도 개별 구성원들이 각자 자신이 관리하는 오픈율을 분석하기 위해 다른 카테고리의 알림들까지도 확인하는 것은 매우 비효율적이죠.
3. 알림 피로도 관리
Facebook의 연구 결과에 따르면 알림 발송량을 줄이면 단기적으로는 관련 지표가 악화되지만, 장기적으로는 오히려 지표가 향상된다고 해요. 이는 사용자들의 알림 피로도 관리가 매우 중요하다는 것을 시사해요. 너무 많은 알림을 받게 되면 사용자들은 알림 자체에 피로감을 느끼게 될 거예요. 그렇게 되면 중요한 알림마저도 사용자에게 제대로 전달되지 않을 수 있어요.
따라서 알림 피로도를 파악하는 것이 중요해요. 알림 발송량과 알림 수신 거부량을 분석하면 사용자들의 알림 피로도를 가늠할 수 있어요. 알림 발송량이 지나치게 늘어나면 일반적으로 사용자들은 알림에 대한 거부감을 느끼게 되고, 그에 따라 수신 거부 처리가 증가할 것이기 때문이죠.
하지만 알림 발송량의 총량을 줄이는 것은 매우 어려운 일이에요. 자신이 발송하는 알림이 굳이 보낼 필요가 없다고 생각하는 당근 구성원이 몇 명이나 있을까요? 또한 알림의 발송량은 서비스의 성장에 의해 자연스럽게 증가할 수도 있는데, 기계적으로 발송량을 제한해서 서비스 성장을 방해할 수도 없는 노릇이고요.
알림 경험팀의 해결책
1. 모니터링 기준 마련
알림 경험팀에서는 각 문제에 대해 가장 먼저 다음과 같은 모니터링 기준을 마련했어요.
방치된 알림
아래와 같은 기준을 가지고 방치된 알림 모니터링을 수행하기로 결정했어요.
- 30일간 알림 발송이 없는 경우 → 방치된 알림으로 간주
- 30일 이상의 주기를 가지고 알림이 발송되는 경우 → 방치된 알림에서 제외
- 미래에 발송이 예약되어 있는 경우 → 방치된 알림에서 제외
기본적으로 30일간 알림 발송이 없는 경우를 방치된 알림으로 간주해요. 하지만 가계부 알림과 같이 꾸준히 사용하는 알림이지만, 발송 주기가 한 달을 넘는 경우가 있어요. 따라서 주기 발송이 설정되어 있거나 미래에 예약 발송이 설정되어 있는 경우는 방치된 알림에서 제외했어요.
알림 오픈율 분석
오픈율 모니터링의 경우 알림 카테고리별 권장 오픈율을 계산하여, 권장 오픈율보다 높은지 낮은지를 확인했어요. 이때 권장 오픈율은 해당 알림 카테고리에서 극단값을 제거하고 중간값을 선택했죠. 극단값을 제거한 이유는 때때로 테스트 발송이나 특수한 상황으로 인해 오픈율이 100% 또는 0%가 되는 경우가 있기 때문이에요. 이러한 극단값을 그대로 반영하면 실제 오픈율을 왜곡할 수 있어요. 또한 알림 오픈율의 분포가 정규분포를 따르지 않는 경우가 많은데요. 이 경우 평균값은 대표성이 떨어질 수 있기 때문에 중간값을 기준으로 삼았어요.
알림 피로도 관리
알림 피로도 관리를 위해 알림 발송량과 수신 거부량을 모니터링했어요. 단순히 알림 발송량을 기계적으로 줄이는 것은 상황에 따라 부작용을 일으킬 수 있어요. 따라서 이상치 탐지 기법을 우선적으로 도입하기로 했어요. 알림 발송량 추이나 수신 거부량 추이를 급격하게 벗어나는 경우를 모니터링하기로 한 거예요.
이상치 탐지에는 사분위 수 기반 기법을 적용했어요. 이는 권장 오픈율 분석과 마찬가지로, 극단값이 존재하고 정규분포를 따르지 않는 경우가 많기 때문이에요. 평균 및 표준편차 기반의 방식보다는 사분위 수 기반 방식이 더 적절할 것으로 판단했어요.
(통계적으로 이상치를 탐지하는 방법을 더 구체적으로 알고 싶은 분은 이 글을 참고하면 도움이 될 거예요.)
2. 당근 구성원을 찾아가는 모니터링
하지만 알림 경험을 효과적으로 개선하려면 모니터링 기준을 세우는 것만으로는 부족해요. 사용자의 긍정적인 알림 경험을 위해서는 당근 구성원의 관심과 노력 또한 필수적이에요. 예를 들어 30일간 알림 발송이 없어서 방치된 알림으로 간주하는 경우, 담당자가 해당 알림들을 확인하고 발송 불가능한 상태로 처리해야 해요. 또한 권장 오픈율보다 낮거나 알림 발송량 및 수신 거부량에 급격한 증가가 생기는 경우, 그 이유를 면밀히 분석하여 개선해 나가는 작업이 필요해요.
다시 말해 당근 구성원들은 알림 센터*의 기능과 관련된 여러 일들을 직접 일일이 챙겨야 하는 상황이었어요. 그런데 만약 스스로 챙기지 않아도, 해야 할 일들이 당근 구성원들을 찾아오게 만들 수 있다면 어떨까요? 모니터링 기준을 충족하지 못하는 알림들을 슬랙이나 알림 센터를 통해 알려준다거나 하면 말이에요. 위와 같은 문제 상황을 방지하면서, 당근 구성원들의 알림 경험 또한 개선할 수 있을 거예요. 그래서 저희 팀에서는 모니터링 결과를 당근 구성원들에게 자동으로 전달하는 모니터링 시스템인 ‘알림 신호등’을 개발하기 시작했어요.
- 알림 센터: 당근 구성원들이 알림 발송을 위해 사용하는 백오피스를 의미해요.
알림 신호등의 구조
알림 신호등의 구조는 다음과 같아요.
- 다양한 알림 관련 데이터를 이용해 모니터링을 수행해요.
- 모니터링 기준을 충족하지 못하는 경우 모니터링 결과를 저장하고 슬랙 알림을 발송해요.
- 알림 센터에서 모니터링 결과 조회 기능을 제공해요.
모니터링 기준을 손쉽게 확장할 수 있는 구조
좋은 알림 경험을 제공하기 위해서는 다양한 측면에서의 모니터링이 필요해요. 지금은 일정 기간 동안 알림이 발송되지 않는 경우, 알림 실험이 장기화되고 있는 경우, 알림 발송량이나 알림 수신 거부 추이에 변동이 생기는 경우에 대해서만 모니터링을 수행하고 있지만, 추후 새로운 기능이 추가되면 해당 기능에 대한 모니터링이 필요해질 수도 있죠.
따라서 이러한 요구사항을 충족시킬 수 있도록 확장성 있는 구조가 필요했어요. 이를 위해 모니터링 기준을 추상화된 인터페이스로 정의하고, 각 기준별 Checker를 구현하는 방식으로 설계했어요. 이를 통해 새로운 모니터링 기준이 추가되더라도 해당 Checker만 구현하면 되는 유연한 구조를 갖출 수 있었어요.
모니터링 기준을 정의할 때, 각 기준별로 충족 여부를 확인하는 로직을 추상화된 MonitoringChecker
인터페이스로 정의했어요.
type MonitoringChecker interface {
Check(<모니터링 대상 알림>) (bool, error)
}
Check
메서드를 이용해 주어진 알림 시나리오가 해당 모니터링 기준을 충족하는지 여부를 판단하고, 그 결과를 boolean 값으로 반환해요.
이를 통해 정의한 모니터링 기준들에 대해 각각의 Checker 를 구현했어요. 예를 들어 “30일 동안 알림 발송이 없다”는 기준에 대한 Checker는 다음과 같아요.
type NoNotificationsIn30DaysChecker struct {
// 필요한 의존성 주입
}
func (c *NoNotificationsIn30DaysChecker) Check(<모니터링 대상 알림>) (bool, error) {
// 30일 간 알림 발송 내역 조회
// 발송 내역이 없는 경우 true 반환
}
결과
그 결과, 이전 대비 발송 불가 처리된 알림의 비율이 약 130% 증가했어요. 불필요한 알림을 제외하고 사용자에게 보다 정돈된 알림 경험을 제공하게 된 거예요. 더 이상 발송돼서는 안 되는 알림들 때문에 사용자가 혼란을 겪는 일이 줄어들었어요.
앞으로의 과제
권장 오픈율과 알림 발송량, 수신 거부량 이상치 탐지의 경우 아직 기능을 활발히 테스트 중이에요. 어느 정도의 오픈율, 알림 발송량, 수신 거부량이 적절한 수준인지 논의를 마친 상태는 아니에요. 하지만 실험 결과를 꾸준히 확인하면서 선제적으로 기준치를 당근 구성원들에게 제시하고 있어요. 실험이 마무리되면 다시 한번 논의를 통해 건강한 알림 경험을 더 명확히 정의하고자 해요.
또한 알림 신호등을 도입한 게 처음이기 때문에 아직 구체적으로 개선할 부분들이 많은데요. 예를 들어 알림 발송량 이상치 탐지 방식에는 한계가 존재해요. 단순한 통계 기반 방식으로는 알림 발송량이 0으로 떨어지는 경우를 효과적으로 탐지하기가 어렵죠. 필요한 알림들이 발송되지 않는다는 측면에서는 중요한 지표일 수도 있지만, 알림 피로도에는 영향을 미치지 않기 때문이에요. 따라서 이러한 한계를 극복하기 위해 좀 더 고도화된 기법을 고민 중이에요. 시계열 분석 알고리즘이나 머신러닝 기법 등을 활용해 알림 모니터링의 정확성과 민감성을 높여보려고 해요.
당근 구성원들에게 슬랙 메시지나 알림 센터를 통해 모니터링 결과를 제공하는 방식에도 한계가 있어요. 대부분의 당근 구성원들은 여러 개의 알림을 동시에 관리하는데, 슬랙 알림이나 알림 센터에서는 개별 알림 단위로 결과를 제공하기 때문이에요. 구성원들은 여전히 자신이 관리하는 여러 개의 알림들을 하나하나 확인해야 하죠. 번거로움이 완전히 해소되지는 않은 거예요. 따라서 개선이 필요한 알림들을 한눈에 확인할 수 있는 대시보드를 만들고 있어요. 대시보드가 제공되면 구성원들은 알림 센터에 접속 후 어떤 알림에 대해 무엇을 해야 하는지 직관적으로 파악하게 될 거예요.
마치며
지금까지 살펴본 ‘알림 신호등 프로젝트’를 통해 알림 경험팀은 앞으로 어떤 방향으로 나아가야 할지 확신할 수 있었어요. 저도 개인적으로 문제정의부터 해결책을 도출하고 팀원들을 설득하는 것까지, 여러 과정을 거치며 팀의 일원으로서 큰 성장을 이뤄낼 수도 있었고요.
알림 경험팀은 앞으로 단순한 플랫폼 조직이 아니라 서비스 조직으로서 당근 앱 사용자와 당근 구성원들의 알림 경험을 개선해 나갈 예정이에요. 부정적 알림 경험을 방지하는 것뿐만 아니라, 사용자에게 긍정적 알림 경험을 적극적으로 제공하기 위해 노력하려고 해요. 예를 들어 사용자에게 꼭 필요한 알림을 발굴하는 기능처럼 사용자가 실질적인 도움을 받을 수 있는 유의미한 알림을 제공하고자 해요.
당근 앱 사용자와 당근 구성원들의 알림 경험을 위해 치열하게 고민하는 저희 팀에 흥미가 생기셨다면, 알림 경험팀의 문은 항상 열려있어요!
아래 채용 공고를 통해 저희 팀에 합류할 수 있으니 많은 관심 부탁드려요! :)