Search

10장. 알림 시스템 설계

생성일
2025/08/17 12:18
태그

개요

알림 시스템(notification system)은 최신 뉴스나 제품 업데이트, 이벤트, 선물 등 고객에게 중요할만한 정보를 비동기적으로 제공하는 시스템을 말한다. 단순히 모바일 푸시 알림(mobile push notification) 뿐만 아니라, SMS 메세지, 이메일 3가지로 분류 할 수 있다.

1단계 문제 이해 및 설계 범위 확정

하루에 백만 건 이상의 알림 시스템을 처리하는 확장성 높은 시스템을 구축하는 것은 어려운 일이며, 알림 시스템이 어떻게 구현되는지에 대한 깊은 이해가 필요한 작업이다. 보통 정답이 없으니, 적절한 질문을 통해 요구사항을 명확히 하는 것이 중요하다.
지원자: 이 시스템은 어떤 종류의 알림을 지원해야 하나요? 면접관: 푸시 알림, SMS 메세지, 이메일입니다. 지원자: 실시간(real-time) 시스템이어야 하나요? 면접관: 연성 실시간(soft real-time) 시스템이라고 가정합시다. 알림은 가능한 빨리 전달되어야하지만 시스템에 높은 부하가 걸렸을 때 약간의 지연은 무방합니다. 지원자: 어떤 종류의 단말을 지원해야 하나요? 면접관: iOS 단말, 안드로이드(android) 단말, 그리고 랩톱/데스크톱을 지원해야 합니다. 지원자: 사용자에게 보낼 알림은 누가 만들 수 있나요? 면접관: 클라이언트 애플리케이션 프로그램이 만들 수도 있고, 서버 측에서 스케줄링 할 수도 있습니다. 지원자: 사용자가 알림을 받지 않도록(opt-out) 설정할 수도 있어야 하나요? 면접관: 네. 해당 설정을 마친 사용자는 더 이상 알림을 받지 않습니다. 지원자: 하루에 몇 건의 알림을 보낼 수 있어야 하나요? 면접관: 천만 건의 모바일 푸시 알림, 백만 건의 SMS 메세지, 5백만 건의 이메일을 보낼 수 있어야 합니다.
Plain Text
복사

2단계 개략적 설계안 제시 및 동의 구하기

iOS 푸시 알림, 안드로이드 푸시 알림, SMS 메시지, 이메일을 지원하는 알림 시스템의 개략적 설계안을 살펴보자. 다음과 같은 내용을 다룰 것이다.

알림 유형별 지원 방안

우선 각각의 알림 메커니즘 동작에 대해 알아보자.

iOS 푸시 알림

iOS에서 푸시 알림을 보내기 위해서는 세 가지 컴포넌트가 필요하다.
알림 제공자(provider) : 알림 요청을 만들어 애플 푸시 알림 서비스로 보내는 주체이다. 다음과 같은 데이터를 담아서 보낸다.
단말 토큰(device token) : 알림 요청을 보내는데 필요한 고유 식별자
페이로드(payload) : 알림 내용을 담은 JSON 딕셔너리
{ "aps": { "alert": { "title": "Game Request", "body": "Bob wants to play chess", "action-loc-key": "PLAY" }, "badge": 5 } }
JSON
복사
APNS(Apple Push Notification Service) : 애플이 제공하는 원격 서비스로, 푸시 알림을 iOS 장치로 보내는 역할을 담당한다.
iOS 단말(device) : 푸시 알림을 수신하는 사용자 단말이다.

안드로이드 푸시 알림

안드로이드 푸시 알림도 APNS 대신 FCM(Firebase Cloud Messaging)을 사용한다는 점만 다르고 비슷한 절차로 전송된다.

SMS 메세지

SMS 메세지를 보낼 때는 보통 트윌리오(Twilo), 넥스모(Nexmo) 같은 제3사업자의 서비스를 이용한다. 이런 서비스는 대부분 상용 서비스라서 이용요금을 내야한다.

이메일

대부분의 회사는 고유 이메일 서버를 구축할 역량을 갖추고 있다. 그럼에도 전송 성공률이나 데이터 분석 서비스를 제공하기 때문에 많은 회사가 센드그리드(Sendgrid), 메일침프(Mailchimp) 같은 상용 이메일 서비스를 이용한다.

통합 시스템

연락처 정보 수집 절차

알림을 보내기 위해서는 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요하다.
위 그림처럼 사용자가 앱을 설치하거나 처음 계정을 등록할 때, 해당 사용자의 정보를 서버에서 수집하여 데이터베이스에 저장한다.
위처럼 데이터베이스에 연락처를 저장할 때, 이메일 주소와 전화번호는 user 테이블에 저장하고 단말 토큰은 device 테이블에 저장한다. 사용자가 여러 단말을 가질 수 있고, 알림은 모든 단말에 전송되어야 하는 점을 고려했다.

알림 전송 및 수신 절차

개략적 설계안 (초안)

