본문 바로가기

10. 알림 시스템 설계 본문

ETC

10. 알림 시스템 설계

00rigin 2025. 4. 22. 01:22

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

  • 푸시 알림, SMS, 이메일 등 다양한 채널을 모두 지원해야 한다.
  • 실시간성을 유지하되 피크 시에는 약간의 지연을 허용하는 연성 실시간(soft real‑time) 시스템이어야 한다.
  • 사용자가 각 채널별 알림 설정을 켜고 끌 수 있도록 옵션을 제공해야 한다.
  • 하루 평균 1,000만 건의 푸시, 100만 건의 SMS, 500만 건의 이메일 처리량을 목표로 삼아야 한다.

2단계: 개략적 설계안 제시

2.1 알림 유형별 전송 경로

  • iOS 푸시: 서비스 → APNS → iOS 단말 토큰에 전달한다. (모바일.. 해볼일이 있으려나..)
  • Android 푸시: FCM(Firebase Cloud Messaging)을 통해 Android 단말에 전달한다.
  • SMS: 통신사(SKT, KT, LGU+)의 SMS 게이트웨이를 경유해 전송한다. (rpm은.. 어디꺼 쓰더라...)
  • 이메일: SendGrid, Mailchimp 또는 자체 SMTP 서버를 활용해 발송한다. (rpm은 SES 붙였었는데잉...)

2.2 연락처 정보 저장

  • 사용자 계정에 모바일 푸시 토큰, 전화번호, 이메일 주소를 저장한다.

  • 자주 참조되는 정보를 Redis 같은 캐시에 보관한다.

2.3 전송 흐름

  1. 서비스에서 Notification API로 알림 요청을 전송한다.
  2. Notification 서버가 페이로드를 생성한다.
    1. 알림 서버 : 전송 API 제공 / 알림 검증 / DB, cache 조회 / MQ로 보내기
    2. 캐시/DB : 정보 가져오겠죠? 캐시는 좀 더 자주 쓰이는거 가져오겠죠?
  3. 채널별 메시지 큐(FIFO)에 페이로드를 발행한다.
  4. 각 큐의 작업 서버가 메시지를 꺼내 제3자 API(APNS/FCM/SMS/이메일)를 호출한다.

Notification 서버, DB, 캐시, 큐, 작업 서버를 모두 수평 확장해 SPOF를 제거 해야 한다!

 

3단계: 상세 설계

3.1 안정성

데이터 손실 방지 및 재시도

  • 모든 알림 요청을 DB에 기록해 소실을 방지한다.
  • 전송 실패 시 재시도 전용 큐에 넣고, 재시도 횟수를 관리하며 반복 처리한다.
  • 이벤트 ID를 이용한 Bloom 필터와 DB 조회로 중복 전송을 방지한다.... 하지만!
더보기

1. 정확히 한 번 전송의 불가능성

Two Generals 문제

  • 분산 시스템의 불완전한 통신 특성을 보여 주는 Two Generals’ Problem에 따르면, 메시지 손실 또는 인지 여부의 불확실성 때문에 단 한 번만, 정확히 한 번 메시지를 전달했다는 상호 확신을 가질 수 없다.
  • 이 사고 실험은 “마지막 메시지가 성공적으로 도달했을 때 이를 알릴 방법이 없으면 합의가 불가능하다”는 역설을 증명하며, exactly‑once 보장 자체가 불가능함을 보인다.

2. 실무에서의 중복 방지 대체 기법

At‑Least‑Once + Idempotency

  • 대부분 시스템은 at‑least‑once 전송을 채택하고, 중복 수신 시 영향을 무효화하는 멱등성(idempotent) 처리를 병행한다.
  • 멱등성 처리: “같은 메시지가 여러 번 적용되어도 최종 상태가 한 번처럼 유지”되도록 설계하는 방식이다.

Deduplication (근사적 중복 제거)

  • Bloom 필터 → DB 조회 순으로 초기 필터링하여 중복 메시지일 가능성을 빠르게 배제하고, 이후 DB에서 확정적으로 확인하는 2단계 검사 방식을 적용한다.
  • 이 방식은 “100% 확실한 제거”가 아니라, 확률적 필터+정확 검증으로 중복 전송을 극히 낮추는 근사 해법이다.

3. 재시도 메커니즘 및 한계

재시도 큐(Re‑try Queue)

  • 전송 실패 시 전용 재시도 큐에 쌓아두고, 재시도 횟수와 지연 정책을 관리하며 반복 전송을 시도한다.
  • 그러나 네트워크 단절, 서비스 장애, 레이스 컨디션 등 예외 상황이 복합될 경우, 동일 메시지 재전송 가능성을 완전히 배제할 수 없다.

Exactly‑Once vs. Exactly‑Once Processing

  • “Exactly‑once delivery”는 메시지 전송 횟수를, “Exactly‑once processing”은 부작용(side‑effects)을 한 번만 발생시키는 것을 의미
  • 실무에서는 부작용 제어를 통해 중복 영향만 제거하고, 순수 전송 횟수 자체는 at‑least‑once로 남겨두는 것이 일반적이다.

결론

  • 분산 시스템에서 “100% 중복 전송 방지(Exactly‑once delivery)”는 이론적으로 불가능하다.
  • 대신 at‑least‑once + idempotent 또는 Bloom 필터+DB 조회 같은 다단계 중복 검사, 그리고 재시도 큐로 실패를 처리하는 근사적 설계로 실용적 신뢰성을 확보해야 한다.

 

3.2 추가 컴포넌트

사용자별 설정 및 속도 제한

  • 채널·유형별 알림 설정 테이블로 전송 전 필터링을 수행한다.
  • Rate Limiting을 적용해 사용자 및 시스템 전체의 전송 속도를 제한한다.

모니터링 및 오토스케일링

  • 각 큐의 길이를 모니터링 지표로 삼아 작업 서버 수를 동적으로 조정한다.
  • 재시도 큐 오류 누적 시 운영팀에 알림을 발송한다.

4. 완성

'ETC' 카테고리의 다른 글

9. 웹 크롤러 설계  (0) 2025.04.22
Closure Table을 이용한 File Authority 적용기  (0) 2025.03.17
RDBMS 에서 tree structure 다루기  (0) 2025.03.17
[Java] StringBuilder 주요 메소드  (0) 2025.01.21
Cursor AI 사용기  (9) 2024.11.07
Comments