비동기 통신과 확장성이 중요해진 요즘의 개발에서, 다양한 메시지 브로커가 존재한다.
메시지 브로커는 메시지(데이터)를 송신자(생산자)로부터 수신자(소비자)에게 전달하는 중간 매개체 역할을 하는 소프트웨어이다.
이에 대한 구체적인 내용은 넘어가고 전반적인 흐름만 짚고 넘어가자!
생산자(Producer): 메시지를 생성하여 메시지 브로커에게 보내는 역할
소비자(Consumer): 메시지 브로커로부터 메시지를 수신하고 처리하는 역할
메시지 큐(Message Queue): 생산자가 보낸 메시지가 저장되는 임시 저장소로, 소비자는 이 큐에서 메시지를 가져와 처리하며, 이는 순서대로 쌓이고 순서대로 나간다. 이를 통해 생산자와 소비자의 속도 차이를 조절하고, 메시지 유실을 방지한다.

메시지 브로커가 없다면, 애플리케이션들은 서로 직접 통신을 해야하고, 이는 동시성의 문제를 직면하거나, 서비스의 부하나 MSA와 같은 구조가 많아지는 요즘의 개발에 여러 문제를 직면할 수 있다.
메시지 브로커의 장점을 다음과 같이 정리할 수 있다.
비동기 통신: 생산자가 메시지를 보내고 즉시 다른 작업에 들어갈 수 있다. 생산자의 입장에서는 메시지 발행 여부만 중요하고, 소비자는 메시지를 나중에 처리한다.
느슨한 결합(Loose Coupling): 생산자와 소비자가 서로를 알 필요 없이 메시지 브로커를 통해 독립적으로 통신이 가능하다.
확장성: 새로운 소비자를 쉽게 추가하여 메시지 처리량 늘리기에 좋다. (소비자 그룹으로 처리하기 때문)
내구성 및 신뢰성: 메시지를 큐에 저장하여 소비자가 메시지를 성공적으로 처리할 때까지 보존하므로, 데이터 유실에 있어서 안정적이다.
이런 메시지 브로커로 대표적인 것에는
RabbitMQ, Kafka, Redis 등이 존재하는데,
이번에는 메시지 브로커로서의 Redis에 대하여 알아볼 것이다.
Redis는 인메모리(In-Memory) 기반 데이터 저장소로서, 속도가 빠르다는 장점을 갖고 있다.

이미지 출처: https://blog.bytebytego.com/p/a-crash-course-in-redis
그리고 데이터의 안전한 보관과 백업을 위해 다른 서버의 메모리에 실시간으로 복사본을 남길 수 있고, 디스크에 저장하는 방법도 제공하는 등 확장성이 높다.

기본적으로 key-value 저장 방식이지만, Lists, Sets, Sorted Sets, Hashes, Streams 같은 다양한 저장 방식을 제공하여 다양한 방식으로 데이터를 활용이 가능하다는 점이 큰 특징이다!

레디스 Pub/Sub은 발행-구독 모델을 구현하는 가장 기본적이고 단순한 모델이다.
메시지 발행자(Publisher)는 특정 채널(Channel)에 메시지를 보내고,
구독자(Subscriber)는 해당 채널을 구독해 메시지를 수신한다.

레디스 List는 선입선출(FIFO) 구조의 큐(Queue)로 사용될 수 있다.
Lists는 key와 value가 1:N(일대다) 관계로,
value는 입력된 순서대로 저장된다. value 위주로 작동하기에, value가 있으면 키(리스트)가 생성되고, value가 전부 삭제되면 키(리스트)도 알아서 삭제되므로, 별도의 작업이 필요가 없다.
Lists는 주로 큐(Queue)와 스택(Stack)으로 사용된다.
큐(Queue)는 들어오는 데이터를 순서대로 처리할때 사용되며,
스택(Stack)은 웹브라우져의 백버튼 처럼 주로 되돌아 갈때 사용된다.
LPUSH/RPUSH 명령어로 리스트의 앞/뒤에 메시지를 넣고, LPOP/RPOP 명령어로 메시지를 가져오는 방식으로 구현
블로킹 큐를 구현하기 위해 BLPOP/BRPOP 명령어를 사용하면, 메시지가 들어올 때까지 대기할 수 있다.

Redis Stream은 레디스 5.0 버전부터 도입된, 메시지 큐를 위한 가장 진보된 자료구조이다.
메시지 그룹(Consumer Group), 메시지 ID, 메시지 확인(ACK) 등 복잡한 메시징 시스템을 구현하는 데 필요한 기능을 제공하는 등 전형적인 메시지 브로커의 특징을 갖고있다.
REF