서비스 1 … 서비스 N : 마이크로 서비스 혹은 크론잡(cronjob) 등 분산 시스템 컴포넌트. 사용자에게 납기일을 알리는 과금 서비스나 배송 알림을 보내는 쇼핑몰가 예시이다.
알림 시스템 : 알림 시스템은 알림 전송/수신 처리의 핵심이다. 1개의 서버만 사용하는 시스템이라고 가정하면, 서비스1~N에 알림 전송을 위한 API를 제공해야하고 제3서비스에 전달할 알림 페이로드를 만들어 내야한다.
제3자 서비스(thrid party service) : 사용자에게 알림을 실제로 전달하는 역할을 하는 제3자 제공 서비스. 제3자 서비스를 통합할 때, 쉽게 새로운 서비스를 통합하거나 기존 서비스를 제거할 수 있도록 확장성에 유의해야한다. 또한 FCM은 중국에서 사용할 수 없는 것처럼 여러 환경도 고려해야한다.
위 설계에는 몇 가지 문제가 있다.
SPOF(Single-Point of Failure) : 알림 서비스 서버가 한 대밖에 없어, 해당 서버의 장애가 전체 서비스의 장애로 이어질 수 있다.
규모 확장성 : 한 대의 서비스로 푸시 알림에 관계된 모든 것을 처리하므로, 데이터베이스나 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 방법이 없다.
성능 병목 : 알림을 처리하고 보내는 것은 자원을 많이 필요로 하는 작업일 수 있다. 따라서 모든 것을 한 대의 서버로 처리하면 사용자 트래픽이 많이 몰리는 시간에 시스템 과부하 상태에 빠질 수 있다.

개선된 개략적 설계안

초안의 문제점을 개선해보자.
데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리한다.
알림 서버를 증설하고 auto scale-out이 가능하게 만든다.
메세지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊는다.
위 개선점을 반영한 새로운 시스템 설계를 자세히 살펴보자.
알림 서버 기능 :
알림 전송 API : 스팸 방지를 위해 사내 서비스 혹은 인증된 클라이언트만 이용 가능하도록 한다.
알림 검증 : 이메일 주소, 전화번호 등에 대한 기본적인 검증을 수행한다.
데이터베이스/캐시 쿼리 : 알림에 포함시킬 데이터를 데이터베이스나 캐시에서 가져온다.
알림 전송 : 알람 데이터를 각 메세지 큐에 넣어 알림을 병렬적으로 처리한다.
캐시 : 사용자 정보, 단말 정보, 알림 템플릿(templage) 등을 캐시한다.
데이터베이스 : 사용자, 알림, 설정 등 다양한 정보를 저장한다.
메세지 큐 : 시스템 컴포넌트 간 의존성을 제거하고, 다양한 알림이 전송되어야하는 경우를 대비한 버퍼 역할을 한다. 위 설계처럼 알림 종류별 메세지 큐를 따로 두는 경우 제3자 서비스 중 하나에 장애가 발생해도 다른 종류의 알림은 정상 동작한다.
작업 서버 : 메세지 큐에서 전송할 알림을 꺼내 제3자 서비스로 전달한다.
위 컴포넌트들이 협력하여 다음과 같은 순서로 알림을 전송한다.
1.
API를 호출하여 알림 서버로 알림을 보낸다.
2.
알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터를 캐시나 데이터베이스에서 가져온다.
3.
알림 서버는 전송할 알림에 맞는 이벤트를 만들어 메세지 큐에 넣는다.
4.
작업 서버가 메세지 큐에서 알림 이벤트를 꺼내 제3자 서비스로 보낸다.
5.
제3자 서비스에서 사용자 단말로 알림을 전송한다.

3단계 상세 설계

상세 설계에서는 서비스의 안정성이나 추가로 필요한 컴포넌트, 고려사항 등을 알아보고 설계를 한 번 더 개선해보자.

안정성

분산 환경에서 시스템을 설계할 때는 안정성을 확보하기 위해 몇 가지 사항들을 반드시 고려해야한다.

데이터 손실 방지

알림 전송 시스템에서 가장 중요한 요구사항 중 하나는 알림이 지연되거나 순서가 틀려도 괜찮지만 어떤 상황에서도 알림이 소실되면 안된다는 것이다. 이 요구사항을 만족하려면 알림 시스템은 알림을 데이터베이스에 보관하고 재시도 메커니즘을 구현해야한다.

알림 중복 전송 방지

대부분의 알림은 딱 한 번만 전송되겠지만, 분산 시스템의 특성상 같은 알림이 여러 번 반복되는 것을 완전히 막는 것은 불가능하다. 그 빈도를 줄이려면 중복을 탐지하는 메커니즘을 도입하고 오류를 신중하게 처리해야 한다.
다음은 간단한 중복 방지 로직의 사례이다.
보내야 할 알림이 도착하면 그 이벤트 ID를 검사하여 이전에 본 적이 있는 이벤트인지 확인하여, 중복인 경우 버리고 중복이 아니라면 알림을 발송한다.

추가로 필요한 컴포넌트 및 고려사항

