일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 웹개발
- springboot
- Yes
- 자료구조
- 데이터베이스
- 빅데이터
- 컴퓨터공학
- 머신러닝
- 딥러닝
- 데이터구조
- I'm Sorry
- 자바스크립트
- 인공지능
- 컴퓨터과학
- 사이버보안
- 컴퓨터비전
- 보안
- 디자인패턴
- 파이썬
- 프로그래밍
- 데이터과학
- 프로그래밍언어
- 데이터분석
- 클라우드컴퓨팅
- 네트워크보안
- 소프트웨어공학
- 알고리즘
- 소프트웨어
- 버전관리
- 네트워크
- Today
- Total
스택큐힙리스트
Redis Pub/Sub로 5초 만에 터지는 알림, 멀티 인스턴스에서도 놓치지 않는 비결 본문
대규모 서비스가 두 세 대를 넘어 수십 대로 늘어나면, 알림 시스템이 가장 먼저 삐걱댑니다. 인스턴스 A에서 새 댓글이 등록됐는데 B에 붙어 있는 사용자는 아무 소식이 없거나, 같은 알림이 두 번씩 날아오곤 하죠. 분산 Observer 패턴을 Redis Pub/Sub로 풀면, 서버 수가 늘어나도 “한 번만, 정확히” 알림을 전송할 수 있습니다.
1) Pub/Sub가 Observer를 분산으로 확장하는 방법
Redis의 채널(topic)에 메시지를 Publish하면, 채널을 구독(Subscribe)한 모든 인스턴스가 동시에 이벤트를 받아옵니다. “발행자–구독자” 모델이니 Subject ↔ Observer 의존성이 사라져, 서버가 몇 대든 ‘알림 복제본’을 걱정할 필요가 없습니다.
2) 기본 흐름 한 줄 요약
Controller → Service → RedisTemplate.convertAndSend() Publish →
RedisMessageListenerContainer Subscribe →
알림 Push(SSE·WebSocket 등) → 사용자 단말.
Spring Boot에서는 MessageListenerAdapter로 리스너를 등록해 두고, JSON 페이로드만 직렬화해 쏘면 끝입니다. 실시간성이 필요한 채팅·알림·작업 큐에서 검증된 패턴으로, 이미 많은 국내 블로거들이 “SSE + Redis Pub/Sub” 조합으로 비용 대비 최고 효율을 얻었다고 소개합니다.
3) 멀티 인스턴스에서도 한 사람에게만 전송되게 하려면?
SSE 연결 정보(session)는 각 인스턴스 메모리에 저장돼 있어서, 발행 서버와 구독 서버가 다르면 알림이 공중으로 사라집니다. Redis를 브로드캐스트 허브로 두면 모든 서버가 같은 메시지를 받고, 연결을 잡고 있는 서버만 최종 전송을 수행하므로 누락 없이 전달됩니다.
4) 채널 설계 꿀팁 3가지
- 1인 1채널: user:{id}처럼 개인 채널을 만들면 보안·필터링이 편해집니다.
- 주제별 채널: post:{boardId} 같이 관심사 단위로 묶어 트래픽을 절약.
- 패턴 구독: pSubscribe("user:*") 로 모니터링·테스트 채널을 따로 둡니다.
5) 코드 스니펫–Publish/Subscribe 핵심만
// Publisher
fun notifyNewComment(event: CommentEvent) {
redisTemplate.convertAndSend("user:${event.receiverId}", event)
}
// Subscriber
@Component
class AlarmSubscriber(
private val emitterRepo: SseEmitterRepository // SSE 연결 풀
) : MessageListener {
override fun onMessage(msg: Message, pattern: ByteArray?) {
val event = objectMapper.readValue(msg.body, CommentEvent::class.java)
emitterRepo.emit(event.receiverId, event) // 해당 사용자에게만 push
}
}
6) 안정성을 높이는 보강 장치
- 메시지 손실 방지: Redis는 휘발성이라 장애 복구 시 메시지가 사라집니다. 중요 알림이면 Streams나 Kafka로 ‘저장형’ 브로커를 섞어 백업하세요.
- 팬아웃 폭주: 구독자 수가 많을수록 발송 루프가 길어집니다. Executors.newFixedThreadPool()로 비즈니스 스레드와 분리하면 TPS가 안정됩니다.
- 모니터링: redis-cli MONITOR 대신 INFO PubSub와 Grafana 대시보드로 채널·구독자 수를 실시간 확인하세요.
7) 이렇게 달라진다
- 서버가 N대여도 알림 로직은 단일 코드 → 배포·확장 부담 최소화
- 트래픽 급증 시 Redis 클러스터만 스케일아웃 → CPU·메모리 예측이 쉬움
- 코드 테스트도 간단: EmbeddedRedis + Awaitility로 발행–수신 시나리오를 단위 테스트 가능
'개발' 카테고리의 다른 글
SSE vs WebSocket, 언제 써야 빛을 볼까? (4) | 2025.07.22 |
---|---|
Redis Streams vs Pub/Sub: 저장형 알림 설계, 무엇을 써야 할까? (3) | 2025.07.22 |
setState vs Provider, 무엇이 다를까? (0) | 2025.07.22 |
“구독 · 알림 · 자동 반응” — Observer 패턴 한눈에 이해하기 (1) | 2025.07.22 |
함수 타입 vs 클래스 구현 – Kotlin Strategy 패턴 성능 벤치마크 실험기 (3) | 2025.07.22 |