프로젝트에서 알림 기능을 구현하는 와중에 RabbitMQ 라는 메시지큐를 사용했던 경험이 있다.
당시, FCM(Firebase Cloud Messaging)을 활용한 서버PUSH 알림기능을 구현하고 있는 상황이었다. NFT거래 체험 서비스였기에 알림설정한 NFT에 이벤트가 발생하면 알림이 가도록 구현하는 것이 목적이었다.
문제는 요청-응답에 걸리는 시간에 있었다.
A라는 요청-응답 흐름이 있다고 가정했을 때, A요청에 의해 알림기능이 트리거되고 이를 처리하는 과정에서 A응답시간이 길어지는 문제가 생긴 것이다. 즉, 알림기능을 추가함으로써 기존의 요청-응답시간에 영향을 끼치는 일이 발생했다.
당시 기억으로 그렇다면 알림 기능을 요청-응답흐름과 분리하면 어떨까?
라는 생각을 가지고 메시지 큐를 도입했었다.
알림 발생!
이라는 이벤트를 발생시키고 응답과 별개의 동작흐름이 되도록, 즉 비동기가 되도록 구성하려고 시도했었다.
하지만, 나는 메시지 큐에대해 잘 모르는 상황이었기 때문에 어찌어찌 구성은 했지만 어디가서 자랑스럽게 나 메시지 큐 뭔지 암!
이라고 할 수는 없는 겉멋(?)이 든 경험만 하게되었다.
그래서 이번 포스팅을 통해 메시지큐에 대해 살펴보고 나름대로의 정리를 진행해볼 생각이다.
메시지 큐는 명칭 그대로 Message
에 대한 Queue
기능을 수행한다.
그렇다면 여기서 말하는 Message
란 무엇일까?
이때 사용되는 메시지라는 표현은 일련의 데이터를 의미한다. 파일, 객체, 텍스트 등 여러가지 유형의 데이터들이 올 수 있다.
메시지 큐는 이러한 메시지들을 Queue의 방식(선입선출)으로 주고받는데 사용되는 대기열이라고 볼 수 있다.
왜 데이터를 Message Queue 라는 수단을 이용해서 주고받는걸까?
만약 A, B 서비스가 존재한다고 가정했을때, 그냥 request 하면 안되는걸까?일단 기본적으로
request
는response
를 필요로 한다.
별도의 비동기수단을 사용하지 않을경우, 요청을 보낸쪽은 응답이 올때까지 작업이 중지된다. 즉, 작업효율이 떨어진다는 의미다.
뿐만아니라, 데이터가 중간에 소실될 위험도 있다. 요청 중간에 네트워크 문제와 같은 특정 문제가 발생한다면 데이터는 그대로 소실될 위험이 있다.
메시지 큐를 이용하게되면 이러한 작업 효율과 데이터 손실 문제를 해결할 수 있다.
비동기로 동작하므로 작업효율이 높아지며, 디스크를 통해 데이터를 저장하기 때문에 데이터가 소실될 위험도 줄어든다. 이 외에도 메시지를 받을 수 있는 대상을 손쉽게 확장할 수 있고, 서비스간의 느슨한 연결을 만들어준다는 장점도 있다.
대략적인 개념과 용도에 대해서 알아봤으니 어떻게 구성되어 있는지를 살펴보자
메시지 큐의 동작에는 발행자와 구독자가 존재한다.
발행자는 메시지를 큐에 Enqueue 하는 주체를 뜻하며,
구독자는 큐에서 Dequeue된 메시지를 소비하는 주체를 뜻한다.
메시지 큐의 역할은 발행자에게서 구독자에게로 메시지를 전달하는 것이며, 그 사이에서 메시지의 버퍼역할도 수행한다. 즉, 이메일과 유사하다고 볼 수 있다.
간단한 유형의 메시지 큐는 발행자가 큐에 메시지를 보내면,
소비자가 원하는 때에 큐에서 메시지를 확인하고 해당 메시지가 큐에서 제거되는 형식이다.
아이디어 자체는 간단하지만, 발행된 메시지는 다수의 소비자가 존재할 수 있음을 생각해봐야한다.
따라서, 메시지를 전달을 위해서는 중개자가 필요하며, 이를 Message Broker라 부른다.
메시지 브로커는 메시지의 라우팅, 저장, 전달을 효율적으로 관리하는데 사용된다.
대표적인 메시지 브로커로는 RabbitMQ가 있다.
소비자의 메시지 처리확인을 처리하고, 문제상황에선 DLQ(Dead Letter Queue) 에 메시지를 저장하거나 재시도를 수행한다.
메시지 브로커가 없는 메시지큐도 있다 ( ex : ZeroMQ )
이 유형은 메시지 큐에 새로운 메시지가 게시되었을 때, 이를 구독하고 있는 구독자에게 라우팅되는 형식을 띈다.
이 구조를 띄기 위해서는 구독자마다 자신의 큐를 가지고 있어야한다.
하나의 큐를 사용하는 경우에는 메시지가 소비되어 사라지기 때문이다.
이러한 게시와 구독의 형태에서 특정 상태변화나 발생 사건을 알리는 정보를 이벤트라 부른다.
이러한 이벤트들을 효율적으로 관리하는 역할로 Event Broker가 존재한다.
이벤트 브로커는 이벤트의 순서 보장과 이벤트 데이터의 영구저장을 통해 안정성과 신뢰성을 높인다.대표적인 이벤트 브로커로는 Apache Kafka가 있다.
메시지 브로커는 서비스간 메시지 전달 중개에 초점이 맞춰져있고,
이벤트 브로커는 이벤트 발행과 구독 관리에 초점이 맞춰져있다.
메시지 브로커는 정보, 데이터의 전달 중개를 주 목적으로 삼는다.
주요 특징으론, 특정 소비자가 메시지를 소비하면 해당 메시지는 큐에서 사라진다.
반면 이벤트 브로커는 상태변화(이벤트)의 발생과 구독관리를 주 목적으로 삼는다.
메시지 브로커의 역할을 수행할 수 있지만, 한번 소비된 이벤트가 사라지지 않는다. 여러 구독자가 이벤트를 소비할 수 있기때문에 디스크에 저장된 데이터가 사라지지 않는다.
주요 차이점 중 하나는 메시지 혹은 이벤트가 영구적인가?
이다.
메시지 브로커는 메시지가 소비되는 순간 사라지기 때문에 단기적인 명령이나 작업 중심의 처리에 적합하다. 예를들어, 애플리케이션내의 신규 변경사항이 한번 반영되고 더이상 필요하지 않은 경우에 사용할 수 있다.
반면, 이벤트 브로커는 이벤트가 사라지지 않으므로 현재 혹은 과거 이벤트를 다루는 상황에서 더 적합하다. 예를들어, 기존 시스템을 변경하지않고 저장된 대량의 데이터를 이용한 신규 서비스를 구현하는 상황에서 사용할 수 있다.
여러모로 부족함이 많은 포스팅이다.
좀 더 자세한 내용과 차이점에 대해서는 아래 참고했던 사이트, 그리고 다른 포스팅들을 충분히 찾아보는걸 추천한다