사실 알림 시스템은 우리가 위에서 설계한 것보다 훨씬 복잡하다. 알림 템플릿, 알림 설정, 이벤트 추적, 시스템 모니터링, 처리율 제한 등 알림 시스템 구현을 위해 필요한 추가 컴포넌트들에 대해 알아보자.

알림 템플릿

대형 알림 시스템은 하루에 수백만 건 이상의 알림을 처리하는데, 그 대부분의 알림 메세지는 형식이 비슷하다. 이런 유사성을 고려하여 알림 메세지의 모든 부분을 처음부터 만들 필요가 없도록 알림 템플릿을 사용한다.
알림 템플릿은 인자(parameter)나 스타일, 추적 링크(tracking link)를 조정하기만 하면 사전에 지정한 형식에 맞춰 알림을 만들어내는 거푸집이다.
여러분이 꿈꿔온 그 상품을 우리가 준비했습니다. [item_name이 다시 입고 되었습니다! [date까지만 주문 가능합니다! 타이틀(CTA: Call to Action): 지금 [item_name]을 주문 또는 예약하세요!
JSON
복사
위처럼 알림 템플릿을 사용하면, 알림들의 형식을 일관성 있게 유지할 수 있고 오류 가능성뿐 아니라 알림 작성에 드는 시간도 줄일 수 있다.

알림 설정

사용자는 너무 많은 알림을 받게 되면 쉽게 피곤함을 느끼기 때문에, 많은 웹사이트나 앱에서 사용자가 알림 설정을 상세히 조정할 수 있도록 한다. 이 정보는 다음과 같이 알림 설정 테이블에 보관된다.
user_id bigInt channel varchar # 알림이 전송될 채널(푸시 알림, 이메일, SMS 등) opt_in boolean # 해당 채널로 알림을 받을 것인지 여부
SQL
복사
이처럼 알림 설정을 도입한 뒤에는, 알림을 보내기 전에 반드시 해당 사용자가 알림을 켜두었는지 확인해야한다.

전송률 제한

알림을 너무 많이 보내기 시작하면 사용자가 알림 기능을 아예 꺼버릴 수도 있다. 이를 피하기 위해 사용자에게 너무 많은 알림을 보내지 않도록하는 한 가지 방법은, 한 사용자가 받을 수 있는 알림의 빈도를 제한하는 것이다.

재시도 방법

제3자 서비스가 알림 전송에 실패하면, 해당 알림을 재시도 전용 큐에 넣어 다시 알림이 보내질 수 있도록 한다.
같은 문제가 계속해서 발생한다면 개발자에게 통지한다(alert).

푸시 알림과 보안

iOS와 안드로이드 앱의 경우, 알림 전송 API는 appKey와 appSecret을 사용하여 보안을 유지한다. 따라서 인증되거나(authenticated) 승인된(verified) 클라이언트만 해당 API를 통해 알림을 보낼 수 있다.

큐 모니터링

알림 시스템을 모니터링 할 때는 큐에 쌓인 알림의 개수를 수집하는 것이 중요하다.
위처럼 쌓인 알림이 너무 많다면 작업 서버들이 이벤트를 빠르게 처리하지 못하고 있다는 의미이기 때문에, 병목 지점을 개선하거나 작업 서버를 증설하는 것이 바람직할 것이다.

이벤트 추적

알림 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 같은 메트릭은 사용자를 이해하는데 중요한 지표이다. 데이터 분석 서비스는 보통 이벤트 추적 기능도 제공하기 때문에, 보통 알림 시스템을 만들 때 분석 서비스와도 통합해야 한다.
위는 데이터 분석 석비스를 통해 추적하게 될 알림 시스템 이벤트의 사례이다.

수정된 설계안

추가된 컴포넌트는 다음과 같다.
알림 서버에 인증과 전송률 제한(rate-limiting) 기능 추가
전송 실패를 대응하기 위한 재시도 기능 추가(실패 시 지정된 횟수만큼 재시도)
전송 템플릿을 사용해 알림 생성 과정을 단순화, 알림 내용의 일관성 유지
시스템 상태 확인 및 추후 시스템 개선을 쉽도록 모니터링과 추적 시스템을 추가

4단계 마무리

이번 장을 통해 규모 확장이 쉬우면서도 푸시 알림, SMS 메세지, 이메일 등 다양한 정보 전달 방식을 지원하는 알림 시스템을 설계해 보았다. 추가적으로 아래와 같은 여러 기능에 대해서도 설계해보았다.
안정성 : 메세지 전송 실패율을 낮추기 위해 안정적인 재시도 메커니즘 도입
보안 : 인증된 클라이언트만 알림을 보낼 수 있도록 appKey, appSecret 메커니즘 추가
이벤트 추적 및 모니터링 : 알림이 만들어진 후 전송되기까지 과정을 추적, 각 단계마다 이벤트 추적 및 시스템 상태 모니터링
사용자 설정 : 사용자가 알림 수신을 조정할 수 있고, 알림 전송 전 사용자의 알림 설정 여부 확인
전송률 제한 : 사용자에게 알림을 보내는 빈도를 제한