[아키텍처] Redis Pub/Sub을 활용한 분산 서버 실시간 동기화 완벽 가이드

1. 문제

사용자가 늘어나 채팅/화상 서버를 여러 대(Scale-out)로 늘렸더니, 다른 서버에 접속한 유저끼리는 메시지를 주고받지 못하는 치명적인 단절 현상이 발생했습니다.
예를 들어 A 서버에 접속한 유저가 보낸 채팅을, B 서버에 할당된 유저가 실시간으로 수신할 연결고리가 물리적으로 끊어져 있기 때문입니다.

2. 왜 필요한가

수십 대의 분산 서버가 마치 하나의 거대한 통형 서버처럼 유기적으로 동작하려면, 모든 서버를 0.01초 만에 연결해 주는 초고속 중앙 허브(Message Hub)가 반드시 필요합니다.
단순히 DB를 거치는 방식은 디스크 I/O 속도 한계로 실시간성을 잃어버리며, 각 서버끼리 직접 통신하는 방식은 서버가 늘어날수록 시스템 구조를 붕괴시킵니다.

3. 기대효과

Redis Pub/Sub 메커니즘을 도입하면, 서버가 1대이든 100대이든 상관없이 10밀리초(ms) 이하의 초고속으로 전 서버에 메시지를 즉각 브로드캐스팅할 수 있습니다.
이로 인해 접속량이 폭주하여 서버를 긴급 증설하더라도 코드를 단 한 줄도 고칠 필요가 없는 완벽한 수평 확장(Scale-out)이 가능해집니다.

4. 구현 방향

초고속 인메모리(In-Memory) 데이터베이스인 Redis를 메시지 버스(Message Bus)로 사용하여, 송신자는 채널에 메시지를 ‘발행(Publish)’하고, 각 서버들은 이를 ‘구독(Subscribe)’하여 자기 클라이언트에게 쏴주도록 설계합니다.
아래는 Spring Boot 애플리케이션이 Redis 채널을 구독하여, 넘어온 메시지를 각자의 로컬 웹소켓 유저들에게 분배하는 핵심 로직입니다.


@Service
@RequiredArgsConstructor
public class RedisMessageSubscriber implements MessageListener {
    
    private final WebSocketService webSocketService;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 1. Redis 채널로부터 타 서버에서 보낸 메시지 수신
        String payload = new String(message.getBody());
        
        // 2. 현재 이 서버 노드에 연결된 유저들에게 실시간 웹소켓 전송
        webSocketService.broadcastToLocalClients(payload);
        
        log.info("Distributed real-time message processed: {}", payload);
    }
}

5. 비즈니스 가치

‘접속자 폭주 시 서버가 터진다’는 막연한 불안감 없이, 마케팅 이벤트나 트래픽 급증 시 언제든 안심하고 서버 인프라를 무한대로 늘릴 수 있는 완벽한 확장성(Scalability)을 달성합니다.
단 한 건의 알림 유실도, 1초의 지연도 허용하지 않는 압도적인 인프라 안정성은 곧 고객의 강력한 신뢰도 상승과 서비스 이탈률 제로(0%)로 직결됩니다.

댓글 남기기